home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 1231.RSAIO.C < prev    next >
Text File  |  1991-05-25  |  18KB  |  619 lines

  1. /*    C source code for RSA library I/O routines.
  2.     Implemented Nov 86 by Philip Zimmermann
  3.     Last revised 11 Apr 91 by PRZ
  4.  
  5.     Boulder Software Engineering
  6.     3021 Eleventh Street
  7.     Boulder, CO 80304
  8.     (303) 444-4541
  9.  
  10.     (c) Copyright 1986 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.     The external data representation for RSA messages and keys that
  16.     some of these library routines assume is outlined in a paper by 
  17.     Philip Zimmermann, "A Proposed Standard Format for RSA Cryptosystems",
  18.     IEEE Computer, September 1986, Vol. 19 No. 9, pages 21-34.
  19.     Some revisions to this data format have occurred since the paper
  20.     was published.
  21. */
  22.  
  23. /* #define DEBUG */
  24.  
  25.  
  26. #ifndef EMBEDDED    /* not EMBEDDED - not compiling for embedded target */
  27. #include <stdio.h>     /* for printf, etc. */
  28. #else    /* EMBEDDED - compiling for embedded target */
  29. #define NULL (void *)0
  30. #endif
  31.  
  32. #include "rsalib.h"
  33. #define RSAIO
  34. #include "rsaio.h"
  35.  
  36.  
  37. /*----------------- Following procedures relate to I/O ------------------*/
  38.  
  39. int string_length(char *s)
  40.     /* Returns string length, just like strlen() from <string.h> */
  41. {    int i;
  42.     i = 0;
  43.     while (*s++) i++;
  44.     return (i);    
  45. }    /* string_length */
  46.  
  47.  
  48. static int ctox(int c)
  49.     /* Returns integer 0-15 if c is an ASCII hex digit, -1 otherwise. */
  50. {    if ((c >= '0') && (c <= '9'))
  51.         return(c - '0');
  52.     if ((c >= 'a') && (c <= 'f'))
  53.         return((c - 'a') + 10);
  54.     if ((c >= 'A') && (c <= 'F'))
  55.         return((c - 'A') + 10);
  56.     return(-1);        /* error -- not a hex digit */
  57. }    /* ctox */
  58.  
  59.  
  60. int str2reg(unitptr reg,string digitstr)
  61.     /* Converts a possibly-signed digit string into a large binary number.
  62.        Returns assumed radix, derived from suffix 'h','o',b','.' */
  63. {    unit temp[MAX_UNIT_PRECISION],base[MAX_UNIT_PRECISION];
  64.     int c,i;
  65.     boolean minus = FALSE;
  66.     short radix;    /* base 2-16 */
  67.  
  68.     mp_init(reg,0);
  69.     
  70.     i = string_length(digitstr);
  71.     if (i==0) return(10);        /* empty string, assume radix 10 */
  72.     c = digitstr[i-1];        /* get last char in string */
  73.     
  74.     switch (c)    /* classify radix select suffix character */
  75.     {
  76.     case '.':    radix = 10;
  77.             break;
  78.     case 'H':
  79.     case 'h':    radix = 16;
  80.             break;
  81.     case 'O': 
  82.     case 'o':    radix = 8;
  83.             break;
  84.     case 'B':
  85.     case 'b':    radix = 2;    /* caution! 'b' is a hex digit! */
  86.             break;
  87.     default:    radix = 10;
  88.     }
  89.  
  90.     mp_init(base,radix);
  91.     if (minus = (*digitstr == '-')) digitstr++;
  92.     while (c = *digitstr++)
  93.     {    if (c==',') continue;    /* allow commas in number */
  94.         c = ctox(c);
  95.         if ((c < 0) || (c >= radix)) 
  96.             break;    /* scan terminated by any non-digit */
  97.         mp_mult(temp,reg,base);
  98.         mp_move(reg,temp);
  99.         mp_init(temp,c);
  100.         mp_add(reg,temp);
  101.     }
  102.     if (minus) mp_neg(reg);
  103.     return(radix);
  104. } /* str2reg */
  105.  
  106.  
  107. /*    These I/O functions, such as putstr, puthexbyte, and puthexw16, 
  108.     are provided here to avoid the need to link in printf from the 
  109.     C I/O library.  This is handy in an embedded application.
  110. */
  111.  
  112. #ifdef EMBEDDED        /* if compiling for embedded target */
  113. int putchar(int c)    /* standard C library function */
  114. {    /* stub -- replace with putchar suitable for embedded target. */
  115. }    /* putchar */
  116. #endif    /* if compiling for embedded target */
  117.  
  118. void putstr(string s)
  119.     /* Put out null-terminated ASCII string via putchar. */
  120. {    while (*s) putchar(*s++);
  121. }    /* putstr */
  122.  
  123. void puthexbyte(byte b)
  124.     /* Put out byte in ASCII hex via putchar. */
  125. {    static const char *nibs = "0123456789ABCDEF";
  126.     putchar(nibs[b >> 4]);
  127.     putchar(nibs[b & 0x0F]);
  128. }    /* puthexbyte */
  129.  
  130. void puthexw16(word16 w)
  131.     /* Put out 16-bit word in hex, high byte first. */
  132. {    puthexbyte((byte)(w >> 8));
  133.     puthexbyte((byte)(w & 0xFF));
  134. }    /* puthexw16 */
  135.  
  136. #ifdef UNIT32
  137. static void puthexw32(word32 lw)
  138.     /* Puts out 32-bit word in hex, high byte first. */
  139. {    puthexw16((word16)(lw>>16));
  140.     puthexw16((word16)(lw & 0xFFFFL));
  141. }    /* puthexw32 */
  142. #endif    /* UNIT32 */
  143.  
  144.  
  145. #ifdef UNIT8
  146. #define puthexunit(u) puthexbyte(u)
  147. #endif
  148. #ifdef UNIT16
  149. #define puthexunit(u) puthexw16(u)
  150. #endif
  151. #ifdef UNIT32
  152. #define puthexunit(u) puthexw32(u)
  153. #endif
  154.  
  155.  
  156. void fill0(byteptr buf,word16 bytecount)
  157.     /* Zero-fill the byte buffer. */
  158. {    while (bytecount--) *buf++ = 0;
  159. }    /* fill0 */
  160.  
  161.  
  162. int display_in_base(string s,unitptr n,short radix)
  163.     /* Display n in any base, such as base 10.  Returns number of digits. */
  164.     /*    s is string to label the displayed register.
  165.         n is multiprecision integer.
  166.         radix is base, 2-16. 
  167.     */
  168. {
  169.     char buf[MAX_BIT_PRECISION + (MAX_BIT_PRECISION/8) + 2];
  170.     unit r[MAX_UNIT_PRECISION],quotient[MAX_UNIT_PRECISION];
  171.     word16 remainder;
  172.     char *bp = buf;
  173.     char minus = FALSE;
  174.     int places = 0;
  175.     int commaplaces;    /* put commas this many digits apart */
  176.     int i;
  177.  
  178.     /*    If string s is just an ESC char, don't print it.
  179.         It's just to inhibit the \n at the end of the number.
  180.     */
  181.     if ((s[0] != '\033') || (s[1] != '\0'))
  182.         putstr(s);
  183.  
  184.     if ( (radix < 2) || (radix > 16) )
  185.     {    putstr("****\n");    /* radix out of range -- show error */
  186.         return(-1);
  187.     }
  188.     commaplaces = (radix==10 ? 3 : (radix==16 ? 4 :
  189.             (radix==2 ? 8 : (radix==8 ? 8 : 1))));
  190.     mp_move(r,n);
  191.     if ((radix == 10) && mp_tstminus(r))
  192.     {    minus = TRUE;
  193.         mp_neg(r);    /* make r positive */
  194.     }
  195.  
  196.     *bp = '\0';
  197.     do    /* build backwards number string */
  198.     {    if (++places>1)
  199.             if ((places % commaplaces)==1)
  200.                 *++bp = ',';    /* 000,000,000,000 */
  201.         remainder = mp_shortdiv(quotient,r,radix);
  202.         *++bp = "0123456789ABCDEF" [remainder]; /* Isn't C wonderful? */
  203.         mp_move(r,quotient);
  204.     } while (testne(r,0));
  205.     if (minus)
  206.         *++bp = '-';
  207.     
  208.     if (commaplaces!=1)
  209.         while ((++places % commaplaces) != 1)
  210.             *++bp = ' '; /* pad to line up commas */
  211.  
  212.     i = string_length(s);
  213.     while (*bp)
  214.     {    putchar(*bp);
  215.         ++i;
  216.         if ((*bp == ',') || commaplaces==1)
  217.             if (i > (72-commaplaces))
  218.             {    putchar('\n'); 
  219.                 i=string_length(s); 
  220.                 while (i--) putchar(' ');
  221.                 i = string_length(s);
  222.             }
  223.         bp--;
  224.     }
  225.     switch (radix)
  226.     {    /* show suffix character to designate radix */
  227.     case 10: /* decimal */
  228.         putchar('.');
  229.         break;
  230.     case 16: /* hex */
  231.         putchar('h');
  232.         break;
  233.     case 8: /* octal */
  234.         putchar('o');
  235.         break;
  236.     case 2: /* binary */
  237.         putchar('b');
  238.         break;
  239.     default: /* nonstandard radix */
  240.         /* printf("(%d)",radix); */ ;    
  241.     }
  242.  
  243.     if ((s[0] == '\033') && (s[1] == '\0'))
  244.         putchar(' ');    /* supress newline */
  245.     else putchar('\n');
  246.  
  247.     fill0(buf,sizeof(buf));    /* burn the evidence on the stack...*/
  248.     /* Note that local stack arrays r and quotient are now 0 */
  249.     return(places);
  250. }    /* display_in_base */
  251.  
  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.  
  323. short mpi2reg(register unitptr r,register byteptr buf)
  324. /*    Converts a multiprecision integer from the externally-represented 
  325.     form of a byte array with a 16-bit bitcount in a leading length 
  326.     word to the internally-used representation as a unit array.
  327.     Converts to INTERNAL byte order.
  328.     The same buffer address may be used for both r and buf.
  329.     Returns number of units in result, or returns -1 on error.
  330. */
  331. {    byte buf2[MAX_BYTE_PRECISION];
  332.     word16 bytecount, unitcount, zero_bytes, i;
  333.     word16 lowcount,highcount;
  334.  
  335.     /* First, extract 16-bit bitcount prefix from first 2 bytes... */
  336. #ifdef XHIGHFIRST
  337.     highcount = *buf++;
  338.     lowcount = *buf++;
  339. #else
  340.     lowcount = *buf++;
  341.     highcount = *buf++;
  342. #endif
  343.     /* Convert bitcount to bytecount and unitcount... */    
  344.     bytecount = bits2bytes(byteglue(lowcount,highcount));
  345.     unitcount = bytes2units(bytecount);
  346.     if (unitcount > global_precision)
  347.     {    /* precision overflow during conversion. */
  348.         return(-1);    /* precision overflow -- error return */
  349.     }
  350.     zero_bytes = units2bytes(global_precision) - bytecount;
  351.  
  352. #ifdef XHIGHFIRST
  353.     fill0(buf2,zero_bytes);  /* fill leading zero bytes */
  354.     i = zero_bytes;
  355. #else
  356.     fill0(buf2+bytecount,zero_bytes);  /* fill trailing zero bytes */
  357.     i = 0;
  358. #endif
  359.     while (bytecount--) buf2[i++] = *buf++;
  360.  
  361.     convert_order(buf2);    /* convert to INTERNAL byte order */
  362.     mp_move(r,(unitptr)buf2);
  363.     mp_burn((unitptr)buf2);    /* burn the evidence on the stack */
  364.     return(unitcount);    /* returns unitcount of reg */
  365. }    /* mpi2reg */
  366.  
  367.  
  368. short reg2mpi(register byteptr buf,register unitptr r)
  369. /*    Converts the multiprecision integer r from the internal form of 
  370.     a unit array to the normalized externally-represented form of a 
  371.     byte array with a leading 16-bit bitcount word in buf[0] and buf[1].
  372.     This bitcount length prefix is exact count, not rounded up.
  373.     Converts to EXTERNAL byte order.
  374.     The same buffer address may be used for both r and buf.
  375.     Returns the number of bytes of the result, not counting length prefix.
  376. */
  377. {    byte buf1[MAX_BYTE_PRECISION];
  378.     byteptr buf2;
  379.     short bytecount,bc;
  380.     word16 bitcount;
  381.     bitcount = countbits(r);
  382.     bytecount = bits2bytes(bitcount);
  383.     bc = bytecount;    /* save bytecount for return */
  384.     buf2 = buf1;
  385.     mp_move((unitptr)buf2,r);
  386.     convert_order(buf2);    /* convert to EXTERNAL byte order */
  387. #ifdef XHIGHFIRST    
  388.     /* Skip over leading zero bytes. */
  389.     buf2 += (units2bytes(global_precision) - bytecount);
  390.     *buf++ = bitcount >> 8;        /* store bitcount with high byte first */
  391.     *buf++ = bitcount & 0xff;
  392. #else
  393.     *buf++ = bitcount & 0xff;    /* store bitcount with low byte first */
  394.     *buf++ = bitcount >> 8;
  395. #endif    /* not XHIGHFIRST */
  396.  
  397.     while (bytecount--) *buf++ = *buf2++;
  398.  
  399.     mp_burn((unitptr)buf1);    /* burn the evidence on the stack */
  400.     return(bc);        /* returns bytecount of mpi, not counting prefix */
  401. }    /* reg2mpi */
  402.  
  403.  
  404. #ifdef DEBUG
  405.  
  406. void dumpbuf(string s, byteptr buf, int bytecount)
  407.     /* Dump buffer in hex, with string label prefix. */
  408. {    putstr(s);
  409.     while (bytecount--)
  410.     {    puthexbyte(*buf++);
  411.         putchar(' ');
  412.         if ((bytecount & 0x0f)==0)
  413.             putchar('\n');
  414.     }
  415. } /* dumpbuf */
  416.  
  417. void dump_unit_array(string s, unitptr r)
  418. /*    Dump unit array r as a C array initializer, with string label prefix. 
  419.     Array is dumped in native unit order.
  420. */
  421. {    int unitcount;
  422.     unitcount = significance(r);
  423.     putstr(s);
  424.     putstr("\n{ ");
  425.     while (unitcount--)
  426.     {    putstr("0x");
  427.         puthexunit(*r++);
  428.         putchar(',');
  429.         if (unitcount && ((unitcount & 0x07)==0))
  430.             putstr("\n  ");
  431.     }
  432.     putstr(" 0};\n");
  433. } /* dump_unit_array */
  434.  
  435. #endif    /* ifdef DEBUG */
  436.  
  437.  
  438. /*
  439. **    short preblock(outreg, inbuf, bytecount, modulus, cksbit, randompad)
  440. **
  441. **    A plaintext message must be converted into an integer less than
  442. **    the modulus n.  We do this by making it 1 byte shorter than the
  443. **    normalized modulus n.  Short blocks are left justified and padded.
  444. **    The last pad byte is a count of how many pad bytes were required,
  445. **    including itself.  Then the 16-bit checksum is appended.
  446. **
  447. **    When using very long keys, if there are more than 255 bytes 
  448. **    of padding, the extra pad bytes will all be 0.  The first 
  449. **    nonzero pad byte from the end will contain the count of the 
  450. **    pad bytes preceding it, which should be 255 if there were more 
  451. **    than 255 total pad bytes.
  452. **
  453. **    For example, suppose the 5-byte string "hello" were the plaintext
  454. **    that needed preblocking, and the modulus was 11 bytes long, and
  455. **    nonrandom padding with a 16-bit checksum was applied.  Here it is 
  456. **    after preblocking, assuming an LSB-first external format:
  457. **    (LSB)                              (MSB)
  458. **    'h','e','l','l','o',1,2,3,low_checksum,high_checksum,0,<slop zeros>
  459. **
  460. **    But if XHIGHFIRST were defined, it would be blocked this way:
  461. **             (MSB)                              (LSB)
  462. **    <slop zeros>,0,'h','e','l','l','o',1,2,3,high_checksum,low_checksum
  463. */
  464. short preblock(unitptr outreg, byteptr inbuf, short bytecount,
  465.     unitptr modulus, boolean cksbit, byteptr randompad)
  466. /*    Converts plaintext block into form suitable for RSA encryption.
  467.     Converts to INTERNAL byte order.
  468.     Returns # of bytes remaining to process.  Note that the same buffer 
  469.     address may be used for both outreg and inbuf.
  470.     cksbit is TRUE iff checksum word should be appended to block.
  471.     randompad is a pointer to a buffer of random pad bytes to use for 
  472.     padding material, or NULL iff we want to use constant padding.
  473. */
  474. {    byte out[MAX_BYTE_PRECISION];
  475.     byte pad;
  476.     short i,byte_precision,leading_zeros,remaining,blocksize,padsize;
  477.     short excess_pads;    /* number of trailing zeros in long pads */
  478.     short startbyte;
  479.     word16 chksum;
  480.  
  481.     byte_precision = units2bytes(global_precision);
  482.     leading_zeros = byte_precision - countbytes(modulus) + 1;
  483.     blocksize = byte_precision - leading_zeros - (2*cksbit);
  484.     /* note that blocksize includes data plus pad bytes, if any */
  485.  
  486.     remaining = bytecount - blocksize;
  487.     if (remaining>=0) 
  488.         bytecount = blocksize;
  489.     padsize = blocksize - bytecount;    /* bytes of padding */
  490.     pad = 0;
  491.     i = 0;
  492.  
  493. #ifdef XHIGHFIRST
  494.     while (leading_zeros--)    
  495.         out[i++] = 0;
  496. #endif
  497.     startbyte = i;
  498.     while (bytecount--)        /* copy user data */
  499.         out[i++] = *inbuf++;
  500.  
  501.     /* Handle pad lengths in excess of 255 bytes... */
  502.     excess_pads = 0;
  503.     if (padsize > 255) 
  504.         excess_pads = padsize - 255;    /* compute spillage */
  505.     padsize -= excess_pads;    /* do not allow padsize > 255 */
  506.  
  507.     /* Perform either random padding or constant padding... */
  508.     if (randompad != NULL)    /* random pad buffer provided? */ 
  509.     {    while (padsize-- > 1)
  510.         {    ++pad;
  511.             out[i++] = *randompad++; /* use random pad bytes */
  512.         }
  513.         padsize++;    /* correct last padsize-- */
  514.     }    /* end of random padding */
  515.  
  516.     while ( padsize-- > 0 )    
  517.         out[i++] = ++pad;
  518.  
  519.     while (excess_pads--)    /* only if more than 255 pad bytes */
  520.         out[i++] = 0;        /* excess padding is zeros */
  521.  
  522.     /* End of padding logic */
  523.  
  524.     if (cksbit) 
  525.     {    chksum = checksum(out+startbyte,blocksize);
  526. #ifdef XHIGHFIRST    
  527.         out[i++] = chksum >> 8; /* store checksum with high byte first */
  528.         out[i++] = chksum & 0xff;
  529. #else
  530.         out[i++] = chksum & 0xff; /* store checksum with low byte first */
  531.         out[i++] = chksum >> 8;
  532. #endif    /* not XHIGHFIRST */
  533.     }
  534.  
  535. #ifndef XHIGHFIRST
  536.     while (leading_zeros--)    
  537.         out[i++] = 0;
  538. #endif
  539.     mp_move(outreg,(unitptr)out);
  540.     mp_burn((unitptr)out); /* burn the evidence on the stack */
  541.     convert_order(outreg);    /* convert outreg to INTERNAL byte order */
  542.     return(remaining);    /* less than 0 if there was padding */
  543. }    /* preblock */
  544.  
  545.  
  546. short postunblock(byteptr outbuf, unitptr inreg,
  547.     unitptr modulus, boolean padded, boolean cksbit)
  548. /*    Converts a just-decrypted RSA block back into unblocked plaintext form.
  549.     Converts to EXTERNAL byte order.
  550.     See the notes on preblocking in the preblock routine above.
  551.     Note that outbuf must be at least as large as inreg.
  552.     The same buffer address may be used for both outbuf and inreg.
  553.     padded is TRUE iff block is expected to contain pad bytes.
  554.     cksbit is TRUE iff block is expected to contain checksum word.
  555.     Returns positive bytecount of plaintext, or negative error status.
  556. */
  557. {    short i,byte_precision,leading_zeros,bytecount,blocksize;
  558.     word16 chksum,chksumlo,chksumhi;
  559.     word16 padsize;
  560.  
  561.     byte_precision = units2bytes(global_precision);
  562.     leading_zeros = byte_precision - countbytes(modulus) + 1;
  563.     blocksize = byte_precision - leading_zeros - (2*cksbit);
  564.     /* note that blocksize includes data plus pad bytes, if any */
  565.  
  566.     mp_move((unitptr)outbuf,inreg);
  567.     convert_order(outbuf);    /* convert to EXTERNAL byte order */
  568.  
  569. #ifndef XHIGHFIRST
  570. #define    STARTBYTE 0
  571. #else
  572. #define STARTBYTE leading_zeros
  573. #endif
  574.     if (cksbit)
  575.     {
  576. #ifdef XHIGHFIRST
  577.         chksumhi = outbuf[STARTBYTE+blocksize];
  578.         chksumlo = outbuf[STARTBYTE+blocksize+1];
  579. #else
  580.         chksumlo = outbuf[STARTBYTE+blocksize];
  581.         chksumhi = outbuf[STARTBYTE+blocksize+1];
  582. #endif
  583.         chksum = byteglue(chksumlo,chksumhi);
  584.  
  585.         if ( chksum != checksum(outbuf+STARTBYTE,blocksize) )
  586.             return(-1);    /* return checksum error */
  587.     }    /* checkum expected */
  588.  
  589.     padsize = 0;
  590.     if (padded)
  591.     {    i = STARTBYTE+blocksize-1;
  592.         while (outbuf[i] == 0)    /* clip off null excess pad bytes */
  593.         {    padsize++; i--;
  594.         }
  595.         padsize += outbuf[i];
  596.     }
  597.  
  598.     if (padsize > blocksize)
  599.     {    /* Error - pad count out of range. */
  600.         padsize = 0; /* bogus padding means no padding */
  601.         return(-2);    /* pad count out of range -- error return */
  602.     }
  603.     bytecount = blocksize - padsize;
  604.  
  605. #ifdef XHIGHFIRST
  606.     i = 0;
  607.     while (i++ < bytecount)
  608.         outbuf[i-1] = outbuf[STARTBYTE+i-1];
  609. #endif
  610.     i = bytecount;
  611.     while (i < byte_precision) 
  612.         outbuf[i++] = 0;
  613.     return(bytecount);    /* normal return */
  614. #undef STARTBYTE
  615. }    /* postunblock */
  616.  
  617. /****************** end of RSA I/O library ************************/
  618.  
  619.