raw
smg_comms_c_wrappers    1 /* mpicoder.c  -  Coder for the external representation of MPIs
smg_comms_c_wrappers 2 * Modified by No Such Labs. (C) 2015. See README.
smg_comms_c_wrappers 3 *
smg_comms_c_wrappers 4 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
smg_comms_c_wrappers 5 * SHA256(gnupg-1.4.10.tar.gz):
smg_comms_c_wrappers 6 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
smg_comms_c_wrappers 7 * (C) 1994-2005 Free Software Foundation, Inc.
smg_comms_c_wrappers 8 *
smg_comms_c_wrappers 9 * This program is free software: you can redistribute it and/or modify
smg_comms_c_wrappers 10 * it under the terms of the GNU General Public License as published by
smg_comms_c_wrappers 11 * the Free Software Foundation, either version 3 of the License, or
smg_comms_c_wrappers 12 * (at your option) any later version.
smg_comms_c_wrappers 13 *
smg_comms_c_wrappers 14 * This program is distributed in the hope that it will be useful,
smg_comms_c_wrappers 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
smg_comms_c_wrappers 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
smg_comms_c_wrappers 17 * GNU General Public License for more details.
smg_comms_c_wrappers 18 *
smg_comms_c_wrappers 19 * You should have received a copy of the GNU General Public License
smg_comms_c_wrappers 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
smg_comms_c_wrappers 21 */
smg_comms_c_wrappers 22
smg_comms_c_wrappers 23 #include <stdio.h>
smg_comms_c_wrappers 24 #include <string.h>
smg_comms_c_wrappers 25 #include <stdlib.h>
smg_comms_c_wrappers 26 #include <assert.h>
smg_comms_c_wrappers 27
smg_comms_c_wrappers 28 #include "knobs.h"
smg_comms_c_wrappers 29 #include "mpi.h"
smg_comms_c_wrappers 30 #include "mpi-internal.h"
smg_comms_c_wrappers 31 #include "memory.h"
smg_comms_c_wrappers 32 #include "util.h"
smg_comms_c_wrappers 33
smg_comms_c_wrappers 34 #ifdef M_DEBUG
smg_comms_c_wrappers 35 #undef mpi_read
smg_comms_c_wrappers 36 #endif
smg_comms_c_wrappers 37
smg_comms_c_wrappers 38 #define MAX_EXTERN_MPI_BITS 16384
smg_comms_c_wrappers 39
smg_comms_c_wrappers 40
smg_comms_c_wrappers 41 MPI
smg_comms_c_wrappers 42 mpi_read_from_buffer(byte *buffer, unsigned int *ret_nread, int secure)
smg_comms_c_wrappers 43 {
smg_comms_c_wrappers 44 int i, j;
smg_comms_c_wrappers 45 unsigned nbits, nbytes, nlimbs, nread=0;
smg_comms_c_wrappers 46 mpi_limb_t a;
smg_comms_c_wrappers 47 MPI val = NULL;
smg_comms_c_wrappers 48
smg_comms_c_wrappers 49 if( *ret_nread < 2 )
smg_comms_c_wrappers 50 goto leave;
smg_comms_c_wrappers 51 nbits = buffer[0] << 8 | buffer[1];
smg_comms_c_wrappers 52 if( nbits > MAX_EXTERN_MPI_BITS ) {
smg_comms_c_wrappers 53 log_info ("mpi too large (%u bits)\n", nbits);
smg_comms_c_wrappers 54 goto leave;
smg_comms_c_wrappers 55 }
smg_comms_c_wrappers 56 buffer += 2;
smg_comms_c_wrappers 57 nread = 2;
smg_comms_c_wrappers 58
smg_comms_c_wrappers 59 nbytes = (nbits+7) / 8;
smg_comms_c_wrappers 60 nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
smg_comms_c_wrappers 61 val = secure? mpi_alloc_secure( nlimbs )
smg_comms_c_wrappers 62 : mpi_alloc( nlimbs );
smg_comms_c_wrappers 63 i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
smg_comms_c_wrappers 64 i %= BYTES_PER_MPI_LIMB;
smg_comms_c_wrappers 65 val->nbits = nbits;
smg_comms_c_wrappers 66 j= val->nlimbs = nlimbs;
smg_comms_c_wrappers 67 val->sign = 0;
smg_comms_c_wrappers 68 for( ; j > 0; j-- ) {
smg_comms_c_wrappers 69 a = 0;
smg_comms_c_wrappers 70 for(; i < BYTES_PER_MPI_LIMB; i++ ) {
smg_comms_c_wrappers 71 if( ++nread > *ret_nread ) {
smg_comms_c_wrappers 72 /* This (as well as the above error condition) may
smg_comms_c_wrappers 73 happen if we use this function to parse a decrypted
smg_comms_c_wrappers 74 MPI which didn't turn out to be a real MPI - possible
smg_comms_c_wrappers 75 because the supplied key was wrong but the OpenPGP
smg_comms_c_wrappers 76 checksum didn't caught it. */
smg_comms_c_wrappers 77 log_info ("mpi larger than buffer\n");
smg_comms_c_wrappers 78 mpi_free (val);
smg_comms_c_wrappers 79 val = NULL;
smg_comms_c_wrappers 80 goto leave;
smg_comms_c_wrappers 81 }
smg_comms_c_wrappers 82 a <<= 8;
smg_comms_c_wrappers 83 a |= *buffer++;
smg_comms_c_wrappers 84 }
smg_comms_c_wrappers 85 i = 0;
smg_comms_c_wrappers 86 val->d[j-1] = a;
smg_comms_c_wrappers 87 }
smg_comms_c_wrappers 88
smg_comms_c_wrappers 89 leave:
smg_comms_c_wrappers 90 *ret_nread = nread;
smg_comms_c_wrappers 91 return val;
smg_comms_c_wrappers 92 }
smg_comms_c_wrappers 93
smg_comms_c_wrappers 94
smg_comms_c_wrappers 95 /****************
smg_comms_c_wrappers 96 * Make an mpi from a character string.
smg_comms_c_wrappers 97 */
smg_comms_c_wrappers 98 int
smg_comms_c_wrappers 99 mpi_fromstr(MPI val, const char *str)
smg_comms_c_wrappers 100 {
smg_comms_c_wrappers 101 int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2;
smg_comms_c_wrappers 102 unsigned nbits, nbytes, nlimbs;
smg_comms_c_wrappers 103 mpi_limb_t a;
smg_comms_c_wrappers 104
smg_comms_c_wrappers 105 if( *str == '-' ) {
smg_comms_c_wrappers 106 sign = 1;
smg_comms_c_wrappers 107 str++;
smg_comms_c_wrappers 108 }
smg_comms_c_wrappers 109 if( *str == '0' && str[1] == 'x' )
smg_comms_c_wrappers 110 hexmode = 1;
smg_comms_c_wrappers 111 else
smg_comms_c_wrappers 112 return 1; /* other bases are not yet supported */
smg_comms_c_wrappers 113 str += 2;
smg_comms_c_wrappers 114
smg_comms_c_wrappers 115 nbits = strlen(str)*4;
smg_comms_c_wrappers 116 if( nbits % 8 )
smg_comms_c_wrappers 117 prepend_zero = 1;
smg_comms_c_wrappers 118 nbytes = (nbits+7) / 8;
smg_comms_c_wrappers 119 nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
smg_comms_c_wrappers 120 if( val->alloced < nlimbs )
smg_comms_c_wrappers 121 mpi_resize(val, nlimbs );
smg_comms_c_wrappers 122 i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
smg_comms_c_wrappers 123 i %= BYTES_PER_MPI_LIMB;
smg_comms_c_wrappers 124 j= val->nlimbs = nlimbs;
smg_comms_c_wrappers 125 val->sign = sign;
smg_comms_c_wrappers 126 for( ; j > 0; j-- ) {
smg_comms_c_wrappers 127 a = 0;
smg_comms_c_wrappers 128 for(; i < BYTES_PER_MPI_LIMB; i++ ) {
smg_comms_c_wrappers 129 if( prepend_zero ) {
smg_comms_c_wrappers 130 c1 = '0';
smg_comms_c_wrappers 131 prepend_zero = 0;
smg_comms_c_wrappers 132 }
smg_comms_c_wrappers 133 else
smg_comms_c_wrappers 134 c1 = *str++;
smg_comms_c_wrappers 135 assert(c1);
smg_comms_c_wrappers 136 c2 = *str++;
smg_comms_c_wrappers 137 assert(c2);
smg_comms_c_wrappers 138 if( c1 >= '0' && c1 <= '9' )
smg_comms_c_wrappers 139 c = c1 - '0';
smg_comms_c_wrappers 140 else if( c1 >= 'a' && c1 <= 'f' )
smg_comms_c_wrappers 141 c = c1 - 'a' + 10;
smg_comms_c_wrappers 142 else if( c1 >= 'A' && c1 <= 'F' )
smg_comms_c_wrappers 143 c = c1 - 'A' + 10;
smg_comms_c_wrappers 144 else {
smg_comms_c_wrappers 145 mpi_clear(val);
smg_comms_c_wrappers 146 return 1;
smg_comms_c_wrappers 147 }
smg_comms_c_wrappers 148 c <<= 4;
smg_comms_c_wrappers 149 if( c2 >= '0' && c2 <= '9' )
smg_comms_c_wrappers 150 c |= c2 - '0';
smg_comms_c_wrappers 151 else if( c2 >= 'a' && c2 <= 'f' )
smg_comms_c_wrappers 152 c |= c2 - 'a' + 10;
smg_comms_c_wrappers 153 else if( c2 >= 'A' && c2 <= 'F' )
smg_comms_c_wrappers 154 c |= c2 - 'A' + 10;
smg_comms_c_wrappers 155 else {
smg_comms_c_wrappers 156 mpi_clear(val);
smg_comms_c_wrappers 157 return 1;
smg_comms_c_wrappers 158 }
smg_comms_c_wrappers 159 a <<= 8;
smg_comms_c_wrappers 160 a |= c;
smg_comms_c_wrappers 161 }
smg_comms_c_wrappers 162 i = 0;
smg_comms_c_wrappers 163 val->d[j-1] = a;
smg_comms_c_wrappers 164 }
smg_comms_c_wrappers 165
smg_comms_c_wrappers 166 return 0;
smg_comms_c_wrappers 167 }
smg_comms_c_wrappers 168
smg_comms_c_wrappers 169
smg_comms_c_wrappers 170 /****************
smg_comms_c_wrappers 171 * print an MPI to the given stream and return the number of characters
smg_comms_c_wrappers 172 * printed.
smg_comms_c_wrappers 173 */
smg_comms_c_wrappers 174 int
smg_comms_c_wrappers 175 mpi_print( FILE *fp, MPI a, int mode )
smg_comms_c_wrappers 176 {
smg_comms_c_wrappers 177 int i, n=0;
smg_comms_c_wrappers 178
smg_comms_c_wrappers 179 if( a == NULL )
smg_comms_c_wrappers 180 return fprintf(fp, "[MPI_NULL]");
smg_comms_c_wrappers 181 if( !mode ) {
smg_comms_c_wrappers 182 unsigned int n1;
smg_comms_c_wrappers 183
smg_comms_c_wrappers 184 n1 = mpi_get_nbits(a);
smg_comms_c_wrappers 185 n += fprintf(fp, "[%u bits]", n1);
smg_comms_c_wrappers 186 }
smg_comms_c_wrappers 187 else {
smg_comms_c_wrappers 188 if( a->sign )
smg_comms_c_wrappers 189 putc('-', fp);
smg_comms_c_wrappers 190 #if BYTES_PER_MPI_LIMB == 2
smg_comms_c_wrappers 191 #define X "4"
smg_comms_c_wrappers 192 #elif BYTES_PER_MPI_LIMB == 4
smg_comms_c_wrappers 193 #define X "8"
smg_comms_c_wrappers 194 #elif BYTES_PER_MPI_LIMB == 8
smg_comms_c_wrappers 195 #define X "16"
smg_comms_c_wrappers 196 #else
smg_comms_c_wrappers 197 #error please define the format here
smg_comms_c_wrappers 198 #endif
smg_comms_c_wrappers 199 for(i=a->nlimbs; i > 0 ; i-- ) {
smg_comms_c_wrappers 200 n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
smg_comms_c_wrappers 201 #undef X
smg_comms_c_wrappers 202 }
smg_comms_c_wrappers 203 if( !a->nlimbs )
smg_comms_c_wrappers 204 putc('0', fp );
smg_comms_c_wrappers 205 }
smg_comms_c_wrappers 206 return n;
smg_comms_c_wrappers 207 }
smg_comms_c_wrappers 208
smg_comms_c_wrappers 209
smg_comms_c_wrappers 210 /*
smg_comms_c_wrappers 211 void
smg_comms_c_wrappers 212 g10_log_mpidump( const char *text, MPI a )
smg_comms_c_wrappers 213 {
smg_comms_c_wrappers 214 FILE *fp = log_stream();
smg_comms_c_wrappers 215
smg_comms_c_wrappers 216 g10_log_print_prefix(text);
smg_comms_c_wrappers 217 mpi_print(fp, a, 1 );
smg_comms_c_wrappers 218 fputc('\n', fp);
smg_comms_c_wrappers 219 }
smg_comms_c_wrappers 220 */
smg_comms_c_wrappers 221
smg_comms_c_wrappers 222
smg_comms_c_wrappers 223 /****************
smg_comms_c_wrappers 224 * Return an xmalloced buffer with the MPI (msb first).
smg_comms_c_wrappers 225 * NBYTES receives the length of this buffer. Caller must free the
smg_comms_c_wrappers 226 * return string (This function does return a 0 byte buffer with NBYTES
smg_comms_c_wrappers 227 * set to zero if the value of A is zero. If sign is not NULL, it will
smg_comms_c_wrappers 228 * be set to the sign of the A.
smg_comms_c_wrappers 229 */
smg_comms_c_wrappers 230 static byte *
smg_comms_c_wrappers 231 do_get_buffer( MPI a, unsigned *nbytes, int *sign, int force_secure )
smg_comms_c_wrappers 232 {
smg_comms_c_wrappers 233 byte *p, *buffer;
smg_comms_c_wrappers 234 mpi_limb_t alimb;
smg_comms_c_wrappers 235 int i;
smg_comms_c_wrappers 236 unsigned int n;
smg_comms_c_wrappers 237
smg_comms_c_wrappers 238 if( sign )
smg_comms_c_wrappers 239 *sign = a->sign;
smg_comms_c_wrappers 240 *nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB;
smg_comms_c_wrappers 241 if (!n)
smg_comms_c_wrappers 242 n++; /* avoid zero length allocation */
smg_comms_c_wrappers 243 p = buffer = force_secure || mpi_is_secure(a) ? xmalloc_secure(n)
smg_comms_c_wrappers 244 : xmalloc(n);
smg_comms_c_wrappers 245
smg_comms_c_wrappers 246 for(i=a->nlimbs-1; i >= 0; i-- ) {
smg_comms_c_wrappers 247 alimb = a->d[i];
smg_comms_c_wrappers 248 #if BYTES_PER_MPI_LIMB == 4
smg_comms_c_wrappers 249 *p++ = alimb >> 24;
smg_comms_c_wrappers 250 *p++ = alimb >> 16;
smg_comms_c_wrappers 251 *p++ = alimb >> 8;
smg_comms_c_wrappers 252 *p++ = alimb ;
smg_comms_c_wrappers 253 #elif BYTES_PER_MPI_LIMB == 8
smg_comms_c_wrappers 254 *p++ = alimb >> 56;
smg_comms_c_wrappers 255 *p++ = alimb >> 48;
smg_comms_c_wrappers 256 *p++ = alimb >> 40;
smg_comms_c_wrappers 257 *p++ = alimb >> 32;
smg_comms_c_wrappers 258 *p++ = alimb >> 24;
smg_comms_c_wrappers 259 *p++ = alimb >> 16;
smg_comms_c_wrappers 260 *p++ = alimb >> 8;
smg_comms_c_wrappers 261 *p++ = alimb ;
smg_comms_c_wrappers 262 #else
smg_comms_c_wrappers 263 #error please implement for this limb size.
smg_comms_c_wrappers 264 #endif
smg_comms_c_wrappers 265 }
smg_comms_c_wrappers 266
smg_comms_c_wrappers 267 /* this is sub-optimal but we need to do the shift operation
smg_comms_c_wrappers 268 * because the caller has to free the returned buffer */
smg_comms_c_wrappers 269 for(p=buffer; !*p && *nbytes; p++, --*nbytes )
smg_comms_c_wrappers 270 ;
smg_comms_c_wrappers 271 if( p != buffer )
smg_comms_c_wrappers 272 memmove(buffer,p, *nbytes);
smg_comms_c_wrappers 273
smg_comms_c_wrappers 274 return buffer;
smg_comms_c_wrappers 275 }
smg_comms_c_wrappers 276
smg_comms_c_wrappers 277
smg_comms_c_wrappers 278 byte *
smg_comms_c_wrappers 279 mpi_get_buffer( MPI a, unsigned *nbytes, int *sign )
smg_comms_c_wrappers 280 {
smg_comms_c_wrappers 281 return do_get_buffer( a, nbytes, sign, 0 );
smg_comms_c_wrappers 282 }
smg_comms_c_wrappers 283
smg_comms_c_wrappers 284 byte *
smg_comms_c_wrappers 285 mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign )
smg_comms_c_wrappers 286 {
smg_comms_c_wrappers 287 return do_get_buffer( a, nbytes, sign, 1 );
smg_comms_c_wrappers 288 }
smg_comms_c_wrappers 289
smg_comms_c_wrappers 290 /****************
smg_comms_c_wrappers 291 * Use BUFFER to update MPI.
smg_comms_c_wrappers 292 */
smg_comms_c_wrappers 293 void
smg_comms_c_wrappers 294 mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign )
smg_comms_c_wrappers 295 {
smg_comms_c_wrappers 296 const byte *p;
smg_comms_c_wrappers 297 mpi_limb_t alimb;
smg_comms_c_wrappers 298 int nlimbs;
smg_comms_c_wrappers 299 int i;
smg_comms_c_wrappers 300
smg_comms_c_wrappers 301 nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
smg_comms_c_wrappers 302 RESIZE_IF_NEEDED(a, nlimbs);
smg_comms_c_wrappers 303 a->sign = sign;
smg_comms_c_wrappers 304
smg_comms_c_wrappers 305 for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
smg_comms_c_wrappers 306 #if BYTES_PER_MPI_LIMB == 4
smg_comms_c_wrappers 307 alimb = (mpi_limb_t)*p-- ;
smg_comms_c_wrappers 308 alimb |= (mpi_limb_t)*p-- << 8 ;
smg_comms_c_wrappers 309 alimb |= (mpi_limb_t)*p-- << 16 ;
smg_comms_c_wrappers 310 alimb |= (mpi_limb_t)*p-- << 24 ;
smg_comms_c_wrappers 311 #elif BYTES_PER_MPI_LIMB == 8
smg_comms_c_wrappers 312 alimb = (mpi_limb_t)*p-- ;
smg_comms_c_wrappers 313 alimb |= (mpi_limb_t)*p-- << 8 ;
smg_comms_c_wrappers 314 alimb |= (mpi_limb_t)*p-- << 16 ;
smg_comms_c_wrappers 315 alimb |= (mpi_limb_t)*p-- << 24 ;
smg_comms_c_wrappers 316 alimb |= (mpi_limb_t)*p-- << 32 ;
smg_comms_c_wrappers 317 alimb |= (mpi_limb_t)*p-- << 40 ;
smg_comms_c_wrappers 318 alimb |= (mpi_limb_t)*p-- << 48 ;
smg_comms_c_wrappers 319 alimb |= (mpi_limb_t)*p-- << 56 ;
smg_comms_c_wrappers 320 #else
smg_comms_c_wrappers 321 #error please implement for this limb size.
smg_comms_c_wrappers 322 #endif
smg_comms_c_wrappers 323 a->d[i++] = alimb;
smg_comms_c_wrappers 324 }
smg_comms_c_wrappers 325 if( p >= buffer ) {
smg_comms_c_wrappers 326 #if BYTES_PER_MPI_LIMB == 4
smg_comms_c_wrappers 327 alimb = *p-- ;
smg_comms_c_wrappers 328 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ;
smg_comms_c_wrappers 329 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
smg_comms_c_wrappers 330 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
smg_comms_c_wrappers 331 #elif BYTES_PER_MPI_LIMB == 8
smg_comms_c_wrappers 332 alimb = (mpi_limb_t)*p-- ;
smg_comms_c_wrappers 333 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ;
smg_comms_c_wrappers 334 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
smg_comms_c_wrappers 335 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
smg_comms_c_wrappers 336 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ;
smg_comms_c_wrappers 337 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ;
smg_comms_c_wrappers 338 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ;
smg_comms_c_wrappers 339 if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ;
smg_comms_c_wrappers 340 #else
smg_comms_c_wrappers 341 #error please implement for this limb size.
smg_comms_c_wrappers 342 #endif
smg_comms_c_wrappers 343 a->d[i++] = alimb;
smg_comms_c_wrappers 344 }
smg_comms_c_wrappers 345 a->nlimbs = i;
smg_comms_c_wrappers 346 assert( i == nlimbs );
smg_comms_c_wrappers 347 }