|
|
1.1.1.5 ! root 1: /* mpiio.c - C source code for multiprecision integer I/O routines. ! 2: Implemented Nov 86 by Philip Zimmermann ! 3: Last revised 13 Sep 91 by PRZ ! 4: ! 5: Boulder Software Engineering ! 6: 3021 Eleventh Street ! 7: Boulder, CO 80304 ! 8: (303) 541-0140 ! 9: ! 10: (c) Copyright 1986-1994 by Philip Zimmermann. All rights reserved. ! 11: The author assumes no liability for damages resulting from the use ! 12: of this software, even if the damage results from defects in this ! 13: software. No warranty is expressed or implied. ! 14: ! 15: These routines are for multiprecision arithmetic I/O functions for ! 16: number-theoretic cryptographic algorithms such as ElGamal, ! 17: Diffie-Hellman, Rabin, or factoring studies for large composite ! 18: numbers, as well as Rivest-Shamir-Adleman (RSA) public key ! 19: cryptography. ! 20: ! 21: The external data representation for RSA messages and keys that ! 22: some of these library routines assume is outlined in a paper by ! 23: Philip Zimmermann, "A Proposed Standard Format for RSA Cryptosystems", ! 24: IEEE Computer, September 1986, Vol. 19 No. 9, pages 21-34. ! 25: Some revisions to this data format have occurred since the paper ! 26: was published. ! 27: */ ! 28: ! 29: /* #define DEBUG */ ! 30: ! 31: ! 32: #ifndef EMBEDDED /* not EMBEDDED - not compiling for embedded target */ ! 33: #include <stdio.h> /* for printf, etc. */ ! 34: #else /* EMBEDDED - compiling for embedded target */ ! 35: #define NULL (VOID *)0 ! 36: #endif ! 37: ! 38: #include "mpilib.h" ! 39: #include "mpiio.h" ! 40: #include "pgp.h" ! 41: ! 42: static void puthexbyte(byte b); /* Put out byte in ASCII hex via putchar. */ ! 43: static ! 44: void puthexw16(word16 w); /* Put out 16-bit word in hex, high byte first. */ ! 45: static ! 46: void putstr(string s); /* Put out null-terminated ASCII string via putchar. */ ! 47: ! 48: /*----------------- Following procedures relate to I/O ------------------*/ ! 49: ! 50: int string_length(char *s) ! 51: /* Returns string length, just like strlen() from <string.h> */ ! 52: { ! 53: int i; ! 54: i = 0; ! 55: if (s != NULL) ! 56: while (*s++) i++; ! 57: return (i); ! 58: } /* string_length */ ! 59: ! 60: ! 61: #ifdef DEBUG ! 62: static int ctox(int c) ! 63: /* Returns integer 0-15 if c is an ASCII hex digit, -1 otherwise. */ ! 64: { ! 65: if ((c >= '0') && (c <= '9')) ! 66: return(c - '0'); ! 67: if ((c >= 'a') && (c <= 'f')) ! 68: return((c - 'a') + 10); ! 69: if ((c >= 'A') && (c <= 'F')) ! 70: return((c - 'A') + 10); ! 71: return(-1); /* error -- not a hex digit */ ! 72: } /* ctox */ ! 73: ! 74: ! 75: int str2reg(unitptr reg,string digitstr) ! 76: /* Converts a possibly-signed digit string into a large binary number. ! 77: Returns assumed radix, derived from suffix 'h','o',b','.' */ ! 78: { ! 79: unit temp[MAX_UNIT_PRECISION],base[MAX_UNIT_PRECISION]; ! 80: int c,i; ! 81: boolean minus = FALSE; ! 82: short radix; /* base 2-16 */ ! 83: ! 84: mp_init(reg,0); ! 85: ! 86: i = string_length(digitstr); ! 87: if (i==0) return(10); /* empty string, assume radix 10 */ ! 88: c = digitstr[i-1]; /* get last char in string */ ! 89: ! 90: switch (c) /* classify radix select suffix character */ ! 91: { ! 92: case '.': radix = 10; break; ! 93: case 'H': ! 94: case 'h': radix = 16; break; ! 95: case 'O': ! 96: case 'o': radix = 8; break; ! 97: case 'B': /* caution! 'b' is a hex digit! */ ! 98: case 'b': radix = 2; break; ! 99: default: radix = 10; break; ! 100: } ! 101: ! 102: mp_init(base,radix); ! 103: if ((minus = (*digitstr == '-')) != 0) digitstr++; ! 104: while ((c = *digitstr++) != 0) { ! 105: if (c==',') continue; /* allow commas in number */ ! 106: c = ctox(c); ! 107: if ((c < 0) || (c >= radix)) ! 108: break; /* scan terminated by any non-digit */ ! 109: mp_mult(temp,reg,base); ! 110: mp_move(reg,temp); ! 111: mp_init(temp,c); ! 112: mp_add(reg,temp); ! 113: } ! 114: if (minus) mp_neg(reg); ! 115: return(radix); ! 116: } /* str2reg */ ! 117: ! 118: #endif /* DEBUG */ ! 119: ! 120: /* These I/O functions, such as putstr, puthexbyte, and puthexw16, ! 121: are provided here to avoid the need to link in printf from the ! 122: C I/O library. This is handy in an embedded application. ! 123: For embedded applications, use a customized putchar function, ! 124: separately compiled. ! 125: */ ! 126: ! 127: static void putstr(string s) ! 128: /* Put out null-terminated ASCII string via putchar. */ ! 129: { ! 130: while (*s) ! 131: putchar(*s++); ! 132: } /* putstr */ ! 133: ! 134: static void puthexbyte(byte b) ! 135: /* Put out byte in ASCII hex via putchar. */ ! 136: { ! 137: static char const nibs[16] = "0123456789ABCDEF"; ! 138: putchar(nibs[b >> 4]); ! 139: putchar(nibs[b & 0x0F]); ! 140: } /* puthexbyte */ ! 141: ! 142: static void puthexw16(word16 w) ! 143: /* Put out 16-bit word in hex, high byte first. */ ! 144: { ! 145: puthexbyte((byte)(w >> 8)); ! 146: puthexbyte((byte)(w & 0xFF)); ! 147: } /* puthexw16 */ ! 148: ! 149: #ifdef UNIT32 ! 150: static void puthexw32(word32 lw) ! 151: /* Puts out 32-bit word in hex, high byte first. */ ! 152: { ! 153: puthexw16((word16)(lw>>16)); ! 154: puthexw16((word16)(lw & 0xFFFFL)); ! 155: } /* puthexw32 */ ! 156: #endif /* UNIT32 */ ! 157: ! 158: ! 159: #ifdef UNIT8 ! 160: #define puthexunit(u) puthexbyte(u) ! 161: #endif ! 162: #ifdef UNIT16 ! 163: #define puthexunit(u) puthexw16(u) ! 164: #endif ! 165: #ifdef UNIT32 ! 166: #define puthexunit(u) puthexw32(u) ! 167: #endif ! 168: ! 169: #ifdef DEBUG ! 170: int display_in_base(string s,unitptr n,short radix) ! 171: /* ! 172: * Display n in any base, such as base 10. Returns number of digits. ! 173: * s is string to label the displayed register. ! 174: * n is multiprecision integer. ! 175: * radix is base, 2-16. ! 176: */ ! 177: { ! 178: char buf[MAX_BIT_PRECISION + (MAX_BIT_PRECISION/8) + 2]; ! 179: unit r[MAX_UNIT_PRECISION],quotient[MAX_UNIT_PRECISION]; ! 180: word16 remainder; ! 181: char *bp = buf; ! 182: char minus = FALSE; ! 183: int places = 0; ! 184: int commaplaces; /* put commas this many digits apart */ ! 185: int i; ! 186: ! 187: /* If string s is just an ESC char, don't print it. ! 188: It's just to inhibit the \n at the end of the number. ! 189: */ ! 190: if ((s[0] != '\033') || (s[1] != '\0')) ! 191: putstr(s); ! 192: ! 193: if ( (radix < 2) || (radix > 16) ) { ! 194: putstr("****\n"); /* radix out of range -- show error */ ! 195: return(-1); ! 196: } ! 197: commaplaces = (radix==10 ? 3 : (radix==16 ? 4 : ! 198: (radix==2 ? 8 : (radix==8 ? 8 : 1)))); ! 199: mp_move(r,n); ! 200: if ((radix == 10) && mp_tstminus(r)) { ! 201: minus = TRUE; ! 202: mp_neg(r); /* make r positive */ ! 203: } ! 204: ! 205: *bp = '\0'; ! 206: do { /* build backwards number string */ ! 207: if (++places>1) ! 208: if ((places % commaplaces)==1) ! 209: *++bp = ','; /* 000,000,000,000 */ ! 210: remainder = mp_shortdiv(quotient,r,radix); ! 211: *++bp = "0123456789ABCDEF" [remainder]; /* Isn't C wonderful? */ ! 212: mp_move(r,quotient); ! 213: } while (testne(r,0)); ! 214: if (minus) ! 215: *++bp = '-'; ! 216: ! 217: if (commaplaces!=1) ! 218: while ((++places % commaplaces) != 1) ! 219: *++bp = ' '; /* pad to line up commas */ ! 220: ! 221: i = string_length(s); ! 222: while (*bp) { ! 223: putchar(*bp); ! 224: ++i; ! 225: if ((*bp == ',') || commaplaces==1) ! 226: if (i > (72-commaplaces)) { ! 227: putchar('\n'); ! 228: i=string_length(s); ! 229: while (i--) putchar(' '); ! 230: i = string_length(s); ! 231: } ! 232: bp--; ! 233: } ! 234: ! 235: /* show suffix character to designate radix */ ! 236: switch (radix) { ! 237: case 10: /* decimal */ ! 238: putchar('.'); ! 239: break; ! 240: case 16: /* hex */ ! 241: putchar('h'); ! 242: break; ! 243: case 8: /* octal */ ! 244: putchar('o'); ! 245: break; ! 246: case 2: /* binary */ ! 247: putchar('b'); ! 248: break; ! 249: default: /* nonstandard radix */ ! 250: /* printf("(%d)",radix); */ ; ! 251: } ! 252: ! 253: if ((s[0] == '\033') && (s[1] == '\0')) ! 254: putchar(' '); /* supress newline */ ! 255: else putchar('\n'); ! 256: ! 257: fill0((byteptr)buf,sizeof(buf)); /* burn the evidence on the stack...*/ ! 258: /* Note that local stack arrays r and quotient are now 0 */ ! 259: return(places); ! 260: } /* display_in_base */ ! 261: ! 262: #endif /* DEBUG */ ! 263: ! 264: void mp_display(string s,unitptr r) ! 265: /* Display register r in hex, with prefix string s. */ ! 266: { ! 267: short precision; ! 268: int i,j; ! 269: putstr(s); ! 270: normalize(r,precision); /* strip off leading zeros */ ! 271: if (precision == 0) { ! 272: putstr(" 0\n"); ! 273: return; ! 274: } ! 275: make_msbptr(r,precision); ! 276: i=0; ! 277: while (precision--) { ! 278: if (!(i++ % (16/BYTES_PER_UNIT))) { ! 279: if (i>1) { ! 280: putchar('\n'); ! 281: j=string_length(s); ! 282: while (j--) putchar(' '); ! 283: } ! 284: } ! 285: puthexunit(*r); ! 286: putchar(' '); ! 287: post_lowerunit(r); ! 288: } ! 289: putchar('\n'); ! 290: } /* mp_display */ ! 291: ! 292: ! 293: word16 checksum(register byteptr buf, register word16 count) ! 294: /* Returns checksum of buffer. */ ! 295: { ! 296: word16 cs; ! 297: cs = 0; ! 298: while (count--) cs += *buf++; ! 299: return(cs); ! 300: } /* checksum */ ! 301: ! 302: ! 303: void cbc_xor(register unitptr dst, register unitptr src, word16 bytecount) ! 304: /* ! 305: * Performs the XOR necessary for RSA Cipher Block Chaining. ! 306: * The dst buffer ought to have 1 less byte of significance than ! 307: * the src buffer. Only the least significant part of the src ! 308: * buffer is used. bytecount is the size of a plaintext block. ! 309: */ ! 310: { short nunits; /* units of precision */ ! 311: nunits = bytes2units(bytecount)-1; ! 312: make_lsbptr(dst,global_precision); ! 313: while (nunits--) { ! 314: *dst ^= *post_higherunit(src); ! 315: post_higherunit(dst); ! 316: bytecount -= units2bytes(1); ! 317: } ! 318: /* on the last unit, don't xor the excess top byte... */ ! 319: *dst ^= (*src & (power_of_2(bytecount<<3)-1)); ! 320: } /* cbc_xor */ ! 321: ! 322: ! 323: void hiloswap(byteptr r1,short numbytes) ! 324: /* Reverses the order of bytes in an array of bytes. */ ! 325: { ! 326: byteptr r2; ! 327: byte b; ! 328: r2 = &(r1[numbytes-1]); ! 329: while (r1 < r2) { ! 330: b = *r1; *r1++ = *r2; *r2-- = b; ! 331: } ! 332: } /* hiloswap */ ! 333: ! 334: ! 335: #define byteglue(lo,hi) ((((word16) hi) << 8) + (word16) lo) ! 336: ! 337: /**** The following functions must be changed if the external byteorder ! 338: changes for integers in PGP packet data. ! 339: ****/ ! 340: ! 341: ! 342: word16 fetch_word16(byte *buf) ! 343: /* Fetches a 16-bit word from where byte pointer is pointing. ! 344: buf points to external-format byteorder array. ! 345: */ ! 346: { ! 347: word16 w0, w1; ! 348: /* Assume MSB external byte ordering */ ! 349: w1 = *buf++; ! 350: w0 = *buf++; ! 351: return(w0 + (w1<<8)); ! 352: } /* fetch_word16 */ ! 353: ! 354: ! 355: byte *put_word16(word16 w, byte *buf) ! 356: /* ! 357: * Puts a 16-bit word to where byte pointer is pointing, and ! 358: * returns updated byte pointer. ! 359: * buf points to external-format byteorder array. ! 360: */ ! 361: { ! 362: /* Assume MSB external byte ordering */ ! 363: buf[1] = w & 0xff; ! 364: w = w>>8; ! 365: buf[0] = w & 0xff; ! 366: return(buf+2); ! 367: } /* put_word16 */ ! 368: ! 369: ! 370: word32 fetch_word32(byte *buf) ! 371: /* Fetches a 32-bit word from where byte pointer is pointing. ! 372: buf points to external-format byteorder array. ! 373: */ ! 374: { ! 375: word32 w0,w1,w2,w3; ! 376: /* Assume MSB external byte ordering */ ! 377: w3 = *buf++; ! 378: w2 = *buf++; ! 379: w1 = *buf++; ! 380: w0 = *buf++; ! 381: return(w0 + (w1<<8) + (w2<<16) + (w3<<24)); ! 382: } /* fetch_word32 */ ! 383: ! 384: ! 385: byte *put_word32(word32 w, byte *buf) ! 386: /* Puts a 32-bit word to where byte pointer is pointing, and ! 387: returns updated byte pointer. ! 388: buf points to external-format byteorder array. ! 389: */ ! 390: { ! 391: /* Assume MSB external byte ordering */ ! 392: buf[3] = w & 0xff; ! 393: w = w>>8; ! 394: buf[2] = w & 0xff; ! 395: w = w>>8; ! 396: buf[1] = w & 0xff; ! 397: w = w>>8; ! 398: buf[0] = w & 0xff; ! 399: return(buf+4); ! 400: } /* put_word32 */ ! 401: ! 402: ! 403: /*** End of functions that must be changed if the external byteorder ! 404: changes for integer fields in PGP packets. ! 405: ***/ ! 406: ! 407: ! 408: ! 409: ! 410: short mpi2reg(register unitptr r,register byteptr buf) ! 411: /* ! 412: * Converts a multiprecision integer from the externally-represented ! 413: * form of a byte array with a 16-bit bitcount in a leading length ! 414: * word to the internally-used representation as a unit array. ! 415: * Converts to INTERNAL byte order. ! 416: * The same buffer address may be used for both r and buf. ! 417: * Returns number of units in result, or returns -1 on error. ! 418: */ ! 419: { ! 420: byte buf2[MAX_BYTE_PRECISION]; ! 421: word16 bitcount, bytecount, unitcount, zero_bytes, i; ! 422: ! 423: /* First, extract 16-bit bitcount prefix from first 2 bytes... */ ! 424: bitcount = fetch_word16(buf); ! 425: buf += 2; ! 426: ! 427: /* Convert bitcount to bytecount and unitcount... */ ! 428: bytecount = bits2bytes(bitcount); ! 429: unitcount = bytes2units(bytecount); ! 430: if (unitcount > global_precision) { ! 431: /* precision overflow during conversion. */ ! 432: return(-1); /* precision overflow -- error return */ ! 433: } ! 434: zero_bytes = units2bytes(global_precision) - bytecount; ! 435: /* Assume MSB external byte ordering */ ! 436: fill0(buf2,zero_bytes); /* fill leading zero bytes */ ! 437: i = zero_bytes; /* assumes MSB first */ ! 438: while (bytecount--) buf2[i++] = *buf++; ! 439: ! 440: mp_convert_order(buf2); /* convert to INTERNAL byte order */ ! 441: mp_move(r,(unitptr)buf2); ! 442: mp_burn((unitptr)buf2); /* burn the evidence on the stack */ ! 443: return(unitcount); /* returns unitcount of reg */ ! 444: } /* mpi2reg */ ! 445: ! 446: ! 447: short reg2mpi(register byteptr buf,register unitptr r) ! 448: /* ! 449: * Converts the multiprecision integer r from the internal form of ! 450: * a unit array to the normalized externally-represented form of a ! 451: * byte array with a leading 16-bit bitcount word in buf[0] and buf[1]. ! 452: * This bitcount length prefix is exact count, not rounded up. ! 453: * Converts to EXTERNAL byte order. ! 454: * The same buffer address may be used for both r and buf. ! 455: * Returns the number of bytes of the result, not counting length prefix. ! 456: */ ! 457: { ! 458: byte buf1[MAX_BYTE_PRECISION]; ! 459: byteptr buf2; ! 460: short bytecount,bc; ! 461: word16 bitcount; ! 462: bitcount = countbits(r); ! 463: #ifdef DEBUG ! 464: if (bitcount > MAX_BIT_PRECISION) { ! 465: fprintf(stderr, "reg2mpi: bitcount out of range (%d)\n", bitcount); ! 466: return 0; ! 467: } ! 468: #endif ! 469: bytecount = bits2bytes(bitcount); ! 470: bc = bytecount; /* save bytecount for return */ ! 471: buf2 = buf1; ! 472: mp_move((unitptr)buf2,r); ! 473: mp_convert_order(buf2); /* convert to EXTERNAL byteorder */ ! 474: /* Assume MSB external byte ordering */ ! 475: buf2 += units2bytes(global_precision) - bytecount; ! 476: buf = put_word16(bitcount, buf); /* store bitcount in external byteorder */ ! 477: ! 478: while (bytecount--) *buf++ = *buf2++; ! 479: ! 480: mp_burn((unitptr)buf1); /* burn the evidence on the stack */ ! 481: return(bc); /* returns bytecount of mpi, not counting prefix */ ! 482: } /* reg2mpi */ ! 483: ! 484: ! 485: #ifdef DEBUG ! 486: ! 487: void dumpbuf(string s, byteptr buf, int bytecount) ! 488: /* Dump buffer in hex, with string label prefix. */ ! 489: { ! 490: putstr(s); ! 491: while (bytecount--) { ! 492: puthexbyte(*buf++); ! 493: putchar(' '); ! 494: if ((bytecount & 0x0f)==0) ! 495: putchar('\n'); ! 496: } ! 497: } /* dumpbuf */ ! 498: ! 499: void dump_unit_array(string s, unitptr r) ! 500: /* ! 501: * Dump unit array r as a C array initializer, with string label prefix. ! 502: * Array is dumped in native unit order. ! 503: */ ! 504: { ! 505: int unitcount; ! 506: unitcount = global_precision; ! 507: putstr(s); ! 508: putstr("\n{ "); ! 509: while (unitcount--) { ! 510: putstr("0x"); ! 511: puthexunit(*r++); ! 512: putchar(','); ! 513: if (unitcount && ((unitcount & 0x07)==0)) ! 514: putstr("\n "); ! 515: } ! 516: putstr(" 0};\n"); ! 517: } /* dump_unit_array */ ! 518: ! 519: #endif /* ifdef DEBUG */ ! 520: ! 521: /************ end of multiprecision integer I/O library *****************/ ! 522:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.