ran_prim.cpp
上传用户:nbcables
上传日期:2007-01-11
资源大小:1243k
文件大小:17k
源码类别:

钩子与API截获

开发平台:

Visual C++

  1. /* random and prime functions
  2.  */
  3. #include "stdafx.h"
  4. #include "rsaref.h"
  5. #include "big_num.h"
  6. /*
  7.  *Random function
  8.  */
  9. #define RANDOM_BYTES_NEEDED 256
  10. int R_RandomInit (R_RANDOM_STRUCT *randomStruct)
  11. {
  12.   randomStruct->bytesNeeded = RANDOM_BYTES_NEEDED;
  13.   R_memset ((POINTER)randomStruct->state, 0, sizeof (randomStruct->state));
  14.   randomStruct->outputAvailable = 0;
  15.   
  16.   return (0);
  17. }
  18. int R_RandomUpdate (R_RANDOM_STRUCT *randomStruct, unsigned char *block, unsigned int blockLen)
  19. {
  20.   LOCAL_MD5_CTX context;
  21.   unsigned char digest[16];
  22.   unsigned int i, x;
  23.   
  24.   LOCAL_MD5Init (&context);
  25.   LOCAL_MD5Update (&context, block, blockLen);
  26.   LOCAL_MD5Final (digest, &context);
  27.   /* add digest to state */
  28.   x = 0;
  29.   for (i = 0; i < 16; i++) {
  30.     x += randomStruct->state[15-i] + digest[15-i];
  31.     randomStruct->state[15-i] = (unsigned char)x;
  32.     x >>= 8;
  33.   }
  34.   
  35.   if (randomStruct->bytesNeeded < blockLen)
  36.     randomStruct->bytesNeeded = 0;
  37.   else
  38.     randomStruct->bytesNeeded -= blockLen;
  39.   
  40.   /* Zeroize sensitive information.
  41.    */
  42.   R_memset ((POINTER)digest, 0, sizeof (digest));
  43.   x = 0;
  44.   
  45.   return (0);
  46. }
  47. void R_RandomFinal (R_RANDOM_STRUCT *randomStruct)
  48. {
  49.   R_memset ((POINTER)randomStruct, 0, sizeof (*randomStruct));
  50. }
  51. int R_GetRandomBytesNeeded (unsigned int *bytesNeeded, R_RANDOM_STRUCT *randomStruct)
  52. {
  53.   *bytesNeeded = randomStruct->bytesNeeded;
  54.   
  55.   return (0);
  56. }
  57. int R_GenerateBytes (unsigned char *block, unsigned int blockLen, R_RANDOM_STRUCT *randomStruct)
  58. {
  59.   LOCAL_MD5_CTX context;
  60.   unsigned int available, i;
  61.   
  62.   if (randomStruct->bytesNeeded)
  63.     return (RE_NEED_RANDOM);
  64.   
  65.   available = randomStruct->outputAvailable;
  66.   
  67.   while (blockLen > available) {
  68.     R_memcpy
  69.       ((POINTER)block, (POINTER)&randomStruct->output[16-available],
  70.        available);
  71.     block += available;
  72.     blockLen -= available;
  73.     /* generate new output */
  74.     LOCAL_MD5Init (&context);
  75.     LOCAL_MD5Update (&context, randomStruct->state, 16);
  76.     LOCAL_MD5Final (randomStruct->output, &context);
  77.     available = 16;
  78.     /* increment state */
  79.     for (i = 0; i < 16; i++)
  80.       if (randomStruct->state[15-i]++)
  81.         break;
  82.   }
  83.   R_memcpy 
  84.     ((POINTER)block, (POINTER)&randomStruct->output[16-available], blockLen);
  85.   randomStruct->outputAvailable = available - blockLen;
  86.   return (0);
  87. }
  88. /*
  89.  * Prime function
  90.  */
  91. static unsigned int SMALL_PRIMES[] = { 3, 5, 7, 11 };
  92. #define SMALL_PRIME_COUNT 4
  93. static int ProbablePrime PROTO_LIST ((NN_DIGIT *, unsigned int));
  94. static int SmallFactor PROTO_LIST ((NN_DIGIT *, unsigned int));
  95. static int FermatTest PROTO_LIST ((NN_DIGIT *, unsigned int));
  96. /* Generates a probable prime a between b and c such that a-1 is
  97.    divisible by d.
  98.    Lengths: a[digits], b[digits], c[digits], d[digits].
  99.    Assumes b < c, digits < MAX_NN_DIGITS.
  100.    
  101.    Returns RE_NEED_RANDOM if randomStruct not seeded, RE_DATA if
  102.    unsuccessful.
  103.  */
  104. int GeneratePrime (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_DIGIT *d, unsigned int digits, R_RANDOM_STRUCT *randomStruct)
  105. {
  106.   int status;
  107.   unsigned char block[MAX_NN_DIGITS * NN_DIGIT_LEN];
  108.   NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS];
  109.   /* Generate random number between b and c.
  110.    */
  111.   if (status = R_GenerateBytes (block, digits * NN_DIGIT_LEN, randomStruct))
  112.     return (status);
  113.   NN_Decode (a, digits, block, digits * NN_DIGIT_LEN);
  114.   NN_Sub (t, c, b, digits);
  115.   NN_ASSIGN_DIGIT (u, 1, digits);
  116.   NN_Add (t, t, u, digits);
  117.   NN_Mod (a, a, digits, t, digits);
  118.   NN_Add (a, a, b, digits);
  119.   /* Adjust so that a-1 is divisible by d.
  120.    */
  121.   NN_Mod (t, a, digits, d, digits);
  122.   NN_Sub (a, a, t, digits);
  123.   NN_Add (a, a, u, digits);
  124.   if (NN_Cmp (a, b, digits) < 0)
  125.     NN_Add (a, a, d, digits);
  126.   if (NN_Cmp (a, c, digits) > 0)
  127.     NN_Sub (a, a, d, digits);
  128.   /* Search to c in steps of d.
  129.    */
  130.   NN_Assign (t, c, digits);
  131.   NN_Sub (t, t, d, digits);
  132.   while (! ProbablePrime (a, digits)) {
  133.     if (NN_Cmp (a, t, digits) > 0)
  134.       return (RE_DATA);
  135.     NN_Add (a, a, d, digits);
  136.   }
  137.   return (0);
  138. }
  139. /* Returns nonzero iff a is a probable prime.
  140.    Lengths: a[aDigits].
  141.    Assumes aDigits < MAX_NN_DIGITS.
  142.  */
  143. static int ProbablePrime (NN_DIGIT *a, unsigned int aDigits)
  144. {
  145.   return (! SmallFactor (a, aDigits) && FermatTest (a, aDigits));
  146. }
  147. /* Returns nonzero iff a has a prime factor in SMALL_PRIMES.
  148.    Lengths: a[aDigits].
  149.    Assumes aDigits < MAX_NN_DIGITS.
  150.  */
  151. static int SmallFactor (NN_DIGIT *a, unsigned int aDigits)
  152. {
  153.   int status;
  154.   NN_DIGIT t[1];
  155.   unsigned int i;
  156.   
  157.   status = 0;
  158.   
  159.   for (i = 0; i < SMALL_PRIME_COUNT; i++) {
  160.     NN_ASSIGN_DIGIT (t, SMALL_PRIMES[i], 1);
  161.     if ((aDigits == 1) && ! NN_Cmp (a, t, 1))
  162.       break;
  163.     NN_Mod (t, a, aDigits, t, 1);
  164.     if (NN_Zero (t, 1)) {
  165.       status = 1;
  166.       break;
  167.     }
  168.   }
  169.   
  170.   /* Zeroize sensitive information.
  171.    */
  172.   i = 0;
  173.   R_memset ((POINTER)t, 0, sizeof (t));
  174.   return (status);
  175. }
  176. /* Returns nonzero iff a passes Fermat's test for witness 2.
  177.    (All primes pass the test, and nearly all composites fail.)
  178.      
  179.    Lengths: a[aDigits].
  180.    Assumes aDigits < MAX_NN_DIGITS.
  181.  */
  182. static int FermatTest (NN_DIGIT *a, unsigned int aDigits)
  183. {
  184.   int status;
  185.   NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS];
  186.   
  187.   NN_ASSIGN_DIGIT (t, 2, aDigits);
  188.   NN_ModExp (u, t, a, aDigits, a, aDigits);
  189.   
  190.   status = NN_EQUAL (t, u, aDigits);
  191.   
  192.   /* Zeroize sensitive information.
  193.    */
  194.   R_memset ((POINTER)u, 0, sizeof (u));
  195.   
  196.   return (status);
  197. }
  198. /*
  199.  *digit function
  200.  */
  201. /* Computes a = b * c, where b and c are digits.
  202.    Lengths: a[2].
  203.  */
  204. void NN_DigitMult (NN_DIGIT a[2], NN_DIGIT b, NN_DIGIT c)
  205. {
  206.   NN_DIGIT t, u;
  207.   NN_HALF_DIGIT bHigh, bLow, cHigh, cLow;
  208.   bHigh = (NN_HALF_DIGIT)HIGH_HALF (b);
  209.   bLow = (NN_HALF_DIGIT)LOW_HALF (b);
  210.   cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
  211.   cLow = (NN_HALF_DIGIT)LOW_HALF (c);
  212.   a[0] = (NN_DIGIT)bLow * (NN_DIGIT)cLow;
  213.   t = (NN_DIGIT)bLow * (NN_DIGIT)cHigh;
  214.   u = (NN_DIGIT)bHigh * (NN_DIGIT)cLow;
  215.   a[1] = (NN_DIGIT)bHigh * (NN_DIGIT)cHigh;
  216.   
  217.   if ((t += u) < u)
  218.     a[1] += TO_HIGH_HALF (1);
  219.   u = TO_HIGH_HALF (t);
  220.   
  221.   if ((a[0] += u) < u)
  222.     a[1]++;
  223.   a[1] += HIGH_HALF (t);
  224. }
  225. /* Sets a = b / c, where a and c are digits.
  226.    Lengths: b[2].
  227.    Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be
  228.    normalized.
  229.  */
  230. void NN_DigitDiv (NN_DIGIT *a, NN_DIGIT b[2], NN_DIGIT c)
  231. {
  232.   NN_DIGIT t[2], u, v;
  233.   NN_HALF_DIGIT aHigh, aLow, cHigh, cLow;
  234.   cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
  235.   cLow = (NN_HALF_DIGIT)LOW_HALF (c);
  236.   t[0] = b[0];
  237.   t[1] = b[1];
  238.   /* Underestimate high half of quotient and subtract.
  239.    */
  240.   if (cHigh == MAX_NN_HALF_DIGIT)
  241.     aHigh = (NN_HALF_DIGIT)HIGH_HALF (t[1]);
  242.   else
  243.     aHigh = (NN_HALF_DIGIT)(t[1] / (cHigh + 1));
  244.   u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow;
  245.   v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh;
  246.   if ((t[0] -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u)))
  247.     t[1]--;
  248.   t[1] -= HIGH_HALF (u);
  249.   t[1] -= v;
  250.   /* Correct estimate.
  251.    */
  252.   while ((t[1] > cHigh) ||
  253.          ((t[1] == cHigh) && (t[0] >= TO_HIGH_HALF (cLow)))) {
  254.     if ((t[0] -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow))
  255.       t[1]--;
  256.     t[1] -= cHigh;
  257.     aHigh++;
  258.   }
  259.   /* Underestimate low half of quotient and subtract.
  260.    */
  261.   if (cHigh == MAX_NN_HALF_DIGIT)
  262.     aLow = (NN_HALF_DIGIT)LOW_HALF (t[1]);
  263.   else
  264.     aLow = 
  265.       (NN_HALF_DIGIT)((TO_HIGH_HALF (t[1]) + HIGH_HALF (t[0])) / (cHigh + 1));
  266.   u = (NN_DIGIT)aLow * (NN_DIGIT)cLow;
  267.   v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh;
  268.   if ((t[0] -= u) > (MAX_NN_DIGIT - u))
  269.     t[1]--;
  270.   if ((t[0] -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v)))
  271.     t[1]--;
  272.   t[1] -= HIGH_HALF (v);
  273.   /* Correct estimate.
  274.    */
  275.   while ((t[1] > 0) || ((t[1] == 0) && t[0] >= c)) {
  276.     if ((t[0] -= c) > (MAX_NN_DIGIT - c))
  277.       t[1]--;
  278.     aLow++;
  279.   }
  280.   
  281.   *a = TO_HIGH_HALF (aHigh) + aLow;
  282. }
  283. /*
  284.  * LOCAL_MD5 functions
  285.  */
  286. /* Constants for LOCAL_MD5Transform routine.
  287.  */
  288. #define S11 7
  289. #define S12 12
  290. #define S13 17
  291. #define S14 22
  292. #define S21 5
  293. #define S22 9
  294. #define S23 14
  295. #define S24 20
  296. #define S31 4
  297. #define S32 11
  298. #define S33 16
  299. #define S34 23
  300. #define S41 6
  301. #define S42 10
  302. #define S43 15
  303. #define S44 21
  304. static void LOCAL_MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
  305. static void Encode PROTO_LIST
  306.   ((unsigned char *, UINT4 *, unsigned int));
  307. static void Decode PROTO_LIST
  308.   ((UINT4 *, unsigned char *, unsigned int));
  309. static void LOCAL_MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
  310. static void LOCAL_MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
  311. static unsigned char PADDING[64] = {
  312.   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  313.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  314.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  315. };
  316. /* F, G, H and I are basic LOCAL_MD5 functions.
  317.  */
  318. #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  319. #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  320. #define H(x, y, z) ((x) ^ (y) ^ (z))
  321. #define I(x, y, z) ((y) ^ ((x) | (~z)))
  322. /* ROTATE_LEFT rotates x left n bits.
  323.  */
  324. #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  325. /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
  326.    Rotation is separate from addition to prevent recomputation.
  327.  */
  328. #define FF(a, b, c, d, x, s, ac) { 
  329.     (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); 
  330.     (a) = ROTATE_LEFT ((a), (s)); 
  331.     (a) += (b); 
  332.   }
  333. #define GG(a, b, c, d, x, s, ac) { 
  334.     (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); 
  335.     (a) = ROTATE_LEFT ((a), (s)); 
  336.     (a) += (b); 
  337.   }
  338. #define HH(a, b, c, d, x, s, ac) { 
  339.     (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); 
  340.     (a) = ROTATE_LEFT ((a), (s)); 
  341.     (a) += (b); 
  342.   }
  343. #define II(a, b, c, d, x, s, ac) { 
  344.     (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); 
  345.     (a) = ROTATE_LEFT ((a), (s)); 
  346.     (a) += (b); 
  347.   }
  348. /* LOCAL_MD5 initialization. Begins an LOCAL_MD5 operation, writing a new context.
  349.  */
  350. void LOCAL_MD5Init (LOCAL_MD5_CTX *context)
  351. {
  352.   context->count[0] = context->count[1] = 0;
  353.   /* Load magic initialization constants.
  354.    */
  355.   context->state[0] = 0x67452301;
  356.   context->state[1] = 0xefcdab89;
  357.   context->state[2] = 0x98badcfe;
  358.   context->state[3] = 0x10325476;
  359. }
  360. /* LOCAL_MD5 block update operation. Continues an LOCAL_MD5 message-digest
  361.      operation, processing another message block, and updating the
  362.      context.
  363.  */
  364. void LOCAL_MD5Update (LOCAL_MD5_CTX *context, unsigned char *input, unsigned int inputLen)
  365. {
  366.   unsigned int i, index, partLen;
  367.   /* Compute number of bytes mod 64 */
  368.   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
  369.   /* Update number of bits */
  370.   if ((context->count[0] += ((UINT4)inputLen << 3))
  371.       < ((UINT4)inputLen << 3))
  372.     context->count[1]++;
  373.   context->count[1] += ((UINT4)inputLen >> 29);
  374.   
  375.   partLen = 64 - index;
  376.   
  377.   /* Transform as many times as possible.
  378.    */
  379.   if (inputLen >= partLen) {
  380.     LOCAL_MD5_memcpy
  381.       ((POINTER)&context->buffer[index], (POINTER)input, partLen);
  382.     LOCAL_MD5Transform (context->state, context->buffer);
  383.   
  384.     for (i = partLen; i + 63 < inputLen; i += 64)
  385.       LOCAL_MD5Transform (context->state, &input[i]);
  386.     
  387.     index = 0;
  388.   }
  389.   else
  390.     i = 0;
  391.   
  392.   /* Buffer remaining input */
  393.   LOCAL_MD5_memcpy 
  394.     ((POINTER)&context->buffer[index], (POINTER)&input[i],
  395.      inputLen-i);
  396. }
  397. /* LOCAL_MD5 finalization. Ends an LOCAL_MD5 message-digest operation, writing the
  398.      the message digest and zeroizing the context.
  399.  */
  400. void LOCAL_MD5Final (unsigned char digest[16], LOCAL_MD5_CTX *context)
  401. {
  402.   unsigned char bits[8];
  403.   unsigned int index, padLen;
  404.   /* Save number of bits */
  405.   Encode (bits, context->count, 8);
  406.   /* Pad out to 56 mod 64.
  407.    */
  408.   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
  409.   padLen = (index < 56) ? (56 - index) : (120 - index);
  410.   LOCAL_MD5Update (context, PADDING, padLen);
  411.   
  412.   /* Append length (before padding) */
  413.   LOCAL_MD5Update (context, bits, 8);
  414.   /* Store state in digest */
  415.   Encode (digest, context->state, 16);
  416.   
  417.   /* Zeroize sensitive information.
  418.    */
  419.   LOCAL_MD5_memset ((POINTER)context, 0, sizeof (*context));
  420. }
  421. /* LOCAL_MD5 basic transformation. Transforms state based on block.
  422.  */
  423. static void LOCAL_MD5Transform (UINT4 state[4], unsigned char block[64])
  424. {
  425.   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
  426.   
  427.   Decode (x, block, 64);
  428.   /* Round 1 */
  429.   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
  430.   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
  431.   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
  432.   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
  433.   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
  434.   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
  435.   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
  436.   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
  437.   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
  438.   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
  439.   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  440.   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  441.   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  442.   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  443.   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  444.   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
  445.   /* Round 2 */
  446.   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
  447.   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
  448.   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  449.   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
  450.   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
  451.   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
  452.   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  453.   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
  454.   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
  455.   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  456.   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
  457.   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
  458.   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  459.   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
  460.   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
  461.   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
  462.   /* Round 3 */
  463.   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
  464.   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
  465.   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  466.   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  467.   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
  468.   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
  469.   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
  470.   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  471.   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  472.   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
  473.   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
  474.   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
  475.   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
  476.   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  477.   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  478.   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
  479.   /* Round 4 */
  480.   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
  481.   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
  482.   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  483.   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
  484.   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  485.   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
  486.   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  487.   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
  488.   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
  489.   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  490.   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
  491.   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  492.   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
  493.   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  494.   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
  495.   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
  496.   state[0] += a;
  497.   state[1] += b;
  498.   state[2] += c;
  499.   state[3] += d;
  500.   
  501.   /* Zeroize sensitive information.
  502.    */
  503.   LOCAL_MD5_memset ((POINTER)x, 0, sizeof (x));
  504. }
  505. /* Encodes input (UINT4) into output (unsigned char). Assumes len is
  506.      a multiple of 4.
  507.  */
  508. static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
  509. {
  510.   unsigned int i, j;
  511.   for (i = 0, j = 0; j < len; i++, j += 4) {
  512.     output[j] = (unsigned char)(input[i] & 0xff);
  513.     output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
  514.     output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
  515.     output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
  516.   }
  517. }
  518. /* Decodes input (unsigned char) into output (UINT4). Assumes len is
  519.      a multiple of 4.
  520.  */
  521. static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
  522. {
  523.   unsigned int i, j;
  524.   for (i = 0, j = 0; j < len; i++, j += 4)
  525.     output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
  526.       (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
  527. }
  528. /* Note: Replace "for loop" with standard memcpy if possible.
  529.  */
  530. static void LOCAL_MD5_memcpy (POINTER output, POINTER input, unsigned int len)
  531. {
  532.   unsigned int i;
  533.   
  534.   for (i = 0; i < len; i++)
  535.     output[i] = input[i];
  536. }
  537. /* Note: Replace "for loop" with standard memset if possible.
  538.  */
  539. static void LOCAL_MD5_memset (POINTER output, int value, unsigned int len)
  540. {
  541.   unsigned int i;
  542.   
  543.   for (i = 0; i < len; i++)
  544.     ((char *)output)[i] = (char)value;
  545. }