Watt-32 tcp/ip  2.2 dev-rel.10
tcp_md5.c
Go to the documentation of this file.
1 
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #include "wattcp.h"
44 #include "chksum.h"
45 #include "strings.h"
46 #include "misc.h"
47 #include "pctcp.h"
48 
49 #if defined(USE_TCP_MD5)
50 
51 /* MD5 context.
52  */
53 typedef struct {
54  DWORD state [4]; /* state (ABCD) */
55  DWORD count [2]; /* number of bits, modulo 2^64 (LSB first) */
56  BYTE buffer [64]; /* input buffer */
57  } MD5_CTX;
58 
59 static void MD5_Init (MD5_CTX *context);
60 static void MD5_Update (MD5_CTX *context, const void *buffer, size_t length);
61 static void MD5_Final (BYTE result[16], MD5_CTX *context);
62 
63 const char *W32_CALL tcp_md5_secret (_tcp_Socket *sock, const char *secret)
64 {
65  char *old = sock->secret;
66 
67  if (old)
68  free (old);
69  sock->secret = secret ? strdup (secret) : NULL;
70  return (old);
71 }
72 
73 /*
74  * Used to insert the MD5 signature *after* we've built the complete
75  * TCP packet.
76  */
77 void W32_CALL make_md5_signature (const in_Header *ip, const tcp_Header *tcp,
78  WORD datalen, const char *secret, BYTE *buf)
79 {
80  struct tcp_PseudoHeader ph;
81  struct tcp_Header tcp_copy;
82  const BYTE *data = (const BYTE*)tcp + (tcp->offset << 2);
83  MD5_CTX ctx;
84 
85  MD5_Init (&ctx);
86 
87  /* Step 1: Update MD5 hash with IP pseudo-header.
88  */
89  memset (&ph, 0, sizeof(ph));
90  ph.src = ip->source;
91  ph.dst = ip->destination;
92  ph.protocol = ip->proto;
93  ph.length = intel16 (datalen);
94 
95  MD5_Update (&ctx, &ph.src, sizeof(ph.src));
96  MD5_Update (&ctx, &ph.dst, sizeof(ph.dst));
97  MD5_Update (&ctx, &ph.mbz, sizeof(ph.mbz));
98  MD5_Update (&ctx, &ph.protocol, sizeof(ph.protocol));
99  MD5_Update (&ctx, &ph.length, sizeof(ph.length));
100 
101  /* Step 2: Update MD5 hash with TCP header, excluding options.
102  * The TCP checksum must be set to zero.
103  */
104  memcpy (&tcp_copy, tcp, sizeof(tcp_copy));
105  tcp_copy.checksum = 0;
106  MD5_Update (&ctx, &tcp_copy, sizeof(tcp_copy));
107 
108  /* Step 3: Update MD5 hash with TCP segment data, if present.
109  */
110  if (datalen > 0)
111  MD5_Update (&ctx, data, datalen);
112 
113  /* Step 4: Update MD5 hash with shared secret.
114  */
115  MD5_Update (&ctx, secret, strlen(secret));
116  MD5_Final (buf, &ctx);
117 }
118 
119 /*
120  * Check incoming TCP segment for MD5 option.
121  */
122 BOOL W32_CALL check_md5_signature (const _tcp_Socket *s, const in_Header *ip)
123 {
124  const struct tcp_Header *tcp;
125  const BYTE *recv_sign, *data, *opt;
126  struct tcp_PseudoHeader ph;
127  struct tcp_Header tcp_copy;
128 
129  BYTE signature [16];
130  MD5_CTX ctx;
131  WORD len;
132 
133  if (!s->secret)
134  return (FALSE);
135 
136  WATT_ASSERT (ip->ver == 4);
137 
138  tcp = (tcp_Header*) ((BYTE*)ip + in_GetHdrLen (ip));
139 
140  len = intel16 (ip->length) - in_GetHdrLen (ip);
141  len -= (tcp->offset << 2);
142  data = (const BYTE*)tcp + (tcp->offset << 2);
143 
144  /* find the TCPOPT_SIGNATURE signature
145  */
146  recv_sign = NULL;
147  for (opt = (const BYTE*)(tcp+1); opt < data; )
148  {
149  if (*opt == TCPOPT_SIGNATURE)
150  {
151  recv_sign = opt + 2;
152  break;
153  }
154  if (*opt == TCPOPT_EOL)
155  break;
156 
157  if (*opt == TCPOPT_NOP)
158  opt++;
159  else opt += *(opt+1);
160  }
161 
162  if (!recv_sign || opt[1] != TCPOPT_SIGN_LEN)
163  return (FALSE);
164 
165  MD5_Init (&ctx);
166 
167  /* Step 1: Update MD5 hash with IP pseudo-header.
168  */
169  memset (&ph, 0, sizeof(ph));
170  ph.src = ip->source;
171  ph.dst = ip->destination;
172  ph.protocol = ip->proto;
173  ph.length = intel16 (len);
174 
175  MD5_Update (&ctx, &ph.src, sizeof(ph.src));
176  MD5_Update (&ctx, &ph.dst, sizeof(ph.dst));
177  MD5_Update (&ctx, &ph.mbz, sizeof(ph.mbz));
178  MD5_Update (&ctx, &ph.protocol, sizeof(ph.protocol));
179  MD5_Update (&ctx, &ph.length, sizeof(ph.length));
180 
181  /* Step 2: Update MD5 hash with TCP header, excluding options.
182  * The TCP checksum must be set to zero.
183  */
184  memcpy (&tcp_copy, tcp, sizeof(tcp_copy));
185  tcp_copy.checksum = 0;
186  MD5_Update (&ctx, &tcp_copy, sizeof(tcp_copy));
187 
188  /* Step 3: Update MD5 hash with TCP segment data, if present.
189  */
190  if (len > 0)
191  MD5_Update (&ctx, data, len);
192 
193  /* Step 4: Update MD5 hash with shared secret.
194  */
195  MD5_Update (&ctx, s->secret, strlen(s->secret));
196  MD5_Final (signature, &ctx);
197 
198  if (!memcmp(recv_sign, signature, sizeof(signature)))
199  return (TRUE);
200  return (FALSE);
201 }
202 
203 /*
204  * taken from RFC-1321/Appendix A.3
205  * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
206  */
207 
208 /*
209  * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights
210  * reserved.
211  *
212  * License to copy and use this software is granted provided that it is
213  * identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm"
214  * in all material mentioning or referencing this software or this function.
215  *
216  * License is also granted to make and use derivative works provided that such
217  * works are identified as "derived from the RSA Data Security, Inc. MD5
218  * Message-Digest Algorithm" in all material mentioning or referencing the
219  * derived work.
220  *
221  * RSA Data Security, Inc. makes no representations concerning either the
222  * merchantability of this software or the suitability of this software for
223  * any particular purpose. It is provided "as is" without express or implied
224  * warranty of any kind.
225  *
226  * These notices must be retained in any copies of any part of this
227  * documentation and/or software.
228  */
229 
230 /*
231  * Constants for MD5Transform routine.
232  */
233 #define S11 7
234 #define S12 12
235 #define S13 17
236 #define S14 22
237 #define S21 5
238 #define S22 9
239 #define S23 14
240 #define S24 20
241 #define S31 4
242 #define S32 11
243 #define S33 16
244 #define S34 23
245 #define S41 6
246 #define S42 10
247 #define S43 15
248 #define S44 21
249 
250 static void Transform (DWORD[4], const BYTE *);
251 static void Encode (BYTE *, const DWORD *, size_t);
252 static void Decode (DWORD *, const BYTE *, size_t);
253 
254 static BYTE padding[64] = {
255  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
256  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
257  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
258  0, 0
259  };
260 
261 /*
262  * F, G, H and I are basic MD5 functions.
263  */
264 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
265 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
266 #define H(x, y, z) ((x) ^ (y) ^ (z))
267 #define I(x, y, z) ((y) ^ ((x) | (~z)))
268 
269 /*
270  * ROTATE_LEFT rotates x left n bits.
271  */
272 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
273 
274 /*
275  * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is
276  * separate from addition to prevent recomputation.
277  */
278 #define FF(a, b, c, d, x, s, ac) { \
279  (a) += F ((b), (c), (d)) + (x) + (DWORD)(ac); \
280  (a) = ROTATE_LEFT ((a), (s)); \
281  (a) += (b); \
282  }
283 #define GG(a, b, c, d, x, s, ac) { \
284  (a) += G ((b), (c), (d)) + (x) + (DWORD)(ac); \
285  (a) = ROTATE_LEFT ((a), (s)); \
286  (a) += (b); \
287  }
288 #define HH(a, b, c, d, x, s, ac) { \
289  (a) += H ((b), (c), (d)) + (x) + (DWORD)(ac); \
290  (a) = ROTATE_LEFT ((a), (s)); \
291  (a) += (b); \
292  }
293 #define II(a, b, c, d, x, s, ac) { \
294  (a) += I ((b), (c), (d)) + (x) + (DWORD)(ac); \
295  (a) = ROTATE_LEFT ((a), (s)); \
296  (a) += (b); \
297  }
298 
299 /*
300  * MD5 initialization. Begins an MD5 operation, writing a new context.
301  */
302 static void MD5_Init (MD5_CTX *context)
303 {
304  context->count[0] = context->count[1] = 0;
305 
306  /* Load magic initialization constants.
307  */
308  context->state[0] = 0x67452301;
309  context->state[1] = 0xefcdab89;
310  context->state[2] = 0x98badcfe;
311  context->state[3] = 0x10325476;
312 }
313 
314 /*
315  * MD5 block update operation. Continues an MD5 message-digest operation,
316  * processing another message block, and updating the context.
317  */
318 static void MD5_Update (MD5_CTX *context, /* context */
319  const void *input, /* input block */
320  size_t inputLen) /* length of input block */
321 {
322  DWORD i, index, partLen;
323 
324  /* Compute number of bytes mod 64 */
325  index = (DWORD) ((context->count[0] >> 3) & 0x3F);
326 
327  /* Update number of bits */
328  if ((context->count[0] += ((DWORD)inputLen << 3)) < ((DWORD)inputLen << 3))
329  context->count[1]++;
330  context->count[1] += ((DWORD)inputLen >> 29);
331 
332  partLen = 64 - index;
333 
334  /* Transform as many times as possible.
335  */
336  if (inputLen >= partLen)
337  {
338  memcpy (&context->buffer[index], input, partLen);
339  Transform (context->state, context->buffer);
340 
341  for (i = partLen; i + 63 < inputLen; i += 64)
342  Transform (context->state, (const BYTE*)input+i);
343  index = 0;
344  }
345  else
346  i = 0;
347 
348  /* Buffer remaining input */
349  memcpy (&context->buffer[index], (const char*)input+i, inputLen-i);
350 }
351 
352 /*
353  * MD5 finalization. Ends an MD5 message-digest operation, writing the
354  * message digest and zeroizing the context.
355  */
356 static void MD5_Final (BYTE digest[16], /* message digest */
357  MD5_CTX *context) /* context */
358 {
359  BYTE bits[8];
360  DWORD index, padLen;
361 
362  /* Save number of bits */
363  Encode (bits, context->count, 8);
364 
365  /* Pad out to 56 mod 64. */
366  index = (DWORD) ((context->count[0] >> 3) & 0x3f);
367  padLen = (index < 56) ? (56 - index) : (120 - index);
368  MD5_Update (context, padding, padLen);
369 
370  /* Append length (before padding) */
371  MD5_Update (context, bits, 8);
372 
373  /* Store state in digest */
374  Encode (digest, context->state, 16);
375 
376  /* Zeroize sensitive information. */
377  memset (context, 0, sizeof(*context));
378 }
379 
380 /*
381  * MD5 basic transformation. Transforms state based on block.
382  */
383 static void Transform (DWORD state[4], const BYTE *block)
384 {
385  DWORD a = state[0];
386  DWORD b = state[1];
387  DWORD c = state[2];
388  DWORD d = state[3];
389  DWORD x[16];
390 
391  Decode (x, block, 64);
392 
393  /* Round 1 */
394  FF (a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
395  FF (d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
396  FF (c, d, a, b, x[2], S13, 0x242070db); /* 3 */
397  FF (b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
398  FF (a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
399  FF (d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
400  FF (c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
401  FF (b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
402  FF (a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
403  FF (d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
404  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
405  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
406  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
407  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
408  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
409  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
410 
411  /* Round 2 */
412  GG (a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
413  GG (d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
414  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
415  GG (b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
416  GG (a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
417  GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
418  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
419  GG (b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
420  GG (a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
421  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
422  GG (c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
423  GG (b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
424  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
425  GG (d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
426  GG (c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
427  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
428 
429  /* Round 3 */
430  HH (a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
431  HH (d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
432  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
433  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
434  HH (a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
435  HH (d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
436  HH (c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
437  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
438  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
439  HH (d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
440  HH (c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
441  HH (b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
442  HH (a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
443  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
444  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
445  HH (b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
446 
447  /* Round 4 */
448  II (a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
449  II (d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
450  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
451  II (b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
452  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
453  II (d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
454  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
455  II (b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
456  II (a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
457  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
458  II (c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
459  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
460  II (a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
461  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
462  II (c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
463  II (b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
464 
465  state[0] += a;
466  state[1] += b;
467  state[2] += c;
468  state[3] += d;
469 
470  /* Zeroize sensitive information. */
471  memset (&x, 0, sizeof(x));
472 }
473 
474 /*
475  * Encodes input (DWORD) into output (BYTE). Assumes len is a
476  * multiple of 4.
477  */
478 static void Encode (BYTE *output, const DWORD *input, size_t len)
479 {
480  size_t i, j;
481 
482  for (i = 0, j = 0; j < len; i++, j += 4)
483  {
484 #if 0
485  output[j] = (BYTE) (input[i] & 0xff);
486  output[j+1] = (BYTE) ((input[i] >> 8) & 0xff);
487  output[j+2] = (BYTE) ((input[i] >> 16) & 0xff);
488  output[j+3] = (BYTE) ((input[i] >> 24) & 0xff);
489 #else
490  *(DWORD*) (output+j) = intel (input[i]);
491 #endif
492  }
493 }
494 
495 /*
496  * Decodes input (BYTE) into output (DWORD). Assumes len is a
497  * multiple of 4.
498  */
499 static void Decode (DWORD *output, const BYTE *input, size_t len)
500 {
501  size_t i, j;
502 
503  for (i = 0, j = 0; j < len; i++, j += 4)
504 #if 0
505  output[i] = ((DWORD)input[j]) |
506  (((DWORD)input[j+1]) << 8) |
507  (((DWORD)input[j+2]) << 16) |
508  (((DWORD)input[j+3]) << 24);
509 #else
510  output[i] = intel (*(DWORD*)(input+j));
511 #endif
512 }
513 
514 #endif /* USE_TCP_MD5 */
Core definitions.
char * secret
< linked-list of frags; not yet
Definition: wattcp.h:669
Definition: ip.h:67