| 1 | /* md5.c - MD5 Message-Digest Algorithm
 | 
|---|
| 2 |  *      Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
 | 
|---|
| 3 |  *
 | 
|---|
| 4 |  * according to the definition of MD5 in RFC 1321 from April 1992.
 | 
|---|
| 5 |  * NOTE: This is *not* the same file as the one from glibc.
 | 
|---|
| 6 |  *
 | 
|---|
| 7 |  * This program is free software; you can redistribute it and/or modify it
 | 
|---|
| 8 |  * under the terms of the GNU General Public License as published by the
 | 
|---|
| 9 |  * Free Software Foundation; either version 2, or (at your option) any
 | 
|---|
| 10 |  * later version.
 | 
|---|
| 11 |  *
 | 
|---|
| 12 |  * This program is distributed in the hope that it will be useful,
 | 
|---|
| 13 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 14 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 15 |  * GNU General Public License for more details.
 | 
|---|
| 16 |  *
 | 
|---|
| 17 |  * You should have received a copy of the GNU General Public License
 | 
|---|
| 18 |  * along with this program; if not, write to the Free Software Foundation,
 | 
|---|
| 19 |  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 | 
|---|
| 20 |  */
 | 
|---|
| 21 | /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
 | 
|---|
| 22 | /* heavily modified for GnuPG by <werner.koch@guug.de> */
 | 
|---|
| 23 | /* Modified by Eric.Aubourg@cea.fr for SOPHYA */
 | 
|---|
| 24 | 
 | 
|---|
| 25 | /* Test values:
 | 
|---|
| 26 |  * ""                  D4 1D 8C D9 8F 00 B2 04  E9 80 09 98 EC F8 42 7E
 | 
|---|
| 27 |  * "a"                 0C C1 75 B9 C0 F1 B6 A8  31 C3 99 E2 69 77 26 61
 | 
|---|
| 28 |  * "abc                90 01 50 98 3C D2 4F B0  D6 96 3F 7D 28 E1 7F 72
 | 
|---|
| 29 |  * "message digest"    F9 6B 69 7D 7C B7 93 8D  52 5A 2F 31 AA F1 61 D0
 | 
|---|
| 30 |  */
 | 
|---|
| 31 | 
 | 
|---|
| 32 | #include <stdio.h>
 | 
|---|
| 33 | #include <stdlib.h>
 | 
|---|
| 34 | #include <string.h>
 | 
|---|
| 35 | #include <assert.h>
 | 
|---|
| 36 | 
 | 
|---|
| 37 | #include "machdefs.h"
 | 
|---|
| 38 | #include "bithelp.h" 
 | 
|---|
| 39 | #include "gnumd5.h"
 | 
|---|
| 40 | 
 | 
|---|
| 41 | #define DIM(v) (sizeof(v)/sizeof((v)[0]))
 | 
|---|
| 42 | 
 | 
|---|
| 43 | #if SWAP==0
 | 
|---|
| 44 | #define BIG_ENDIAN_HOST 1
 | 
|---|
| 45 | #endif
 | 
|---|
| 46 | 
 | 
|---|
| 47 | 
 | 
|---|
| 48 | /* 
 | 
|---|
| 49 | typedef struct {
 | 
|---|
| 50 |   uint_4 A,B,C,D;          chaining variables 
 | 
|---|
| 51 |   uint_4  nblocks;
 | 
|---|
| 52 |   uint_1 buf[64];
 | 
|---|
| 53 |   int  count;
 | 
|---|
| 54 | } MD5_CONTEXT;
 | 
|---|
| 55 | */
 | 
|---|
| 56 | 
 | 
|---|
| 57 | void
 | 
|---|
| 58 | md5_init( MD5_CONTEXT *ctx )
 | 
|---|
| 59 | {
 | 
|---|
| 60 |     ctx->A = 0x67452301;
 | 
|---|
| 61 |     ctx->B = 0xefcdab89;
 | 
|---|
| 62 |     ctx->C = 0x98badcfe;
 | 
|---|
| 63 |     ctx->D = 0x10325476;
 | 
|---|
| 64 | 
 | 
|---|
| 65 |     ctx->nblocks = 0;
 | 
|---|
| 66 |     ctx->count = 0;
 | 
|---|
| 67 | }
 | 
