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