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