|---|
| 68 | 
 | 
|---|
| 69 | 
 | 
|---|
| 70 | 
 | 
|---|
| 71 | 
 | 
|---|
| 72 | /* These are the four functions used in the four steps of the MD5 algorithm
 | 
|---|
| 73 |    and defined in the RFC 1321.  The first function is a little bit optimized
 | 
|---|
| 74 |    (as found in Colin Plumbs public domain implementation).  */
 | 
|---|
| 75 | /* #define FF(b, c, d) ((b & c) | (~b & d)) */
 | 
|---|
| 76 | #define FF(b, c, d) (d ^ (b & (c ^ d)))
 | 
|---|
| 77 | #define FG(b, c, d) FF (d, b, c)
 | 
|---|
| 78 | #define FH(b, c, d) (b ^ c ^ d)
 | 
|---|
| 79 | #define FI(b, c, d) (c ^ (b | ~d))
 | 
|---|
| 80 | 
 | 
|---|
| 81 | 
 | 
|---|
| 82 | /****************
 | 
|---|
| 83 |  * transform n*64 bytes
 | 
|---|
| 84 |  */
 | 
|---|
| 85 | static void
 | 
|---|
| 86 | /*transform( MD5_CONTEXT *ctx, const void *buffer, size_t len )*/
 | 
|---|
| 87 | transform( MD5_CONTEXT *ctx, uint_1 *data )
 | 
