|
|
1.1.1.2 ! 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-92 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: ! 43: /*----------------- Following procedures relate to I/O ------------------*/ ! 44: ! 45: int string_length(char *s) ! 46: /* Returns string length, just like strlen() from <string.h> */ ! 47: { int i; ! 48: i = 0; ! 49: if (s != NULL) ! 50: while (*s++) i++; ! 51: return (i); ! 52: } /* string_length */ ! 53: ! 54: ! 55: #ifdef DEBUG ! 56: static int ctox(int c) ! 57: /* Returns integer 0-15 if c is an ASCII hex digit, -1 otherwise. */ ! 58: { if ((c >= '0') && (c <= '9')) ! 59: return(c - '0'); ! 60: if ((c >= 'a') && (c <= 'f')) ! 61: return((c - 'a') + 10); ! 62: if ((c >= 'A') && (c <= 'F')) ! 63: return((c - 'A') + 10); ! 64: return(-1); /* error -- not a hex digit */ ! 65: } /* ctox */ ! 66: ! 67: ! 68: int str2reg(unitptr reg,string digitstr) ! 69: /* Converts a possibly-signed digit string into a large binary number. ! 70: Returns assumed radix, derived from suffix 'h','o',b','.' */ ! 71: { unit temp[MAX_UNIT_PRECISION],base[MAX_UNIT_PRECISION]; ! 72: int c,i; ! 73: boolean minus = FALSE; ! 74: short radix; /* base 2-16 */ ! 75: ! 76: mp_init(reg,0); ! 77: ! 78: i = string_length(digitstr); ! 79: if (i==0) return(10); /* empty string, assume radix 10 */ ! 80: c = digitstr[i-1]; /* get last char in string */ ! 81: ! 82: switch (c) /* classify radix select suffix character */ ! 83: { ! 84: case '.': radix = 10; ! 85: break; ! 86: case 'H': ! 87: case 'h': radix = 16; ! 88: break; ! 89: case 'O': ! 90: case 'o': radix = 8; ! 91: break; ! 92: case 'B': ! 93: case 'b': radix = 2; /* caution! 'b' is a hex digit! */ ! 94: break; ! 95: default: radix = 10; ! 96: } ! 97: ! 98: mp_init(base,radix); ! 99: if ((minus = (*digitstr == '-')) != 0) digitstr++; ! 100: while ((c = *digitstr++) != 0) ! 101: { if (c==',') continue; /* allow commas in number */ ! 102: c = ctox(c); ! 103: if ((c < 0) || (c >= radix)) ! 104: break; /* scan terminated by any non-digit */ ! 105: mp_mult(temp,reg,base); ! 106: mp_move(reg,temp); ! 107: mp_init(temp,c); ! 108: mp_add(reg,temp); ! 109: } ! 110: if (minus) mp_neg(reg); ! 111: return(radix); ! 112: } /* str2reg */ ! 113: ! 114: #endif /* DEBUG */ ! 115: ! 116: /* These I/O functions, such as putstr, puthexbyte, and puthexw16, ! 117: are provided here to avoid the need to link in printf from the ! 118: C I/O library. This is handy in an embedded application. ! 119: For embedded applications, use a customized putchar function, ! 120: separately compiled. ! 121: */ ! 122: ! 123: void putstr(string s) ! 124: /* Put out null-terminated ASCII string via putchar. */ ! 125: { while (*s) putchar(*s++); ! 126: } /* putstr */ ! 127: ! 128: void puthexbyte(byte b) ! 129: /* Put out byte in ASCII hex via putchar. */ ! 130: { static char *nibs = "0123456789ABCDEF"; ! 131: putchar(nibs[b >> 4]); ! 132: putchar(nibs[b & 0x0F]); ! 133: } /* puthexbyte */ ! 134: ! 135: void puthexw16(word16 w) ! 136: /* Put out 16-bit word in hex, high byte first. */ ! 137: { puthexbyte((byte)(w >> 8)); ! 138: puthexbyte((byte)(w & 0xFF)); ! 139: } /* puthexw16 */ ! 140: ! 141: #ifdef UNIT32 ! 142: static void puthexw32(word32 lw) ! 143: /* Puts out 32-bit word in hex, high byte first. */ ! 144: { puthexw16((word16)(lw>>16)); ! 145: puthexw16((word16)(lw & 0xFFFFL)); ! 146: } /* puthexw32 */ ! 147: #endif /* UNIT32 */ ! 148: ! 149: ! 150: #ifdef UNIT8 ! 151: #define puthexunit(u) puthexbyte(u) ! 152: #endif ! 153: #ifdef UNIT16 ! 154: #define puthexunit(u) puthexw16(u) ! 155: #endif ! 156: #ifdef UNIT32 ! 157: #define puthexunit(u) puthexw32(u) ! 158: #endif ! 159: ! 160: #ifdef DEBUG ! 161: int display_in_base(string s,unitptr n,short radix) ! 162: /* Display n in any base, such as base 10. Returns number of digits. */ ! 163: /* s is string to label the displayed register. ! 164: n is multiprecision integer. ! 165: radix is base, 2-16. ! 166: */ ! 167: { ! 168: char buf[MAX_BIT_PRECISION + (MAX_BIT_PRECISION/8) + 2]; ! 169: unit r[MAX_UNIT_PRECISION],quotient[MAX_UNIT_PRECISION]; ! 170: word16 remainder; ! 171: char *bp = buf; ! 172: char minus = FALSE; ! 173: int places = 0; ! 174: int commaplaces; /* put commas this many digits apart */ ! 175: int i; ! 176: ! 177: /* If string s is just an ESC char, don't print it. ! 178: It's just to inhibit the \n at the end of the number. ! 179: */ ! 180: if ((s[0] != '\033') || (s[1] != '\0')) ! 181: putstr(s); ! 182: ! 183: if ( (radix < 2) || (radix > 16) ) ! 184: { putstr("****\n"); /* radix out of range -- show error */ ! 185: return(-1); ! 186: } ! 187: commaplaces = (radix==10 ? 3 : (radix==16 ? 4 : ! 188: (radix==2 ? 8 : (radix==8 ? 8 : 1)))); ! 189: mp_move(r,n); ! 190: if ((radix == 10) && mp_tstminus(r)) ! 191: { minus = TRUE; ! 192: mp_neg(r); /* make r positive */ ! 193: } ! 194: ! 195: *bp = '\0'; ! 196: do /* build backwards number string */ ! 197: { if (++places>1) ! 198: if ((places % commaplaces)==1) ! 199: *++bp = ','; /* 000,000,000,000 */ ! 200: remainder = mp_shortdiv(quotient,r,radix); ! 201: *++bp = "0123456789ABCDEF" [remainder]; /* Isn't C wonderful? */ ! 202: mp_move(r,quotient); ! 203: } while (testne(r,0)); ! 204: if (minus) ! 205: *++bp = '-'; ! 206: ! 207: if (commaplaces!=1) ! 208: while ((++places % commaplaces) != 1) ! 209: *++bp = ' '; /* pad to line up commas */ ! 210: ! 211: i = string_length(s); ! 212: while (*bp) ! 213: { putchar(*bp); ! 214: ++i; ! 215: if ((*bp == ',') || commaplaces==1) ! 216: if (i > (72-commaplaces)) ! 217: { putchar('\n'); ! 218: i=string_length(s); ! 219: while (i--) putchar(' '); ! 220: i = string_length(s); ! 221: } ! 222: bp--; ! 223: } ! 224: switch (radix) ! 225: { /* show suffix character to designate radix */ ! 226: case 10: /* decimal */ ! 227: putchar('.'); ! 228: break; ! 229: case 16: /* hex */ ! 230: putchar('h'); ! 231: break; ! 232: case 8: /* octal */ ! 233: putchar('o'); ! 234: break; ! 235: case 2: /* binary */ ! 236: putchar('b'); ! 237: break; ! 238: default: /* nonstandard radix */ ! 239: /* printf("(%d)",radix); */ ; ! 240: } ! 241: ! 242: if ((s[0] == '\033') && (s[1] == '\0')) ! 243: putchar(' '); /* supress newline */ ! 244: else putchar('\n'); ! 245: ! 246: fill0((byteptr)buf,sizeof(buf)); /* burn the evidence on the stack...*/ ! 247: /* Note that local stack arrays r and quotient are now 0 */ ! 248: return(places); ! 249: } /* display_in_base */ ! 250: ! 251: #endif /* DEBUG */ ! 252: ! 253: void mp_display(string s,unitptr r) ! 254: /* Display register r in hex, with prefix string s. */ ! 255: { short precision; ! 256: int i,j; ! 257: putstr(s); ! 258: normalize(r,precision); /* strip off leading zeros */ ! 259: if (precision == 0) ! 260: { putstr(" 0\n"); ! 261: return; ! 262: } ! 263: make_msbptr(r,precision); ! 264: i=0; ! 265: while (precision--) ! 266: { if (!(i++ % (16/BYTES_PER_UNIT))) ! 267: { if (i>1) ! 268: { putchar('\n'); ! 269: j=string_length(s); ! 270: while (j--) putchar(' '); ! 271: } ! 272: } ! 273: puthexunit(*r); ! 274: putchar(' '); ! 275: post_lowerunit(r); ! 276: } ! 277: putchar('\n'); ! 278: } /* mp_display */ ! 279: ! 280: ! 281: word16 checksum(register byteptr buf, register word16 count) ! 282: /* Returns checksum of buffer. */ ! 283: { word16 cs; ! 284: cs = 0; ! 285: while (count--) cs += *buf++; ! 286: return(cs); ! 287: } /* checksum */ ! 288: ! 289: ! 290: void cbc_xor(register unitptr dst, register unitptr src, word16 bytecount) ! 291: /* Performs the XOR necessary for RSA Cipher Block Chaining. ! 292: The dst buffer ought to have 1 less byte of significance than ! 293: the src buffer. Only the least significant part of the src ! 294: buffer is used. bytecount is the size of a plaintext block. ! 295: */ ! 296: { short nunits; /* units of precision */ ! 297: nunits = bytes2units(bytecount)-1; ! 298: make_lsbptr(dst,global_precision); ! 299: while (nunits--) ! 300: { *dst ^= *post_higherunit(src); ! 301: post_higherunit(dst); ! 302: bytecount -= units2bytes(1); ! 303: } ! 304: /* on the last unit, don't xor the excess top byte... */ ! 305: *dst ^= (*src & (power_of_2(bytecount<<3)-1)); ! 306: } /* cbc_xor */ ! 307: ! 308: ! 309: void hiloswap(byteptr r1,short numbytes) ! 310: /* Reverses the order of bytes in an array of bytes. */ ! 311: { byteptr r2; ! 312: byte b; ! 313: r2 = &(r1[numbytes-1]); ! 314: while (r1 < r2) ! 315: { b = *r1; *r1++ = *r2; *r2-- = b; ! 316: } ! 317: } /* hiloswap */ ! 318: ! 319: ! 320: #define byteglue(lo,hi) ((((word16) hi) << 8) + (word16) lo) ! 321: ! 322: /**** The following functions must be changed if the external byteorder ! 323: changes for integers in PGP packet data. ! 324: ****/ ! 325: ! 326: ! 327: word16 fetch_word16(byte *buf) ! 328: /* Fetches a 16-bit word from where byte pointer is pointing. ! 329: buf points to external-format byteorder array. ! 330: */ ! 331: { word16 w0,w1; ! 332: #ifdef XLOWFIRST ! 333: w0 = *buf++; ! 334: w1 = *buf++; ! 335: #else ! 336: w1 = *buf++; ! 337: w0 = *buf++; ! 338: #endif ! 339: return(w0 + (w1<<8)); ! 340: } /* fetch_word16 */ ! 341: ! 342: ! 343: byte *put_word16(word16 w, byte *buf) ! 344: /* Puts a 16-bit word to where byte pointer is pointing, and ! 345: returns updated byte pointer. ! 346: buf points to external-format byteorder array. ! 347: */ ! 348: { ! 349: #ifdef XLOWFIRST ! 350: buf[0] = w & 0xff; ! 351: w = w>>8; ! 352: buf[1] = w & 0xff; ! 353: #else ! 354: buf[1] = w & 0xff; ! 355: w = w>>8; ! 356: buf[0] = w & 0xff; ! 357: #endif ! 358: return(buf+2); ! 359: } /* put_word16 */ ! 360: ! 361: ! 362: word32 fetch_word32(byte *buf) ! 363: /* Fetches a 32-bit word from where byte pointer is pointing. ! 364: buf points to external-format byteorder array. ! 365: */ ! 366: { word32 w0,w1,w2,w3; ! 367: #ifdef XLOWFIRST ! 368: w0 = *buf++; ! 369: w1 = *buf++; ! 370: w2 = *buf++; ! 371: w3 = *buf++; ! 372: #else ! 373: w3 = *buf++; ! 374: w2 = *buf++; ! 375: w1 = *buf++; ! 376: w0 = *buf++; ! 377: #endif ! 378: return(w0 + (w1<<8) + (w2<<16) + (w3<<24)); ! 379: } /* fetch_word32 */ ! 380: ! 381: ! 382: byte *put_word32(word32 w, byte *buf) ! 383: /* Puts a 32-bit word to where byte pointer is pointing, and ! 384: returns updated byte pointer. ! 385: buf points to external-format byteorder array. ! 386: */ ! 387: { ! 388: #ifdef XLOWFIRST ! 389: buf[0] = w & 0xff; ! 390: w = w>>8; ! 391: buf[1] = w & 0xff; ! 392: w = w>>8; ! 393: buf[2] = w & 0xff; ! 394: w = w>>8; ! 395: buf[3] = w & 0xff; ! 396: #else ! 397: buf[3] = w & 0xff; ! 398: w = w>>8; ! 399: buf[2] = w & 0xff; ! 400: w = w>>8; ! 401: buf[1] = w & 0xff; ! 402: w = w>>8; ! 403: buf[0] = w & 0xff; ! 404: #endif ! 405: return(buf+4); ! 406: } /* put_word32 */ ! 407: ! 408: ! 409: /*** End of functions that must be changed if the external byteorder ! 410: changes for integer fields in PGP packets. ! 411: ***/ ! 412: ! 413: ! 414: ! 415: ! 416: short mpi2reg(register unitptr r,register byteptr buf) ! 417: /* Converts a multiprecision integer from the externally-represented ! 418: form of a byte array with a 16-bit bitcount in a leading length ! 419: word to the internally-used representation as a unit array. ! 420: Converts to INTERNAL byte order. ! 421: The same buffer address may be used for both r and buf. ! 422: Returns number of units in result, or returns -1 on error. ! 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: #ifdef XLOWFIRST ! 440: fill0(buf2+bytecount,zero_bytes); /* fill trailing zero bytes */ ! 441: i = 0; /* assumes LSB first */ ! 442: #else ! 443: fill0(buf2,zero_bytes); /* fill leading zero bytes */ ! 444: i = zero_bytes; /* assumes MSB first */ ! 445: #endif ! 446: while (bytecount--) buf2[i++] = *buf++; ! 447: ! 448: mp_convert_order(buf2); /* convert to INTERNAL byte order */ ! 449: mp_move(r,(unitptr)buf2); ! 450: mp_burn((unitptr)buf2); /* burn the evidence on the stack */ ! 451: return(unitcount); /* returns unitcount of reg */ ! 452: } /* mpi2reg */ ! 453: ! 454: ! 455: short reg2mpi(register byteptr buf,register unitptr r) ! 456: /* Converts the multiprecision integer r from the internal form of ! 457: a unit array to the normalized externally-represented form of a ! 458: byte array with a leading 16-bit bitcount word in buf[0] and buf[1]. ! 459: This bitcount length prefix is exact count, not rounded up. ! 460: Converts to EXTERNAL byte order. ! 461: The same buffer address may be used for both r and buf. ! 462: Returns the number of bytes of the result, not counting length prefix. ! 463: */ ! 464: { byte buf1[MAX_BYTE_PRECISION]; ! 465: byteptr buf2; ! 466: short bytecount,bc; ! 467: word16 bitcount; ! 468: bitcount = countbits(r); ! 469: #ifdef DEBUG ! 470: if (bitcount > MAX_BIT_PRECISION) ! 471: { fprintf(stderr, "reg2mpi: bitcount out of range (%d)\n", bitcount); ! 472: return 0; ! 473: } ! 474: #endif ! 475: bytecount = bits2bytes(bitcount); ! 476: bc = bytecount; /* save bytecount for return */ ! 477: buf2 = buf1; ! 478: mp_move((unitptr)buf2,r); ! 479: mp_convert_order(buf2); /* convert to EXTERNAL byteorder */ ! 480: #ifndef XLOWFIRST ! 481: buf2 += units2bytes(global_precision) - bytecount; ! 482: #endif ! 483: buf = put_word16(bitcount, buf); /* store bitcount in external byteorder */ ! 484: ! 485: while (bytecount--) *buf++ = *buf2++; ! 486: ! 487: mp_burn((unitptr)buf1); /* burn the evidence on the stack */ ! 488: return(bc); /* returns bytecount of mpi, not counting prefix */ ! 489: } /* reg2mpi */ ! 490: ! 491: ! 492: #ifdef DEBUG ! 493: ! 494: void dumpbuf(string s, byteptr buf, int bytecount) ! 495: /* Dump buffer in hex, with string label prefix. */ ! 496: { putstr(s); ! 497: while (bytecount--) ! 498: { puthexbyte(*buf++); ! 499: putchar(' '); ! 500: if ((bytecount & 0x0f)==0) ! 501: putchar('\n'); ! 502: } ! 503: } /* dumpbuf */ ! 504: ! 505: void dump_unit_array(string s, unitptr r) ! 506: /* Dump unit array r as a C array initializer, with string label prefix. ! 507: Array is dumped in native unit order. ! 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: ! 526: /* ! 527: ** short preblock(outreg, inbuf, bytecount, modulus, randompad) ! 528: ** ! 529: ** A plaintext message must be converted into an integer less than ! 530: ** the modulus n. We do this by making it 1 byte shorter than the ! 531: ** normalized modulus n. Short blocks are left justified and padded. ! 532: ** ! 533: ** The padding used depends on whether randompad is NULL. First a ! 534: ** 0 byte is added beyond the data; then either 0xff's or values ! 535: ** from randompad are added. Last is a byte which tells whether ! 536: ** we are preblocking a message digest or a conventional key; we ! 537: ** assume that random padding is only used for conventional keys. ! 538: ** ! 539: */ ! 540: short preblock(unitptr outreg, byteptr inbuf, short bytecount, ! 541: unitptr modulus, byteptr randompad) ! 542: /* Converts plaintext block into form suitable for RSA encryption. ! 543: Converts to INTERNAL byte order. ! 544: Returns # of bytes remaining to process. Note that the same buffer ! 545: address may be used for both outreg and inbuf. ! 546: randompad is a pointer to a buffer of random pad bytes to use for ! 547: padding material, or NULL iff we want to use constant padding. ! 548: */ ! 549: { byte out[MAX_BYTE_PRECISION]; ! 550: short byte_precision,leading_zeros,remaining,blocksize,padsize; ! 551: short excess_pads; /* number of trailing zeros in long pads */ ! 552: int i; ! 553: ! 554: byte_precision = units2bytes(global_precision); ! 555: leading_zeros = byte_precision - countbytes(modulus) + 1; ! 556: blocksize = byte_precision - leading_zeros; ! 557: /* note that blocksize includes data plus pad bytes, if any */ ! 558: ! 559: remaining = bytecount - blocksize; ! 560: if (remaining>=0) ! 561: bytecount = blocksize; ! 562: padsize = blocksize - bytecount; /* bytes of padding */ ! 563: i = 0; ! 564: ! 565: #ifndef XLOWFIRST ! 566: while (leading_zeros--) /* assumes MSB first */ ! 567: out[i++] = 0; ! 568: #endif ! 569: while (bytecount--) /* copy user data */ ! 570: out[i++] = *inbuf++; ! 571: ! 572: out [i++] = 0; /* Always start with a 0 for padding */ ! 573: ! 574: /* Pad with either 0xff or values from randompad */ ! 575: #ifdef XLOWFIRST ! 576: while (i < blocksize - 1) ! 577: #else ! 578: while (i < byte_precision - 1) ! 579: #endif ! 580: out[i++] = randompad ? *randompad++ : 0xff; ! 581: ! 582: /* End with type byte, which we deduce from randompad */ ! 583: out[i++] = randompad ? CK_ENCRYPTED_BYTE : MD_ENCRYPTED_BYTE; ! 584: ! 585: /* End of padding logic */ ! 586: ! 587: #ifdef XLOWFIRST ! 588: while (leading_zeros--) /* assumes LSB first */ ! 589: out[i++] = 0; ! 590: #endif ! 591: mp_move(outreg,(unitptr)out); ! 592: mp_burn((unitptr)out); /* burn the evidence on the stack */ ! 593: mp_convert_order((byte *)outreg); /* convert outreg to INTERNAL byte order */ ! 594: return(remaining); /* less than 0 if there was padding */ ! 595: } /* preblock */ ! 596: ! 597: ! 598: short postunblock(byteptr outbuf, unitptr inreg, unitptr modulus) ! 599: /* Converts a just-decrypted RSA block back into unblocked plaintext form. ! 600: Converts to EXTERNAL byte order. ! 601: See the notes on preblocking in the preblock routine above. ! 602: Note that outbuf must be at least as large as inreg. ! 603: The same buffer address may be used for both outbuf and inreg. ! 604: Returns positive bytecount of plaintext, or negative error status. ! 605: */ ! 606: { short i,byte_precision,leading_zeros,bytecount,blocksize; ! 607: boolean constpad; ! 608: ! 609: byte_precision = units2bytes(global_precision); ! 610: leading_zeros = byte_precision - countbytes(modulus) + 1; ! 611: blocksize = byte_precision - leading_zeros; ! 612: /* note that blocksize includes data plus pad bytes, if any */ ! 613: ! 614: mp_move((unitptr)outbuf,inreg); ! 615: mp_convert_order(outbuf); /* convert to EXTERNAL byte order */ ! 616: ! 617: /* Check high byte, make sure it's legal, figure out padding type */ ! 618: #ifdef XLOWFIRST ! 619: i = blocksize - 1; ! 620: #else ! 621: i = byte_precision - 1; ! 622: #endif ! 623: if (outbuf[i] == MD_ENCRYPTED_BYTE) ! 624: constpad = 1; ! 625: else if (outbuf[i] == CK_ENCRYPTED_BYTE) ! 626: constpad = 0; ! 627: else ! 628: return(-1); ! 629: ! 630: /* Scan down for the 0 byte that ends padding */ ! 631: while (--i > 0 && outbuf[i]) ! 632: if (constpad && outbuf[i] != 0xff) ! 633: return(-1); ! 634: ! 635: #ifdef XLOWFIRST ! 636: bytecount = i; ! 637: #else ! 638: bytecount = i - leading_zeros; ! 639: if (leading_zeros) ! 640: for (i = 0; i < bytecount; ++i) ! 641: outbuf[i] = outbuf[i+leading_zeros]; ! 642: #endif ! 643: ! 644: /* Zero out high part of buffer to make it look nice */ ! 645: while (i < byte_precision) ! 646: outbuf[i++] = 0; ! 647: ! 648: return(bytecount); /* normal return */ ! 649: } /* postunblock */ ! 650: ! 651: /************ end of muliprecision integer I/O library *****************/ ! 652:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.