Annotation of pgp/src/mpiio.c, revision 1.1.1.8

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 *****************/

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.