Home | History | Annotate | Download | only in lib
      1 /*
      2  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 #pragma ident	"%Z%%M%	%I%	%E% SMI"
      6 
      7 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
      8  */
      9 
     10 /* Function names changed to avoid namespace collisions: Rob Siemborski */
     11 
     12 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
     13 rights reserved.
     14 
     15 License to copy and use this software is granted provided that it
     16 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
     17 Algorithm" in all material mentioning or referencing this software
     18 or this function.
     19 
     20 License is also granted to make and use derivative works provided
     21 that such works are identified as "derived from the RSA Data
     22 Security, Inc. MD5 Message-Digest Algorithm" in all material
     23 mentioning or referencing the derived work.
     24 
     25 RSA Data Security, Inc. makes no representations concerning either
     26 the merchantability of this software or the suitability of this
     27 software for any particular purpose. It is provided "as is"
     28 without express or implied warranty of any kind.
     29 
     30 These notices must be retained in any copies of any part of this
     31 documentation and/or software.
     32 */
     33 
     34 #include <config.h>
     35 #include "md5global.h"
     36 #ifdef _HAVE_LIB_MD5
     37 /*
     38  * If libmd5 is available, we will use it.
     39  * sasl_hmac_md5* functions are still needed.
     40  */
     41 #include "md5_private.h"
     42 #else
     43 #include "md5.h"
     44 #endif /* _HAVE_LIB_MD5 */
     45 #include "hmac-md5.h"
     46 
     47 #ifndef WIN32
     48 #include <arpa/inet.h>
     49 #endif
     50 
     51 /* Constants for MD5Transform routine.
     52 */
     53 
     54 #define S11 7
     55 #define S12 12
     56 #define S13 17
     57 #define S14 22
     58 #define S21 5
     59 #define S22 9
     60 #define S23 14
     61 #define S24 20
     62 #define S31 4
     63 #define S32 11
     64 #define S33 16
     65 #define S34 23
     66 #define S41 6
     67 #define S42 10
     68 #define S43 15
     69 #define S44 21
     70 
     71 #ifdef _HAVE_LIB_MD5
     72 #define MD5_memcpy(s1, s2, n) memcpy(s1, s2, n)
     73 #define MD5_memset(s1, c, n) memset(s1, c, n)
     74 #else
     75 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
     76 static void Encode PROTO_LIST
     77        ((unsigned char *, UINT4 *, unsigned int));
     78 static void Decode PROTO_LIST
     79        ((UINT4 *, unsigned char *, unsigned int));
     80 static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
     81 static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
     82 
     83 static unsigned char PADDING[64] = {
     84        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     85        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     86 };
     87 #endif /* _HAVE_LIB_MD5 */
     88 
     89 /* F, G, H and I are basic MD5 functions.
     90 
     91         */
     92 #ifdef I
     93 /* This might be defined via NANA */
     94 #undef I
     95 #endif
     96 
     97 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
     98 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
     99 #define H(x, y, z) ((x) ^ (y) ^ (z))
    100 #define I(x, y, z) ((y) ^ ((x) | (~z)))
    101 
    102 /* ROTATE_LEFT rotates x left n bits.
    103 
    104         */
    105 
    106 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
    107 
    108 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
    109 Rotation is separate from addition to prevent recomputation.
    110 */
    111 
    112 #define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s));        (a) += (b);        }
    113 #define GG(a, b, c, d, x, s, ac) {        (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac);        (a) = ROTATE_LEFT ((a), (s));        (a) += (b);         }
    114 #define HH(a, b, c, d, x, s, ac) {        (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac);        (a) = ROTATE_LEFT ((a), (s));        (a) += (b);        }
    115 #define II(a, b, c, d, x, s, ac) {        (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac);        (a) = ROTATE_LEFT ((a), (s));        (a) += (b);        }
    116 
    117 /* MD5 initialization. Begins an MD5 operation, writing a new context.
    118 */
    119 
    120 #ifndef _HAVE_LIB_MD5
    121 void _sasl_MD5Init (context)
    122 MD5_CTX *context; /* context */
    123 {
    124        context->count[0] = context->count[1] = 0;
    125 
    126        /* Load magic initialization constants. */
    127        context->state[0] = 0x67452301;
    128        context->state[1] = 0xefcdab89;
    129        context->state[2] = 0x98badcfe;
    130        context->state[3] = 0x10325476;
    131 }
    132 
    133 /* MD5 block update operation. Continues an MD5 message-digest
    134        operation, processing another message block, and updating the context.
    135 */
    136 
    137 void _sasl_MD5Update (context, input, inputLen)
    138 MD5_CTX *context; /* context */
    139 unsigned char *input; /* input block */
    140 unsigned int inputLen; /* length of input block */
    141 {
    142        unsigned int i, index, partLen;
    143 
    144          /* Compute number of bytes mod 64 */
    145          index = (unsigned int)((context->count[0] >> 3) & 0x3F);
    146 
    147          /* Update number of bits */
    148          if ((context->count[0] += ((UINT4)inputLen << 3))
    149           < ((UINT4)inputLen << 3))
    150         context->count[1]++;
    151          context->count[1] += ((UINT4)inputLen >> 29);
    152 
    153        partLen = 64 - index;
    154 
    155          /* Transform as many times as possible.
    156 
    157 */
    158        if (inputLen >= partLen) {
    159        MD5_memcpy
    160        ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform
    161        (context->state, context->buffer);
    162 
    163        for (i = partLen; i + 63 < inputLen; i += 64)
    164        MD5Transform (context->state, &input[i]);
    165 
    166        index = 0;
    167        }
    168        else
    169        i = 0;
    170 
    171          /* Buffer remaining input */
    172          MD5_memcpy
    173         ((POINTER)&context->buffer[index], (POINTER)&input[i],
    174          inputLen-i);
    175 
    176 }
    177 
    178 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
    179        the message digest and zeroizing the context.
    180 */
    181 
    182 void _sasl_MD5Final (digest, context)
    183 unsigned char digest[16]; /* message digest */
    184 MD5_CTX *context; /* context */
    185 {
    186        unsigned char bits[8];
    187        unsigned int index, padLen;
    188 
    189          /* Save number of bits */
    190          Encode (bits, context->count, 8);
    191 
    192          /* Pad out to 56 mod 64. */
    193 	 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
    194 	 padLen = (index < 56) ? (56 - index) : (120 - index);
    195 	 _sasl_MD5Update (context, PADDING, padLen);
    196 
    197          /* Append length (before padding) */
    198          _sasl_MD5Update (context, bits, 8);
    199 
    200          /* Store state in digest */
    201          Encode (digest, context->state, 16);
    202 
    203          /* Zeroize sensitive information. */
    204        MD5_memset ((POINTER)context, 0, sizeof (*context));
    205 }
    206 
    207 /* MD5 basic transformation. Transforms state based on block. */
    208 
    209 static void MD5Transform (state, block)
    210 UINT4 state[4];
    211 unsigned char block[64];
    212 {
    213        UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
    214 
    215        Decode (x, block, 64);
    216 
    217          /* Round 1 */
    218          FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
    219          FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
    220          FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
    221          FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
    222          FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
    223          FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
    224          FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
    225          FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
    226          FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
    227          FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
    228          FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
    229          FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
    230          FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
    231          FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
    232          FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
    233          FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
    234 
    235         /* Round 2 */
    236          GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
    237          GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
    238          GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
    239          GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
    240          GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
    241          GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
    242          GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
    243          GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
    244          GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
    245          GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
    246          GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
    247 	 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
    248 	 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
    249 	 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
    250 	 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
    251 	 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
    252 
    253          /* Round 3 */
    254          HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
    255          HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
    256          HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
    257          HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
    258          HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
    259          HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
    260          HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
    261          HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
    262          HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
    263          HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
    264          HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
    265          HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
    266          HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
    267          HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
    268          HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
    269          HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
    270 
    271          /* Round 4 */
    272          II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
    273          II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
    274          II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
    275          II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
    276          II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
    277          II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
    278          II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
    279          II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
    280          II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
    281          II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
    282          II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
    283          II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
    284          II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
    285          II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
    286          II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
    287          II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
    288 
    289        state[0] += a;
    290        state[1] += b;
    291        state[2] += c;
    292        state[3] += d;
    293 
    294          /* Zeroize sensitive information.
    295 	 */
    296        MD5_memset ((POINTER)x, 0, sizeof (x));
    297 }
    298 
    299 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
    300        a multiple of 4.
    301 
    302         */
    303 
    304 static void Encode (output, input, len)
    305 unsigned char *output;
    306 UINT4 *input;
    307 unsigned int len;
    308 {
    309        unsigned int i, j;
    310 
    311        for (i = 0, j = 0; j < len; i++, j += 4) {
    312        output[j] = (unsigned char)(input[i] & 0xff);
    313        output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
    314        output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
    315        output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
    316        }
    317 }
    318 
    319 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
    320        a multiple of 4.
    321 
    322         */
    323 
    324 static void Decode (output, input, len)
    325 UINT4 *output;
    326 unsigned char *input;
    327 unsigned int len;
    328 {
    329        unsigned int i, j;
    330 
    331        for (i = 0, j = 0; j < len; i++, j += 4)
    332        output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16)
    333        | (((UINT4)input[j+3]) << 24);
    334 }
    335 
    336 /* Note: Replace "for loop" with standard memcpy if possible.
    337 
    338         */
    339 
    340 static void MD5_memcpy (output, input, len)
    341 POINTER output;
    342 POINTER input;
    343 unsigned int len;
    344 {
    345        unsigned int i;
    346 
    347        for (i = 0; i < len; i++)
    348 	      output[i] = input[i];
    349 }
    350 
    351 /* Note: Replace "for loop" with standard memset if possible.
    352 */
    353 
    354 static void MD5_memset (output, value, len)
    355 POINTER output;
    356 int value;
    357 unsigned int len;
    358 {
    359        unsigned int i;
    360 
    361        for (i = 0; i < len; i++)
    362        ((char *)output)[i] = (char)value;
    363 }
    364 #endif /* !_HAVE_LIB_MD5 */
    365 
    366 void _sasl_hmac_md5_init(HMAC_MD5_CTX *hmac,
    367 			 const unsigned char *key,
    368 			 int key_len)
    369 {
    370   unsigned char k_ipad[65];    /* inner padding -
    371 				* key XORd with ipad
    372 				*/
    373   unsigned char k_opad[65];    /* outer padding -
    374 				* key XORd with opad
    375 				*/
    376   unsigned char tk[16];
    377   int i;
    378   /* if key is longer than 64 bytes reset it to key=MD5(key) */
    379   if (key_len > 64) {
    380 
    381     MD5_CTX      tctx;
    382 
    383     _sasl_MD5Init(&tctx);
    384     _sasl_MD5Update(&tctx, key, key_len);
    385     _sasl_MD5Final(tk, &tctx);
    386 
    387     key = tk;
    388     key_len = 16;
    389   }
    390 
    391   /*
    392    * the HMAC_MD5 transform looks like:
    393    *
    394    * MD5(K XOR opad, MD5(K XOR ipad, text))
    395    *
    396    * where K is an n byte key
    397    * ipad is the byte 0x36 repeated 64 times
    398    * opad is the byte 0x5c repeated 64 times
    399    * and text is the data being protected
    400    */
    401 
    402   /* start out by storing key in pads */
    403   MD5_memset(k_ipad, '\0', sizeof k_ipad);
    404   MD5_memset(k_opad, '\0', sizeof k_opad);
    405   MD5_memcpy( k_ipad, key, key_len);
    406   MD5_memcpy( k_opad, key, key_len);
    407 
    408   /* XOR key with ipad and opad values */
    409   for (i=0; i<64; i++) {
    410     k_ipad[i] ^= 0x36;
    411     k_opad[i] ^= 0x5c;
    412   }
    413 
    414   _sasl_MD5Init(&hmac->ictx);                   /* init inner context */
    415   _sasl_MD5Update(&hmac->ictx, k_ipad, 64);     /* apply inner pad */
    416 
    417   _sasl_MD5Init(&hmac->octx);                   /* init outer context */
    418   _sasl_MD5Update(&hmac->octx, k_opad, 64);     /* apply outer pad */
    419 
    420   /* scrub the pads and key context (if used) */
    421   MD5_memset(&k_ipad, 0, sizeof(k_ipad));
    422   MD5_memset(&k_opad, 0, sizeof(k_opad));
    423   MD5_memset(&tk, 0, sizeof(tk));
    424 
    425   /* and we're done. */
    426 }
    427 
    428 /* The precalc and import routines here rely on the fact that we pad
    429  * the key out to 64 bytes and use that to initialize the md5
    430  * contexts, and that updating an md5 context with 64 bytes of data
    431  * leaves nothing left over; all of the interesting state is contained
    432  * in the state field, and none of it is left over in the count and
    433  * buffer fields.  So all we have to do is save the state field; we
    434  * can zero the others when we reload it.  Which is why the decision
    435  * was made to pad the key out to 64 bytes in the first place. */
    436 void _sasl_hmac_md5_precalc(HMAC_MD5_STATE *state,
    437 			    const unsigned char *key,
    438 			    int key_len)
    439 {
    440   HMAC_MD5_CTX hmac;
    441   unsigned lupe;
    442 
    443   _sasl_hmac_md5_init(&hmac, key, key_len);
    444   for (lupe = 0; lupe < 4; lupe++) {
    445     state->istate[lupe] = htonl(hmac.ictx.state[lupe]);
    446     state->ostate[lupe] = htonl(hmac.octx.state[lupe]);
    447   }
    448   MD5_memset(&hmac, 0, sizeof(hmac));
    449 }
    450 
    451 
    452 void _sasl_hmac_md5_import(HMAC_MD5_CTX *hmac,
    453 		     HMAC_MD5_STATE *state)
    454 {
    455   unsigned lupe;
    456   MD5_memset(hmac, 0, sizeof(HMAC_MD5_CTX));
    457   for (lupe = 0; lupe < 4; lupe++) {
    458     hmac->ictx.state[lupe] = ntohl(state->istate[lupe]);
    459     hmac->octx.state[lupe] = ntohl(state->ostate[lupe]);
    460   }
    461   /* Init the counts to account for our having applied
    462    * 64 bytes of key; this works out to 0x200 (64 << 3; see
    463    * MD5Update above...) */
    464   hmac->ictx.count[0] = hmac->octx.count[0] = 0x200;
    465 }
    466 
    467 void _sasl_hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
    468 			  HMAC_MD5_CTX *hmac)
    469 {
    470   _sasl_MD5Final(digest, &hmac->ictx);  /* Finalize inner md5 */
    471   _sasl_MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */
    472   _sasl_MD5Final(digest, &hmac->octx); /* Finalize outer md5 */
    473 }
    474 
    475 
    476 void _sasl_hmac_md5(text, text_len, key, key_len, digest)
    477 const unsigned char* text; /* pointer to data stream */
    478 int text_len; /* length of data stream */
    479 const unsigned char* key; /* pointer to authentication key */
    480 int key_len; /* length of authentication key */
    481 unsigned char *digest; /* caller digest to be filled in */
    482 {
    483   MD5_CTX context;
    484 
    485   unsigned char k_ipad[65];    /* inner padding -
    486 				* key XORd with ipad
    487 				*/
    488   unsigned char k_opad[65];    /* outer padding -
    489 				* key XORd with opad
    490 				*/
    491   unsigned char tk[16];
    492   int i;
    493   /* if key is longer than 64 bytes reset it to key=MD5(key) */
    494   if (key_len > 64) {
    495 
    496     MD5_CTX      tctx;
    497 
    498     _sasl_MD5Init(&tctx);
    499     _sasl_MD5Update(&tctx, key, key_len);
    500     _sasl_MD5Final(tk, &tctx);
    501 
    502     key = tk;
    503     key_len = 16;
    504   }
    505 
    506   /*
    507    * the HMAC_MD5 transform looks like:
    508    *
    509    * MD5(K XOR opad, MD5(K XOR ipad, text))
    510    *
    511    * where K is an n byte key
    512    * ipad is the byte 0x36 repeated 64 times
    513    * opad is the byte 0x5c repeated 64 times
    514    * and text is the data being protected
    515    */
    516 
    517   /* start out by storing key in pads */
    518   MD5_memset(k_ipad, '\0', sizeof k_ipad);
    519   MD5_memset(k_opad, '\0', sizeof k_opad);
    520   MD5_memcpy( k_ipad, key, key_len);
    521   MD5_memcpy( k_opad, key, key_len);
    522 
    523   /* XOR key with ipad and opad values */
    524   for (i=0; i<64; i++) {
    525     k_ipad[i] ^= 0x36;
    526     k_opad[i] ^= 0x5c;
    527   }
    528   /*
    529    * perform inner MD5
    530    */
    531 
    532   _sasl_MD5Init(&context);                   /* init context for 1st
    533 					       * pass */
    534   _sasl_MD5Update(&context, k_ipad, 64);      /* start with inner pad */
    535   _sasl_MD5Update(&context, text, text_len); /* then text of datagram */
    536   _sasl_MD5Final(digest, &context);          /* finish up 1st pass */
    537 
    538   /*
    539    * perform outer MD5
    540    */
    541   _sasl_MD5Init(&context);                   /* init context for 2nd
    542 					* pass */
    543   _sasl_MD5Update(&context, k_opad, 64);     /* start with outer pad */
    544   _sasl_MD5Update(&context, digest, 16);     /* then results of 1st
    545 					* hash */
    546   _sasl_MD5Final(digest, &context);          /* finish up 2nd pass */
    547 
    548 }
    549