|---|
| 88 | {
 | 
|---|
| 89 |     uint_4 correct_words[16];
 | 
|---|
| 90 |     uint_4 A = ctx->A;
 | 
|---|
| 91 |     uint_4 B = ctx->B;
 | 
|---|
| 92 |     uint_4 C = ctx->C;
 | 
|---|
| 93 |     uint_4 D = ctx->D;
 | 
|---|
| 94 |     uint_4 *cwp = correct_words;
 | 
|---|
| 95 | 
 | 
|---|
| 96 | #ifdef BIG_ENDIAN_HOST
 | 
|---|
| 97 |     { int i;
 | 
|---|
| 98 |       uint_1 *p2, *p1;
 | 
|---|
| 99 |       for(i=0, p1=data, p2=(uint_1*)correct_words; i < 16; i++, p2 += 4 ) {
 | 
|---|
| 100 |         p2[3] = *p1++;
 | 
|---|
| 101 |         p2[2] = *p1++;
 | 
|---|
| 102 |         p2[1] = *p1++;
 | 
|---|
| 103 |         p2[0] = *p1++;
 | 
|---|
| 104 |       }
 | 
|---|
| 105 |     }
 | 
|---|
| 106 | #else
 | 
|---|
| 107 |     memcpy( correct_words, data, 64 );
 | 
|---|
| 108 | #endif
 | 
|---|
| 109 | 
 | 
|---|
| 110 | 
 | 
|---|
| 111 | #define OP(a, b, c, d, s, T)                                        \
 | 
|---|
| 112 |   do                                                                \
 | 
|---|
| 113 |     {                                                               \
 | 
|---|
| 114 |       a += FF (b, c, d) + (*cwp++) + T;             \
 | 
|---|
| 115 |       a = rol(a, s);                                                \
 | 
|---|
| 116 |       a += b;                                                       \
 | 
|---|
| 117 |     }                                                               \
 | 
|---|
| 118 |   while (0)
 | 
|---|
| 119 | 
 | 
|---|
| 120 |     /* Before we start, one word about the strange constants.
 | 
|---|
| 121 |        They are defined in RFC 1321 as
 | 
|---|
| 122 | 
 | 
|---|
| 123 |        T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
 | 
|---|
| 124 |      */
 | 
|---|
| 125 | 
 | 
|---|
| 126 |     /* Round 1.  */
 | 
|---|
| 127 |     OP (A, B, C, D,  7, 0xd76aa478);
 | 
|---|
| 128 |     OP (D, A, B, C, 12, 0xe8c7b756);
 | 
|---|
| 129 |     OP (C, D, A, B, 17, 0x242070db);
 | 
|---|
| 130 |     OP (B, C, D, A, 22, 0xc1bdceee);
 | 
|---|
| 131 |     OP (A, B, C, D,  7, 0xf57c0faf);
 | 
|---|
| 132 |     OP (D, A, B, C, 12, 0x4787c62a);
 | 
|---|
| 133 |     OP (C, D, A, B, 17, 0xa8304613);
 | 
|---|
| 134 |     OP (B, C, D, A, 22, 0xfd469501);
 | 
|---|
| 135 |     OP (A, B, C, D,  7, 0x698098d8);
 | 
|---|
| 136 |     OP (D, A, B, C, 12, 0x8b44f7af);
 | 
|---|
| 137 |     OP (C, D, A, B, 17, 0xffff5bb1);
 | 
|---|
| 138 |     OP (B, C, D, A, 22, 0x895cd7be);
 | 
|---|
| 139 |     OP (A, B, C, D,  7, 0x6b901122);
 | 
|---|
| 140 |     OP (D, A, B, C, 12, 0xfd987193);
 | 
|---|
| 141 |     OP (C, D, A, B, 17, 0xa679438e);
 | 
|---|
| 142 |     OP (B, C, D, A, 22, 0x49b40821);
 | 
|---|
| 143 | 
 | 
|---|
| 144 | #undef OP
 | 
|---|
| 145 | #define OP(f, a, b, c, d, k, s, T)  \
 | 
|---|
| 146 |     do                                                                \
 | 
|---|
| 147 |       {                                                               \
 | 
|---|
| 148 |         a += f (b, c, d) + correct_words[k] + T;                      \
 | 
|---|
| 149 |         a = rol(a, s);                                                \
 | 
|---|
| 150 |         a += b;                                                       \
 | 
|---|
| 151 |       }                                                               \
 | 
|---|
| 152 |     while (0)
 | 
|---|
| 153 | 
 | 
|---|
| 154 |     /* Round 2.  */
 | 
|---|
| 155 |     OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
 | 
|---|
| 156 |     OP (FG, D, A, B, C,  6,  9, 0xc040b340);
 | 
|---|
| 157 |     OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
 | 
|---|
| 158 |     OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
 | 
|---|
| 159 |     OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
 | 
|---|
| 160 |     OP (FG, D, A, B, C, 10,  9, 0x02441453);
 | 
|---|
| 161 |     OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
 | 
|---|
| 162 |     OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
 | 
|---|
| 163 |     OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
 | 
|---|
| 164 |     OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
 | 
|---|
| 165 |     OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
 | 
|---|
| 166 |     OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
 | 
|---|
| 167 |     OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
 | 
|---|
| 168 |     OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
 | 
|---|
| 169 |     OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
 | 
|---|
| 170 |     OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
 | 
|---|
| 171 | 
 | 
|---|
| 172 |     /* Round 3.  */
 | 
|---|
| 173 |     OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
 | 
|---|
| 174 |     OP (FH, D, A, B, C,  8, 11, 0x8771f681);
 | 
|---|
| 175 |     OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
 | 
|---|
| 176 |     OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
 | 
|---|
| 177 |     OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
 | 
|---|
| 178 |     OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
 | 
|---|
| 179 |     OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
 | 
|---|
| 180 |     OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
 | 
|---|
| 181 |     OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
 | 
|---|
| 182 |     OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
 | 
|---|
| 183 |     OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
 | 
|---|
| 184 |     OP (FH, B, C, D, A,  6, 23, 0x04881d05);
 | 
|---|
| 185 |     OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
 | 
|---|
| 186 |     OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
 | 
|---|
| 187 |     OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
 | 
|---|
| 188 |     OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
 | 
|---|
| 189 | 
 | 
|---|
| 190 |     /* Round 4.  */
 | 
|---|
| 191 |     OP (FI, A, B, C, D,  0,  6, 0xf4292244);
 | 
|---|
| 192 |     OP (FI, D, A, B, C,  7, 10, 0x432aff97);
 | 
|---|
| 193 |     OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
 | 
|---|
| 194 |     OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
 | 
|---|
| 195 |     OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
 | 
|---|
| 196 |     OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
 | 
|---|
| 197 |     OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
 | 
|---|
| 198 |     OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
 | 
|---|
| 199 |     OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
 | 
|---|
| 200 |     OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
 | 
|---|
| 201 |     OP (FI, C, D, A, B,  6, 15, 0xa3014314);
 | 
|---|
| 202 |     OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
 | 
|---|
| 203 |     OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
 | 
|---|
| 204 |     OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
 | 
|---|
| 205 |     OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
 | 
|---|
| 206 |     OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
 | 
|---|
| 207 | 
 | 
|---|
| 208 |     /* Put checksum in context given as argument.  */
 | 
|---|
| 209 |     ctx->A += A;
 | 
|---|
| 210 |     ctx->B += B;
 | 
|---|
| 211 |     ctx->C += C;
 | 
|---|
| 212 |     ctx->D += D;
 | 
|---|
| 213 | }
 | 
