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

1.1       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:        bytecount = bits2bytes(bitcount);
                    470:        bc = bytecount; /* save bytecount for return */
                    471:        buf2 = buf1;
                    472:        mp_move((unitptr)buf2,r);
                    473:        mp_convert_order(buf2); /* convert to EXTERNAL byteorder */
                    474: #ifndef XLOWFIRST
                    475:        buf2 += units2bytes(global_precision) - bytecount;
                    476: #endif
                    477:        buf = put_word16(bitcount, buf); /* store bitcount in external byteorder */
                    478: 
                    479:        while (bytecount--) *buf++ = *buf2++;
                    480: 
                    481:        mp_burn((unitptr)buf1); /* burn the evidence on the stack */
                    482:        return(bc);             /* returns bytecount of mpi, not counting prefix */
                    483: }      /* reg2mpi */
                    484: 
                    485: 
                    486: #ifdef DEBUG
                    487: 
                    488: void dumpbuf(string s, byteptr buf, int bytecount)
                    489:        /* Dump buffer in hex, with string label prefix. */
                    490: {      putstr(s);
                    491:        while (bytecount--)
                    492:        {       puthexbyte(*buf++);
                    493:                putchar(' ');
                    494:                if ((bytecount & 0x0f)==0)
                    495:                        putchar('\n');
                    496:        }
                    497: } /* dumpbuf */
                    498: 
                    499: void dump_unit_array(string s, unitptr r)
                    500: /*     Dump unit array r as a C array initializer, with string label prefix. 
                    501:        Array is dumped in native unit order.
                    502: */
                    503: {      int unitcount;
                    504:        unitcount = global_precision;
                    505:        putstr(s);
                    506:        putstr("\n{ ");
                    507:        while (unitcount--)
                    508:        {       putstr("0x");
                    509:                puthexunit(*r++);
                    510:                putchar(',');
                    511:                if (unitcount && ((unitcount & 0x07)==0))
                    512:                        putstr("\n  ");
                    513:        }
                    514:        putstr(" 0};\n");
                    515: } /* dump_unit_array */
                    516: 
                    517: #endif /* ifdef DEBUG */
                    518: 
                    519: 
                    520: /*
                    521: **     short preblock(outreg, inbuf, bytecount, modulus, randompad)
                    522: **
                    523: **     A plaintext message must be converted into an integer less than
                    524: **     the modulus n.  We do this by making it 1 byte shorter than the
                    525: **     normalized modulus n.  Short blocks are left justified and padded.
                    526: **
                    527: **     The padding used depends on whether randompad is NULL.  First a
                    528: **     0 byte is added beyond the data; then either 0xff's or values
                    529: **     from randompad are added.  Last is a byte which tells whether
                    530: **     we are preblocking a message digest or a conventional key; we
                    531: **     assume that random padding is only used for conventional keys.
                    532: **
                    533: */
                    534: short preblock(unitptr outreg, byteptr inbuf, short bytecount,
                    535:        unitptr modulus, byteptr randompad)
                    536: /*     Converts plaintext block into form suitable for RSA encryption.
                    537:        Converts to INTERNAL byte order.
                    538:        Returns # of bytes remaining to process.  Note that the same buffer 
                    539:        address may be used for both outreg and inbuf.
                    540:        randompad is a pointer to a buffer of random pad bytes to use for 
                    541:        padding material, or NULL iff we want to use constant padding.
                    542: */
                    543: {      byte out[MAX_BYTE_PRECISION];
                    544:        short byte_precision,leading_zeros,remaining,blocksize,padsize;
                    545:        short excess_pads;      /* number of trailing zeros in long pads */
                    546:        int i;
                    547: 
                    548:        byte_precision = units2bytes(global_precision);
                    549:        leading_zeros = byte_precision - countbytes(modulus) + 1;
                    550:        blocksize = byte_precision - leading_zeros;
                    551:        /* note that blocksize includes data plus pad bytes, if any */
                    552: 
                    553:        remaining = bytecount - blocksize;
                    554:        if (remaining>=0)
                    555:                bytecount = blocksize;
                    556:        padsize = blocksize - bytecount;        /* bytes of padding */
                    557:        i = 0;
                    558: 
                    559: #ifndef XLOWFIRST
                    560:        while (leading_zeros--) /* assumes MSB first */
                    561:                out[i++] = 0;
                    562: #endif
                    563:        while (bytecount--)             /* copy user data */
                    564:                out[i++] = *inbuf++;
                    565: 
                    566:        out     [i++] = 0;                      /* Always start with a 0 for padding */
                    567: 
                    568:        /* Pad with either 0xff or values from randompad */
                    569: #ifdef XLOWFIRST
                    570:        while (i < blocksize - 1)
                    571: #else
                    572:        while (i < byte_precision - 1)
                    573: #endif
                    574:                out[i++] = randompad ? *randompad++ : 0xff;
                    575: 
                    576:        /* End with type byte, which we deduce from randompad */
                    577:        out[i++] = randompad ? CK_ENCRYPTED_BYTE : MD_ENCRYPTED_BYTE;
                    578: 
                    579:        /* End of padding logic */
                    580: 
                    581: #ifdef XLOWFIRST
                    582:        while (leading_zeros--) /* assumes LSB first */
                    583:                out[i++] = 0;
                    584: #endif
                    585:        mp_move(outreg,(unitptr)out);
                    586:        mp_burn((unitptr)out); /* burn the evidence on the stack */
                    587:        mp_convert_order((byte *)outreg);       /* convert outreg to INTERNAL byte order */
                    588:        return(remaining);      /* less than 0 if there was padding */
                    589: }      /* preblock */
                    590: 
                    591: 
                    592: short postunblock(byteptr outbuf, unitptr inreg, unitptr modulus)
                    593: /*     Converts a just-decrypted RSA block back into unblocked plaintext form.
                    594:        Converts to EXTERNAL byte order.
                    595:        See the notes on preblocking in the preblock routine above.
                    596:        Note that outbuf must be at least as large as inreg.
                    597:        The same buffer address may be used for both outbuf and inreg.
                    598:        Returns positive bytecount of plaintext, or negative error status.
                    599: */
                    600: {      short i,byte_precision,leading_zeros,bytecount,blocksize;
                    601:        boolean constpad;
                    602: 
                    603:        byte_precision = units2bytes(global_precision);
                    604:        leading_zeros = byte_precision - countbytes(modulus) + 1;
                    605:        blocksize = byte_precision - leading_zeros;
                    606:        /* note that blocksize includes data plus pad bytes, if any */
                    607: 
                    608:        mp_move((unitptr)outbuf,inreg);
                    609:        mp_convert_order(outbuf);       /* convert to EXTERNAL byte order */
                    610: 
                    611:        /* Check high byte, make sure it's legal, figure out padding type */
                    612: #ifdef XLOWFIRST
                    613:        i = blocksize - 1;
                    614: #else
                    615:        i = byte_precision - 1;
                    616: #endif
                    617:        if (outbuf[i] == MD_ENCRYPTED_BYTE)
                    618:                constpad = 1;
                    619:        else if (outbuf[i] == CK_ENCRYPTED_BYTE)
                    620:                constpad = 0;
                    621:        else
                    622:                return(-1);
                    623: 
                    624:        /* Scan down for the 0 byte that ends padding */
                    625:        while (--i > 0  &&  outbuf[i])
                    626:                if (constpad && outbuf[i] != 0xff)
                    627:                        return(-1);
                    628: 
                    629: #ifdef XLOWFIRST
                    630:        bytecount = i;
                    631: #else
                    632:        bytecount = i - leading_zeros;
                    633:        if (leading_zeros)
                    634:                for (i = 0; i < bytecount; ++i)
                    635:                        outbuf[i] = outbuf[i+leading_zeros];
                    636: #endif
                    637: 
                    638:        /* Zero out high part of buffer to make it look nice */
                    639:        while (i < byte_precision)
                    640:                outbuf[i++] = 0;
                    641: 
                    642:        return(bytecount);      /* normal return */
                    643: }      /* postunblock */
                    644: 
                    645: /************ end of muliprecision integer I/O library *****************/
                    646: 

unix.superglobalmegacorp.com

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