|
|
1.1.1.6 ! 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: #ifdef VMS ! 138: static char const nibs[] = "0123456789ABCDEF"; ! 139: #else ! 140: static char const nibs[16] = "0123456789ABCDEF"; ! 141: #endif ! 142: putchar(nibs[b >> 4]); ! 143: putchar(nibs[b & 0x0F]); ! 144: } /* puthexbyte */ ! 145: ! 146: static void puthexw16(word16 w) ! 147: /* Put out 16-bit word in hex, high byte first. */ ! 148: { ! 149: puthexbyte((byte)(w >> 8)); ! 150: puthexbyte((byte)(w & 0xFF)); ! 151: } /* puthexw16 */ ! 152: ! 153: #ifdef UNIT32 ! 154: static void puthexw32(word32 lw) ! 155: /* Puts out 32-bit word in hex, high byte first. */ ! 156: { ! 157: puthexw16((word16)(lw>>16)); ! 158: puthexw16((word16)(lw & 0xFFFFL)); ! 159: } /* puthexw32 */ ! 160: #endif /* UNIT32 */ ! 161: ! 162: ! 163: #ifdef UNIT8 ! 164: #define puthexunit(u) puthexbyte(u) ! 165: #endif ! 166: #ifdef UNIT16 ! 167: #define puthexunit(u) puthexw16(u) ! 168: #endif ! 169: #ifdef UNIT32 ! 170: #define puthexunit(u) puthexw32(u) ! 171: #endif ! 172: ! 173: #ifdef DEBUG ! 174: int display_in_base(string s,unitptr n,short radix) ! 175: /* ! 176: * Display n in any base, such as base 10. Returns number of digits. ! 177: * s is string to label the displayed register. ! 178: * n is multiprecision integer. ! 179: * radix is base, 2-16. ! 180: */ ! 181: { ! 182: char buf[MAX_BIT_PRECISION + (MAX_BIT_PRECISION/8) + 2]; ! 183: unit r[MAX_UNIT_PRECISION],quotient[MAX_UNIT_PRECISION]; ! 184: word16 remainder; ! 185: char *bp = buf; ! 186: char minus = FALSE; ! 187: int places = 0; ! 188: int commaplaces; /* put commas this many digits apart */ ! 189: int i; ! 190: ! 191: /* If string s is just an ESC char, don't print it. ! 192: It's just to inhibit the \n at the end of the number. ! 193: */ ! 194: if ((s[0] != '\033') || (s[1] != '\0')) ! 195: putstr(s); ! 196: ! 197: if ( (radix < 2) || (radix > 16) ) { ! 198: putstr("****\n"); /* radix out of range -- show error */ ! 199: return(-1); ! 200: } ! 201: commaplaces = (radix==10 ? 3 : (radix==16 ? 4 : ! 202: (radix==2 ? 8 : (radix==8 ? 8 : 1)))); ! 203: mp_move(r,n); ! 204: if ((radix == 10) && mp_tstminus(r)) { ! 205: minus = TRUE; ! 206: mp_neg(r); /* make r positive */ ! 207: } ! 208: ! 209: *bp = '\0'; ! 210: do { /* build backwards number string */ ! 211: if (++places>1) ! 212: if ((places % commaplaces)==1) ! 213: *++bp = ','; /* 000,000,000,000 */ ! 214: remainder = mp_shortdiv(quotient,r,radix); ! 215: *++bp = "0123456789ABCDEF" [remainder]; /* Isn't C wonderful? */ ! 216: mp_move(r,quotient); ! 217: } while (testne(r,0)); ! 218: if (minus) ! 219: *++bp = '-'; ! 220: ! 221: if (commaplaces!=1) ! 222: while ((++places % commaplaces) != 1) ! 223: *++bp = ' '; /* pad to line up commas */ ! 224: ! 225: i = string_length(s); ! 226: while (*bp) { ! 227: putchar(*bp); ! 228: ++i; ! 229: if ((*bp == ',') || commaplaces==1) ! 230: if (i > (72-commaplaces)) { ! 231: putchar('\n'); ! 232: i=string_length(s); ! 233: while (i--) putchar(' '); ! 234: i = string_length(s); ! 235: } ! 236: bp--; ! 237: } ! 238: ! 239: /* show suffix character to designate radix */ ! 240: switch (radix) { ! 241: case 10: /* decimal */ ! 242: putchar('.'); ! 243: break; ! 244: case 16: /* hex */ ! 245: putchar('h'); ! 246: break; ! 247: case 8: /* octal */ ! 248: putchar('o'); ! 249: break; ! 250: case 2: /* binary */ ! 251: putchar('b'); ! 252: break; ! 253: default: /* nonstandard radix */ ! 254: /* printf("(%d)",radix); */ ; ! 255: } ! 256: ! 257: if ((s[0] == '\033') && (s[1] == '\0')) ! 258: putchar(' '); /* supress newline */ ! 259: else putchar('\n'); ! 260: ! 261: fill0((byteptr)buf,sizeof(buf)); /* burn the evidence on the stack...*/ ! 262: /* Note that local stack arrays r and quotient are now 0 */ ! 263: return(places); ! 264: } /* display_in_base */ ! 265: ! 266: #endif /* DEBUG */ ! 267: ! 268: void mp_display(string s,unitptr r) ! 269: /* Display register r in hex, with prefix string s. */ ! 270: { ! 271: short precision; ! 272: int i,j; ! 273: putstr(s); ! 274: normalize(r,precision); /* strip off leading zeros */ ! 275: if (precision == 0) { ! 276: putstr(" 0\n"); ! 277: return; ! 278: } ! 279: make_msbptr(r,precision); ! 280: i=0; ! 281: while (precision--) { ! 282: if (!(i++ % (16/BYTES_PER_UNIT))) { ! 283: if (i>1) { ! 284: putchar('\n'); ! 285: j=string_length(s); ! 286: while (j--) putchar(' '); ! 287: } ! 288: } ! 289: puthexunit(*r); ! 290: putchar(' '); ! 291: post_lowerunit(r); ! 292: } ! 293: putchar('\n'); ! 294: } /* mp_display */ ! 295: ! 296: ! 297: word16 checksum(register byteptr buf, register word16 count) ! 298: /* Returns checksum of buffer. */ ! 299: { ! 300: word16 cs; ! 301: cs = 0; ! 302: while (count--) cs += *buf++; ! 303: return(cs); ! 304: } /* checksum */ ! 305: ! 306: ! 307: void cbc_xor(register unitptr dst, register unitptr src, word16 bytecount) ! 308: /* ! 309: * Performs the XOR necessary for RSA Cipher Block Chaining. ! 310: * The dst buffer ought to have 1 less byte of significance than ! 311: * the src buffer. Only the least significant part of the src ! 312: * buffer is used. bytecount is the size of a plaintext block. ! 313: */ ! 314: { short nunits; /* units of precision */ ! 315: nunits = bytes2units(bytecount)-1; ! 316: make_lsbptr(dst,global_precision); ! 317: while (nunits--) { ! 318: *dst ^= *post_higherunit(src); ! 319: post_higherunit(dst); ! 320: bytecount -= units2bytes(1); ! 321: } ! 322: /* on the last unit, don't xor the excess top byte... */ ! 323: *dst ^= (*src & (power_of_2(bytecount<<3)-1)); ! 324: } /* cbc_xor */ ! 325: ! 326: ! 327: void hiloswap(byteptr r1,short numbytes) ! 328: /* Reverses the order of bytes in an array of bytes. */ ! 329: { ! 330: byteptr r2; ! 331: byte b; ! 332: r2 = &(r1[numbytes-1]); ! 333: while (r1 < r2) { ! 334: b = *r1; *r1++ = *r2; *r2-- = b; ! 335: } ! 336: } /* hiloswap */ ! 337: ! 338: ! 339: #define byteglue(lo,hi) ((((word16) hi) << 8) + (word16) lo) ! 340: ! 341: /**** The following functions must be changed if the external byteorder ! 342: changes for integers in PGP packet data. ! 343: ****/ ! 344: ! 345: ! 346: word16 fetch_word16(byte *buf) ! 347: /* Fetches a 16-bit word from where byte pointer is pointing. ! 348: buf points to external-format byteorder array. ! 349: */ ! 350: { ! 351: word16 w0, w1; ! 352: /* Assume MSB external byte ordering */ ! 353: w1 = *buf++; ! 354: w0 = *buf++; ! 355: return(w0 + (w1<<8)); ! 356: } /* fetch_word16 */ ! 357: ! 358: ! 359: byte *put_word16(word16 w, byte *buf) ! 360: /* ! 361: * Puts a 16-bit word to where byte pointer is pointing, and ! 362: * returns updated byte pointer. ! 363: * buf points to external-format byteorder array. ! 364: */ ! 365: { ! 366: /* Assume MSB external byte ordering */ ! 367: buf[1] = w & 0xff; ! 368: w = w>>8; ! 369: buf[0] = w & 0xff; ! 370: return(buf+2); ! 371: } /* put_word16 */ ! 372: ! 373: ! 374: word32 fetch_word32(byte *buf) ! 375: /* Fetches a 32-bit word from where byte pointer is pointing. ! 376: buf points to external-format byteorder array. ! 377: */ ! 378: { ! 379: word32 w0,w1,w2,w3; ! 380: /* Assume MSB external byte ordering */ ! 381: w3 = *buf++; ! 382: w2 = *buf++; ! 383: w1 = *buf++; ! 384: w0 = *buf++; ! 385: return(w0 + (w1<<8) + (w2<<16) + (w3<<24)); ! 386: } /* fetch_word32 */ ! 387: ! 388: ! 389: byte *put_word32(word32 w, byte *buf) ! 390: /* Puts a 32-bit word to where byte pointer is pointing, and ! 391: returns updated byte pointer. ! 392: buf points to external-format byteorder array. ! 393: */ ! 394: { ! 395: /* Assume MSB external byte ordering */ ! 396: buf[3] = w & 0xff; ! 397: w = w>>8; ! 398: buf[2] = w & 0xff; ! 399: w = w>>8; ! 400: buf[1] = w & 0xff; ! 401: w = w>>8; ! 402: buf[0] = w & 0xff; ! 403: return(buf+4); ! 404: } /* put_word32 */ ! 405: ! 406: ! 407: /*** End of functions that must be changed if the external byteorder ! 408: changes for integer fields in PGP packets. ! 409: ***/ ! 410: ! 411: ! 412: ! 413: ! 414: short mpi2reg(register unitptr r,register byteptr buf) ! 415: /* ! 416: * Converts a multiprecision integer from the externally-represented ! 417: * form of a byte array with a 16-bit bitcount in a leading length ! 418: * word to the internally-used representation as a unit array. ! 419: * Converts to INTERNAL byte order. ! 420: * The same buffer address may be used for both r and buf. ! 421: * Returns number of units in result, or returns -1 on error. ! 422: */ ! 423: { ! 424: byte buf2[MAX_BYTE_PRECISION]; ! 425: word16 bitcount, bytecount, unitcount, zero_bytes, i; ! 426: ! 427: /* First, extract 16-bit bitcount prefix from first 2 bytes... */ ! 428: bitcount = fetch_word16(buf); ! 429: buf += 2; ! 430: ! 431: /* Convert bitcount to bytecount and unitcount... */ ! 432: bytecount = bits2bytes(bitcount); ! 433: unitcount = bytes2units(bytecount); ! 434: if (unitcount > global_precision) { ! 435: /* precision overflow during conversion. */ ! 436: return(-1); /* precision overflow -- error return */ ! 437: } ! 438: zero_bytes = units2bytes(global_precision) - bytecount; ! 439: /* Assume MSB external byte ordering */ ! 440: fill0(buf2,zero_bytes); /* fill leading zero bytes */ ! 441: i = zero_bytes; /* assumes MSB first */ ! 442: while (bytecount--) buf2[i++] = *buf++; ! 443: ! 444: mp_convert_order(buf2); /* convert to INTERNAL byte order */ ! 445: mp_move(r,(unitptr)buf2); ! 446: mp_burn((unitptr)buf2); /* burn the evidence on the stack */ ! 447: return(unitcount); /* returns unitcount of reg */ ! 448: } /* mpi2reg */ ! 449: ! 450: ! 451: short reg2mpi(register byteptr buf,register unitptr r) ! 452: /* ! 453: * Converts the multiprecision integer r from the internal form of ! 454: * a unit array to the normalized externally-represented form of a ! 455: * byte array with a leading 16-bit bitcount word in buf[0] and buf[1]. ! 456: * This bitcount length prefix is exact count, not rounded up. ! 457: * Converts to EXTERNAL byte order. ! 458: * The same buffer address may be used for both r and buf. ! 459: * Returns the number of bytes of the result, not counting length prefix. ! 460: */ ! 461: { ! 462: byte buf1[MAX_BYTE_PRECISION]; ! 463: byteptr buf2; ! 464: short bytecount,bc; ! 465: word16 bitcount; ! 466: bitcount = countbits(r); ! 467: #ifdef DEBUG ! 468: if (bitcount > MAX_BIT_PRECISION) { ! 469: fprintf(stderr, "reg2mpi: bitcount out of range (%d)\n", bitcount); ! 470: return 0; ! 471: } ! 472: #endif ! 473: bytecount = bits2bytes(bitcount); ! 474: bc = bytecount; /* save bytecount for return */ ! 475: buf2 = buf1; ! 476: mp_move((unitptr)buf2,r); ! 477: mp_convert_order(buf2); /* convert to EXTERNAL byteorder */ ! 478: /* Assume MSB external byte ordering */ ! 479: buf2 += units2bytes(global_precision) - bytecount; ! 480: buf = put_word16(bitcount, buf); /* store bitcount in external byteorder */ ! 481: ! 482: while (bytecount--) *buf++ = *buf2++; ! 483: ! 484: mp_burn((unitptr)buf1); /* burn the evidence on the stack */ ! 485: return(bc); /* returns bytecount of mpi, not counting prefix */ ! 486: } /* reg2mpi */ ! 487: ! 488: ! 489: #ifdef DEBUG ! 490: ! 491: void dumpbuf(string s, byteptr buf, int bytecount) ! 492: /* Dump buffer in hex, with string label prefix. */ ! 493: { ! 494: putstr(s); ! 495: while (bytecount--) { ! 496: puthexbyte(*buf++); ! 497: putchar(' '); ! 498: if ((bytecount & 0x0f)==0) ! 499: putchar('\n'); ! 500: } ! 501: } /* dumpbuf */ ! 502: ! 503: void dump_unit_array(string s, unitptr r) ! 504: /* ! 505: * Dump unit array r as a C array initializer, with string label prefix. ! 506: * Array is dumped in native unit order. ! 507: */ ! 508: { ! 509: int unitcount; ! 510: unitcount = global_precision; ! 511: putstr(s); ! 512: putstr("\n{ "); ! 513: while (unitcount--) { ! 514: putstr("0x"); ! 515: puthexunit(*r++); ! 516: putchar(','); ! 517: if (unitcount && ((unitcount & 0x07)==0)) ! 518: putstr("\n "); ! 519: } ! 520: putstr(" 0};\n"); ! 521: } /* dump_unit_array */ ! 522: ! 523: #endif /* ifdef DEBUG */ ! 524: ! 525: /************ end of multiprecision integer I/O library *****************/ ! 526:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.