|---|
| 214 | 
 | 
|---|
| 215 | 
 | 
|---|
| 216 | 
 | 
|---|
| 217 | /* The routine updates the message-digest context to
 | 
|---|
| 218 |  * account for the presence of each of the characters inBuf[0..inLen-1]
 | 
|---|
| 219 |  * in the message whose digest is being computed.
 | 
|---|
| 220 |  */
 | 
|---|
| 221 | void
 | 
|---|
| 222 | md5_write( MD5_CONTEXT *hd, uint_1 *inbuf, size_t inlen)
 | 
|---|
| 223 | {
 | 
|---|
| 224 |     if( hd->count == 64 ) { /* flush the buffer */
 | 
|---|
| 225 |         transform( hd, hd->buf );
 | 
|---|
| 226 |         hd->count = 0;
 | 
|---|
| 227 |         hd->nblocks++;
 | 
|---|
| 228 |     }
 | 
|---|
| 229 |     if( !inbuf )
 | 
|---|
| 230 |         return;
 | 
|---|
| 231 |     if( hd->count ) {
 | 
|---|
| 232 |         for( ; inlen && hd->count < 64; inlen-- )
 | 
|---|
| 233 |             hd->buf[hd->count++] = *inbuf++;
 | 
|---|
| 234 |         md5_write( hd, NULL, 0 );
 | 
|---|
| 235 |         if( !inlen )
 | 
|---|
| 236 |             return;
 | 
|---|
| 237 |     }
 | 
|---|
| 238 | 
 | 
|---|
| 239 |     while( inlen >= 64 ) {
 | 
|---|
| 240 |         transform( hd, inbuf );
 | 
|---|
| 241 |         hd->count = 0;
 | 
|---|
| 242 |         hd->nblocks++;
 | 
|---|
| 243 |         inlen -= 64;
 | 
|---|
| 244 |         inbuf += 64;
 | 
|---|
| 245 |     }
 | 
|---|
| 246 |     for( ; inlen && hd->count < 64; inlen-- )
 | 
|---|
| 247 |         hd->buf[hd->count++] = *inbuf++;
 | 
|---|
| 248 | 
 | 
|---|
| 249 | }
 | 
|---|
| 250 | 
 | 
|---|
| 251 | 
 | 
|---|
| 252 | 
 | 
|---|
| 253 | /* The routine final terminates the message-digest computation and
 | 
|---|
| 254 |  * ends with the desired message digest in mdContext->digest[0...15].
 | 
|---|
| 255 |  * The handle is prepared for a new MD5 cycle.
 | 
|---|
| 256 |  * Returns 16 bytes representing the digest.
 | 
|---|
| 257 |  */
 | 
|---|
| 258 | 
 | 
|---|
| 259 | void
 | 
|---|
| 260 | md5_final( MD5_CONTEXT *hd )
 | 
