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