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

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

unix.superglobalmegacorp.com

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