|---|
| 261 | {
 | 
|---|
| 262 |     uint_4 t, msb, lsb;
 | 
|---|
| 263 |     uint_1 *p;
 | 
|---|
| 264 | 
 | 
|---|
| 265 |     md5_write(hd, NULL, 0); /* flush */;
 | 
|---|
| 266 | 
 | 
|---|
| 267 |     msb = 0;
 | 
|---|
| 268 |     t = hd->nblocks;
 | 
|---|
| 269 |     if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
 | 
|---|
| 270 |         msb++;
 | 
|---|
| 271 |     msb += t >> 26;
 | 
|---|
| 272 |     t = lsb;
 | 
|---|
| 273 |     if( (lsb = t + hd->count) < t ) /* add the count */
 | 
|---|
| 274 |         msb++;
 | 
|---|
| 275 |     t = lsb;
 | 
|---|
| 276 |     if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
 | 
|---|
| 277 |         msb++;
 | 
|---|
| 278 |     msb += t >> 29;
 | 
|---|
| 279 | 
 | 
|---|
| 280 |     if( hd->count < 56 ) { /* enough room */
 | 
|---|
| 281 |         hd->buf[hd->count++] = 0x80; /* pad */
 | 
|---|
| 282 |         while( hd->count < 56 )
 | 
|---|
| 283 |             hd->buf[hd->count++] = 0;  /* pad */
 | 
|---|
| 284 |     }
 | 
|---|
| 285 |     else { /* need one extra block */
 | 
|---|
| 286 |         hd->buf[hd->count++] = 0x80; /* pad character */
 | 
|---|
| 287 |         while( hd->count < 64 )
 | 
|---|
| 288 |             hd->buf[hd->count++] = 0;
 | 
|---|
| 289 |         md5_write(hd, NULL, 0);  /* flush */;
 | 
|---|
| 290 |         memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
 | 
|---|
| 291 |     }
 | 
|---|
| 292 |     /* append the 64 bit count */
 | 
|---|
| 293 |     hd->buf[56] = lsb      ;
 | 
|---|
| 294 |     hd->buf[57] = lsb >>  8;
 | 
|---|
| 295 |     hd->buf[58] = lsb >> 16;
 | 
|---|
| 296 |     hd->buf[59] = lsb >> 24;
 | 
|---|
| 297 |     hd->buf[60] = msb      ;
 | 
|---|
| 298 |     hd->buf[61] = msb >>  8;
 | 
|---|
| 299 |     hd->buf[62] = msb >> 16;
 | 
|---|
| 300 |     hd->buf[63] = msb >> 24;
 | 
|---|
| 301 |     transform( hd, hd->buf );
 | 
|---|
| 302 | 
 | 
|---|
| 303 |     p = hd->buf;
 | 
|---|
| 304 | #ifdef BIG_ENDIAN_HOST
 | 
|---|
| 305 | #define X(a) do { *p++ = hd->##a          ; *p++ = hd->##a >> 8;      \
 | 
|---|
| 306 |                       *p++ = hd->##a >> 16; *p++ = hd->##a >> 24; } while(0)
 | 
|---|
| 307 | #else /* little endian */
 | 
|---|
| 308 |     /*#define X(a) do { *(uint_4*)p = hd->##a ; p += 4; } while(0)*/
 | 
|---|
| 309 |     /* Unixware's cpp doesn't like the above construct so we do it his way:
 | 
|---|
| 310 |      * (reported by Allan Clark) */
 | 
|---|
| 311 | #define X(a) do { *(uint_4*)p = (*hd).a ; p += 4; } while(0)
 | 
|---|
| 312 | #endif
 | 
|---|
| 313 |     X(A);
 | 
|---|
| 314 |     X(B);
 | 
|---|
| 315 |     X(C);
 | 
|---|
| 316 |     X(D);
 | 
|---|
| 317 | #undef X
 | 
|---|
| 318 | 
 | 
|---|
| 319 | }
 | 
|---|
| 320 | 
 | 
|---|
| 321 | static uint_1 *
 | 
|---|
| 322 | md5_read( MD5_CONTEXT *hd )
 | 
|---|
| 323 | {
 | 
|---|
| 324 |     return hd->buf;
 | 
|---|
| 325 | }
 | 
|---|
| 326 | 
 | 
|---|
| 327 | /****************
 | 
|---|
| 328 |  * Return some information about the algorithm.  We need algo here to
 | 
|---|
| 329 |  * distinguish different flavors of the algorithm.
 | 
|---|
| 330 |  * Returns: A pointer to string describing the algorithm or NULL if
 | 
|---|
| 331 |  *          the ALGO is invalid.
 | 
|---|
| 332 |  */
 | 
|---|
| 333 | static const char *
 | 
|---|
| 334 | md5_get_info( int algo, size_t *contextsize,
 | 
|---|
| 335 |                uint_1 **r_asnoid, int *r_asnlen, int *r_mdlen,
 | 
|---|
| 336 |                void (**r_init)( void *c ),
 | 
|---|
| 337 |                void (**r_write)( void *c, uint_1 *buf, size_t nbytes ),
 | 
|---|
| 338 |                void (**r_final)( void *c ),
 | 
|---|
| 339 |                uint_1 *(**r_read)( void *c )
 | 
|---|
| 340 |              )
 | 
|---|
| 341 | {
 | 
|---|
| 342 |     static uint_1 asn[18] = /* Object ID is 1.2.840.113549.2.5 */
 | 
|---|
| 343 |                     { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
 | 
|---|
| 344 |                       0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
 | 
|---|
| 345 | 
 | 
|---|
| 346 |     if( algo != 1 )
 | 
|---|
| 347 |         return NULL;
 | 
|---|
| 348 | 
 | 
|---|
| 349 |     *contextsize = sizeof(MD5_CONTEXT);
 | 
|---|
| 350 |     *r_asnoid = asn;
 | 
|---|
| 351 |     *r_asnlen = DIM(asn);
 | 
|---|
| 352 |     *r_mdlen = 16;
 | 
|---|
| 353 |     *r_init  = (void (*)(void *))md5_init;
 | 
|---|
| 354 |     *r_write = (void (*)(void *, uint_1*, size_t))md5_write;
 | 
|---|
| 355 |     *r_final = (void (*)(void *))md5_final;
 | 
|---|
| 356 |     *r_read  = (uint_1 *(*)(void *))md5_read;
 | 
|---|
| 357 | 
 | 
|---|
| 358 |     return "MD5";
 | 
|---|
| 359 | }
 | 
|---|
| 360 | 
 | 
|---|
| 361 | 
 | 
|---|
| 362 | #ifndef IS_MODULE
 | 
|---|
| 363 | static
 | 
|---|
| 364 | #endif
 | 
|---|
| 365 | const char * const gnupgext_version = "MD5 ($Revision: 1.4 $)";
 | 
|---|
| 366 | 
 | 
|---|
| 367 | static struct {
 | 
|---|
| 368 |     int class;
 | 
|---|
| 369 |     int version;
 | 
|---|
| 370 |     int  value;
 | 
|---|
| 371 |     void (*func)(void);
 | 
|---|
| 372 | } func_table[] = {
 | 
|---|
| 373 |     { 10, 1, 0, (void(*)(void))md5_get_info },
 | 
|---|
| 374 |     { 11, 1, 1 },
 | 
|---|
| 375 | };
 | 
|---|
| 376 | 
 | 
|---|
| 377 | 
 | 
|---|
| 378 | #ifndef IS_MODULE
 | 
|---|
| 379 | static
 | 
|---|
| 380 | #endif
 | 
|---|
| 381 | void *
 | 
|---|
| 382 | gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
 | 
|---|
| 383 | {
 | 
|---|
| 384 |     void *ret;
 | 
|---|
| 385 |     int i = *sequence;
 | 
|---|
| 386 | 
 | 
|---|
| 387 |     do {
 | 
|---|
| 388 |         if( i >= DIM(func_table) || i < 0 )
 | 
|---|
| 389 |             return NULL;
 | 
|---|
| 390 |         *class = func_table[i].class;
 | 
|---|
| 391 |         *vers  = func_table[i].version;
 | 
|---|
| 392 |         switch( *class ) {
 | 
|---|
| 393 |           case 11: case 21: case 31: ret = &func_table[i].value; break;
 | 
|---|
| 394 |           default:                   ret = func_table[i].func; break;
 | 
|---|
| 395 |         }
 | 
|---|
| 396 |         i++;
 | 
|---|
| 397 |     } while( what && what != *class );
 | 
|---|
| 398 | 
 | 
|---|
| 399 |     *sequence = i;
 | 
|---|
| 400 |     return ret;
 | 
|---|
| 401 | }
 | 
|---|
| 402 | 
 | 
|---|
| 403 | 
 | 
|---|
| 404 | 
 | 
|---|
| 405 | /*
 | 
|---|
| 406 | #ifndef IS_MODULE
 | 
|---|
| 407 | void
 | 
|---|
| 408 | md5_constructor(void)
 | 
|---|
| 409 | {
 | 
|---|
| 410 |     register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func );
 | 
|---|
| 411 | }
 | 
|---|
| 412 | #endif
 | 
|---|
| 413 | */
 | 
|---|
| 414 | 
 | 
|---|
| 415 | 
 | 
|---|
| 416 | /* end of file */
 | 
|---|