Annotation of embedaddon/freevrrpd/vrrp_ah.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 2003 BurnesOnLine <bol@b0l.org>
3: *
4: * Redistribution and use in source forms, with and without modification,
5: * are permitted provided that the following conditions are met:
6: * 1. Redistributions of source code must retain the above copyright notice,
7: * this list of conditions and the following disclaimer.
8: * 2. Redistributions in binary form must reproduce the above copyright notice,
9: * this list of conditions and the following disclaimer in the documentation
10: * and/or other materials provided with the distribution. Obviously, it
11: * would be nice if you gave credit where credit is due but requiring it
12: * would be too onerous.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by Sebastien Petit.
16: * 4. Neither the name of its contributors may be used to endorse or promote
17: * products derived from this software without specific prior written
18: * permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: * $Id: vrrp_ah.c,v 1.13 2004/04/04 19:45:46 rival Exp $
33: *
34: * MISC COMMENTS :
35: * FreeVRRPd project AH implementation using KAME based ipsec stack.
36: * tested on :
37: * FreeBSD
38: * NetBSD
39: * should work on :
40: * Linux 2.6 or KAME based linux ipsec stack
41: *
42: * this code use KAME not fully implemented :
43: * RFC 2367 - PF_KEY Key Management API, Version 2
44: *
45: * AUTHORS:
46: * this is a working and almost clean "HACK" :)
47: * problem is, we cant set socket wide SPD and SAD
48: * need to work out with KAME project to know exactly
49: * the procedure to make process wide changes and NOT
50: * host wide changes.
51: *
52: * b0l.
53: *
54: */
55: #include "vrrp_proto.h"
56: #include "vrrp_ah.h"
57: #include "md5.h"
58:
59: #ifdef ENABLE_VRRP_AH
60: #ifdef KAME_BASED
61: /* special struct */
62: typedef enum {
63: HMAC_MD5 = 2, /* 128 bits */
64: HMAC_SHA1 = 3, /* 160 bits */
65: HMAC_NULL,
66: HMAC_SHA2_256, /* 256 bits */
67: HMAC_SHA2_384, /* 384 bits */
68: HMAC_SHA2_512, /* 512 bits */
69: HMAC_RIPEMD160, /* 160 bits */
70: AES_XCBC_MAC /* 128 bits */
71: } alg_t;
72:
73: typedef struct algorithm {
74: alg_t type;
75: size_t keysize;
76: } algorithm_t;
77:
78: algorithm_t algos[] = {
79: { HMAC_MD5, 128 },
80: { HMAC_SHA1, 160 },
81: { HMAC_NULL, 0 },
82: { HMAC_SHA2_256, 256 },
83: { HMAC_SHA2_384, 384 },
84: { HMAC_SHA2_512, 512 },
85: { HMAC_RIPEMD160, 160 },
86: { AES_XCBC_MAC, 128 }
87: };
88:
89: /* what we need
90: ipsec (4)
91: setsockopt(2) * per socket behavior *
92: sysctl(3) * host wide *
93: ipsec_set_policy(3) * IPsec Policy Control Library (libipsec, -lipsec) *
94: */
95:
96: /* STOLEN FROM FreeBSD setkey.c :) */
97: struct addrinfo * parse_addr(char *host, char *port) {
98: struct addrinfo hints, *res = NULL;
99: int error;
100:
101: memset(&hints, 0, sizeof(hints));
102: hints.ai_family = PF_UNSPEC;
103: hints.ai_socktype = SOCK_DGRAM; /*dummy*/
104: hints.ai_protocol = IPPROTO_UDP; /*dummy*/
105: hints.ai_flags = 0;
106: error = getaddrinfo(host, port, &hints, &res);
107: if (error != 0) {
108: perror(gai_strerror(error));
109: return NULL;
110: }
111: return res;
112: }
113:
114: int setkeymsg(struct sadb_msg *msg, unsigned int type, unsigned int satype, size_t l) {
115:
116: msg->sadb_msg_version = PF_KEY_V2;
117: msg->sadb_msg_type = type;
118: msg->sadb_msg_errno = 0;
119: msg->sadb_msg_satype = satype;
120: msg->sadb_msg_reserved = 0;
121: msg->sadb_msg_seq = 0;
122: msg->sadb_msg_pid = getpid();
123: msg->sadb_msg_len = PFKEY_UNIT64(l);
124: return 0;
125: }
126:
127: int setvarbuf(char *buf, int *off, struct sadb_ext *ebuf, int elen, caddr_t vbuf, int vlen) {
128: memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
129: memcpy(buf + *off, (caddr_t)ebuf, elen);
130: memcpy(buf + *off + elen, vbuf, vlen);
131: (*off) += PFKEY_ALIGN8(elen + vlen);
132: return 0;
133: }
134:
135: /* WE NEED :
136: setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
137: */
138:
139: /* open the PF_KEY socket */
140: int vrrp_pfkey_open(void) {
141: int key_fd;
142:
143: /* opening PF_KEY API */
144: key_fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
145: if (key_fd < 0) {
146: perror("socket(PF_KEY)");
147: return key_fd;
148: }
149:
150: return key_fd;
151: }
152:
153: /* close PF_KEY socket */
154: int vrrp_pfkey_close(int fd) {
155: int rc = 0;
156: rc = close(fd);
157: return rc;
158: }
159:
160: /* return -1 on failure, 0 on success */
161: int vrrp_ah_set_outpolicy(int fd, char *src) {
162: int rc = 0;
163:
164: rc = vrrp_ah_spd(fd, src, VRRP_OUT_POLICY, SADB_X_SPDADD);
165: if (rc < 0) {
166: perror("VRRP_OUT_POLICY setup failed!\n");
167: rc = -1;
168: }
169: return rc;
170: }
171:
172: /* return -1 on failure, 0 on success */
173: int vrrp_ah_rm_outpolicy(int fd, char *src) {
174: int rc = 0;
175:
176: rc = vrrp_ah_spd(fd, src, VRRP_OUT_POLICY, SADB_X_SPDDELETE);
177: if (rc < 0) {
178: perror("VRRP_OUT_POLICY removal failed\n");
179: rc = -1;
180: }
181: return rc;
182: }
183:
184: /* return -1 on failure, 0 on success */
185: int vrrp_ah_set_inpolicy(int fd, char *src) {
186: int rc = 0;
187:
188: rc = vrrp_ah_spd(fd, src, VRRP_IN_POLICY, SADB_X_SPDADD);
189: if (rc < 0) {
190: perror("VRRP_IN_POLICY setup failed\n");
191: rc = -1;
192: }
193: return rc;
194: }
195:
196: /* return -1 on failure, 0 on success */
197: int vrrp_ah_rm_inpolicy(int fd, char *src) {
198: int rc = 0;
199:
200: rc = vrrp_ah_spd(fd, src, VRRP_IN_POLICY, SADB_X_SPDDELETE);
201: if (rc < 0) {
202: perror("VRRP_IN_POLICY setup failed\n");
203: rc = -1;
204: }
205: return rc;
206: }
207:
208: /* return number of bytes sent to PF_KEY socket/in-kernel */
209: int vrrp_ah_spd(int fd, char *src_addr, char *ah_policy, unsigned int cmd) {
210: /* lets see if it works */
211: char *policy;
212: int policy_len;
213: const int bufsiz = 128 * 1024;
214: char * buf = (char *) malloc (bufsiz * sizeof(char));
215: struct sadb_msg *msg;
216: struct sadb_address m_addr;
217: struct sockaddr *sa;
218: struct addrinfo *src, *dst;
219: int m_size;
220: int salen;
221: int rc;
222:
223: /* sanity checks */
224: if (!buf) {
225: fprintf(stderr,"could not allocate memory\n");
226: return -1;
227: }
228:
229: /* prepare the policy */
230: policy = ipsec_set_policy(VRRP_OUT_POLICY, strlen(VRRP_OUT_POLICY));
231: if (!policy) {
232: perror("ipsec_set_policy()");
233: return -1;
234: }
235:
236: policy_len = ipsec_get_policylen(policy);
237: if (policy_len < 0) {
238: perror("ipsec_get_policylen()");
239: return -1;
240: }
241:
242: /* clearing everything, don't want this bugs to happen again */
243: memset(buf,0,bufsiz);
244: memset(&m_addr, 0, sizeof(m_addr));
245:
246: /* building PF_KEY msg */
247: msg = (struct sadb_msg *) buf;
248: setkeymsg(msg,(unsigned int)cmd,SADB_SATYPE_UNSPEC, 0);
249: m_size = sizeof(struct sadb_msg);
250:
251: /* copying the policy */
252: memcpy(buf+m_size, policy, policy_len);
253: m_size += policy_len;
254:
255: /* parsing from / to */
256: src = parse_addr(src_addr, 0);
257: if (!src) {
258: free(policy);
259: free(buf);
260: return -1;
261: }
262:
263: dst = parse_addr(VRRP_ADDRESS, 0);
264: if (!dst) {
265: free(policy);
266: freeaddrinfo(src);
267: free(buf);
268: return -1;
269: }
270:
271: /* SOURCE SETUP */
272: sa = src->ai_addr;
273: salen = src->ai_addr->sa_len;
274: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr)+PFKEY_ALIGN8(salen));
275: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
276: m_addr.sadb_address_proto = (unsigned int)IPSEC_IPPROTO_ANY;
277: m_addr.sadb_address_prefixlen = HOST_MASK;
278: m_addr.sadb_address_reserved = 0;
279:
280: setvarbuf(buf, &m_size, (struct sadb_ext *)&m_addr,sizeof(m_addr),(caddr_t)sa, salen);
281:
282: /* DESTINATION SETUP */
283: sa = dst->ai_addr;
284: salen = src->ai_addr->sa_len;
285: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr)+PFKEY_ALIGN8(salen));
286: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
287: m_addr.sadb_address_proto = (unsigned int)IPSEC_IPPROTO_ANY;
288: m_addr.sadb_address_prefixlen = HOST_MASK; /* (splen >= 0 ? -1 : plen ); */
289: m_addr.sadb_address_reserved = 0;
290:
291: setvarbuf(buf, &m_size, (struct sadb_ext *)&m_addr,sizeof(m_addr),(caddr_t)sa, salen);
292:
293: msg->sadb_msg_len = PFKEY_UNIT64(m_size);
294:
295: (void)setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
296: (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
297:
298: rc = send(fd, buf, m_size, 0);
299: if (rc < 0)
300: perror("could not add entry to SPD: send()");
301:
302: free(policy);
303: free(buf);
304: freeaddrinfo(src);
305: freeaddrinfo(dst);
306: return rc;
307: }
308:
309:
310:
311: /* status = setkeymsg_add(SADB_ADD, $5, $3, $4); */
312: /* DO NOT FORGET TO CLEAN THOSE FUKING LOCAL STRUCTURE 2 DAYS LOST $#@$!@#$#@!
313: * */
314: int vrrp_ah_sad(int fd, char *src_addr, alg_t algo, char *key) {
315: const int bufsiz = 128 * 1024;
316: char * buf = (char *) malloc (bufsiz * sizeof(char));
317: struct sadb_msg *msg;
318: struct sadb_address m_addr;
319: struct sockaddr *sa;
320: struct addrinfo *src, *dst, *s;
321: int m_size;
322: int salen;
323: int rc;
324: /* ADDED */
325: int len;
326: char * p_alg_auth = "hmac-sha1";
327: char * p_key_auth = "12345678901234567890";
328: int p_key_auth_len = strlen(p_key_auth);
329: struct sadb_key m_key;
330: struct sadb_sa m_sa;
331: struct sadb_x_sa2 m_sa2;
332: struct sadb_lifetime m_lt;
333:
334: msg = (struct sadb_msg *) buf;
335:
336: /* clearing the allocated data */
337: memset(buf,0,bufsiz);
338:
339: setkeymsg(msg, SADB_ADD, SADB_SATYPE_AH, 0);
340: /* setkeymsg(msg, SADB_DELETE, SADB_SATYPE_AH, 0); */
341:
342: m_size = sizeof(struct sadb_msg);
343: /* HACK HACK */
344: /* hexdump(msg,m_size); */
345:
346: m_key.sadb_key_len = PFKEY_UNIT64(sizeof(m_key) + PFKEY_ALIGN8(p_key_auth_len));
347: m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
348: m_key.sadb_key_bits = p_key_auth_len * 8;
349: m_key.sadb_key_reserved = 0;
350:
351: setvarbuf(buf, &m_size, (struct sadb_ext *)&m_key,sizeof(m_key),(caddr_t)p_key_auth, p_key_auth_len);
352:
353: /*
354: u_int slen = sizeof(struct sadb_lifetime);
355: m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
356: m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
357: m_lt.sadb_lifetime_allocations = 0;
358: m_lt.sadb_lifetime_bytes = 0;
359: m_lt.sadb_lifetime_addtime = 0;
360: m_lt.sadb_lifetime_usetime = 0;
361:
362: memcpy(buf + m_size, &m_lt, slen);
363: m_size += slen;
364: */
365:
366: /*
367: m_key.sadb_key_len = PFKEY_UNIT64(sizeof(m_key) + PFKEY_ALIGN8(p_key_auth_len));
368: m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
369: m_key.sadb_key_bits = p_key_auth_len * 8;
370: m_key.sadb_key_reserved = 0;
371:
372: setvarbuf(buf, &m_size, (struct sadb_ext *)&m_key, sizeof(m_key), (caddr_t)p_key_auth, p_key_auth_len);
373: */
374:
375: len = sizeof(struct sadb_sa);
376: m_sa.sadb_sa_len = PFKEY_UNIT64(len);
377: m_sa.sadb_sa_exttype = SADB_EXT_SA;
378: m_sa.sadb_sa_spi = htonl(0x2710);
379: m_sa.sadb_sa_replay = 0;
380: m_sa.sadb_sa_state = 0;
381: m_sa.sadb_sa_auth = 3; /* hmac-sha1 */
382: m_sa.sadb_sa_encrypt = 0; /* no encryption yet */
383: m_sa.sadb_sa_flags = 64; /* BUG HERE */
384:
385: memcpy(buf + m_size, &m_sa, len);
386: m_size += len;
387:
388: bzero(&m_sa2, sizeof(struct sadb_x_sa2));
389:
390: len = sizeof(struct sadb_x_sa2);
391: printf("len: %x exttype: %x\n",PFKEY_UNIT64(len), SADB_X_EXT_SA2);
392: m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
393: m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
394: m_sa2.sadb_x_sa2_mode = IPSEC_MODE_ANY;
395: m_sa2.sadb_x_sa2_reqid = 0;
396:
397: memcpy(buf + m_size, &m_sa2, len);
398: m_size += len;
399:
400: /* parsing from / to */
401: src = parse_addr(src_addr, 0);
402: if (!src) {
403: free(buf);
404: return -1;
405: }
406:
407: dst = parse_addr(VRRP_ADDRESS, 0);
408: if (!dst) {
409: freeaddrinfo(src);
410: free(buf);
411: return -1;
412: }
413:
414: /* SOURCE SETUP */
415: for (s = src; s; s = s->ai_next) {
416: sa = s->ai_addr;
417: salen = s->ai_addr->sa_len; /* POSSIBLE BUG */
418: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr)+PFKEY_ALIGN8(salen));
419: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
420: m_addr.sadb_address_proto = (unsigned int)IPSEC_ULPROTO_ANY;
421: m_addr.sadb_address_prefixlen = HOST_MASK; /* (splen >= 0 ? -1 : plen ); */
422: m_addr.sadb_address_reserved = 0;
423: setvarbuf(buf, &m_size, (struct sadb_ext *)&m_addr,sizeof(m_addr),(caddr_t)sa, salen);
424: }
425:
426: /* DESTINATION SETUP */
427: sa = dst->ai_addr;
428: salen = dst->ai_addr->sa_len;
429: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr)+PFKEY_ALIGN8(salen));
430: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
431: m_addr.sadb_address_proto = (unsigned int)IPSEC_ULPROTO_ANY;
432: m_addr.sadb_address_prefixlen = HOST_MASK; /* (splen >= 0 ? -1 : plen ); */
433: m_addr.sadb_address_reserved = 0;
434:
435: setvarbuf(buf, &m_size, (struct sadb_ext *)&m_addr,sizeof(m_addr),(caddr_t)sa, salen);
436:
437: msg->sadb_msg_len = PFKEY_UNIT64(m_size);
438:
439: (void)setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
440: (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
441:
442: rc = send(fd, buf, m_size, 0);
443: if (rc < 0)
444: perror("could not add entry to SAD: send()");
445:
446: free(buf);
447: freeaddrinfo(src);
448: freeaddrinfo(dst);
449: return rc;
450: }
451:
452: #else
453: /* The simple implementation based on keepalived draft */
454: void vrrp_ah_init_ahhdr(unsigned char *buffer, struct vrrp_vr *vr) {
455: struct ip *ip;
456: struct ah_header *ah;
457:
458: ip = (struct ip *) buffer;
459: ah = (struct ah_header *) (buffer+sizeof(struct ip));
460: ah->next = IPPROTO_VRRP;
461: ah->length = 0x04;
462: ah->zero = 0x0000;
463: ah->spi = htonl(vr->vr_if->ip_addrs[0].s_addr);
464: ah->seq = htonl(1);
465: /* clean first */
466: memset(ah->auth,0,sizeof(ah->auth));
467:
468: return;
469: }
470:
471: void vrrp_ah_hmacmd5(unsigned char *buffer, struct vrrp_vr *vr) {
472: struct ip *ip;
473: struct ah_header *ah;
474: unsigned char md5[16];
475:
476: ip = (struct ip *) buffer;
477: ah = (struct ah_header *) (buffer+sizeof(struct ip));
478:
479: /* clear md5 */
480: memset(md5,0,sizeof(md5));
481:
482: /* hexdump(md5,sizeof(md5)); */
483: /* lets compute digest */
484: hmac_md5(buffer, (sizeof(struct ip)+sizeof(struct ah_header)+sizeof(struct vrrp_hdr)), (unsigned char *)vr->password, strlen(vr->password), md5);
485: /* hexdump(md5,sizeof(md5)); */
486:
487: /* copy it */
488: memcpy(ah->auth, md5, 12);
489:
490: return;
491: }
492:
493: /* return 0 if packet is valid, -1 else */
494: int vrrp_ah_check_ahhdr(char *buffer, struct vrrp_vr *vr) {
495: struct ah_header *ah;
496: unsigned char recv_authdata[HMAC_MD596_SIZE], comp_authdata[HMAC_MD596_SIZE+4];
497:
498: ah = (struct ah_header *) buffer;
499: if (ah->next != IPPROTO_VRRP)
500: return -1;
501: if (ah->length != 0x04)
502: return -1;
503: /*
504: if (ah->seq < vr->ahctx->seq)
505: return -1;
506: else
507: vr->ahctx->seq = ah->seq;
508: */
509:
510: /* save auth data and rebuild hmac to see if it match */
511: memcpy(recv_authdata,(caddr_t)ah->auth,HMAC_MD596_SIZE);
512: memset(ah->auth,0, HMAC_MD596_SIZE);
513: hmac_md5((unsigned char *)buffer, sizeof(struct ip)+sizeof(struct ah_header)+sizeof(struct vrrp_hdr), vr->password, strlen(vr->password), comp_authdata);
514:
515: if (memcmp(recv_authdata, comp_authdata, HMAC_MD596_SIZE) == 0)
516: return 0;
517:
518: printf("packet invalid!!!\n");
519: return -1;
520: }
521: #endif /* end of ifdef KAME_BASED */
522: #endif /* endof ENABLE_VRRP_AH */
523:
524:
525: int vrrp_ah_ahhdr_len(struct vrrp_vr *vr) {
526: #ifdef ENABLE_VRRP_AH
527: if (vr->AHencryption == 1)
528: return (sizeof(struct ah_header));
529: #endif
530: return 0;
531: }
532:
533:
534: /*
535: RFC 2104 define this.
536: unsigned char* text; * pointer to data stream *
537: int text_len; * length of data stream *
538: unsigned char* key; * pointer to authentication key *
539: int key_len; * length of authentication key *
540: caddr_t digest; * caller digest to be filled in *
541: */
542: void hmac_md5(unsigned char *text, int text_len, unsigned char *key, int key_len, caddr_t digest) {
543: MD5_CTX context,tctx;
544: unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */
545: unsigned char k_opad[65]; /* outer padding - key XORd with opad */
546: unsigned char tk[16];
547: int i;
548:
549: /* if key is longer than 64 bytes reset it to key=MD5(key) */
550: if (key_len > 64) {
551:
552: MD5Init(&tctx);
553: MD5Update(&tctx, key, key_len);
554: MD5Final(tk, &tctx);
555:
556: key = tk;
557: key_len = 16;
558: }
559:
560: /*
561: * the HMAC_MD5 transform looks like:
562: *
563: * MD5(K XOR opad, MD5(K XOR ipad, text))
564: *
565: * where K is an n byte key
566: * ipad is the byte 0x36 repeated 64 times
567: * opad is the byte 0x5c repeated 64 times
568: * and text is the data being protected
569: */
570:
571: /* start out by storing key in pads */
572: bzero( k_ipad, sizeof k_ipad);
573: bzero( k_opad, sizeof k_opad);
574: bcopy( key, k_ipad, key_len);
575: bcopy( key, k_opad, key_len);
576:
577: /* XOR key with ipad and opad values */
578: for (i=0; i<64; i++) {
579: k_ipad[i] ^= 0x36;
580: k_opad[i] ^= 0x5c;
581: }
582: /* perform inner MD5 */
583: MD5Init(&context); /* init context for 1st pass */
584: MD5Update(&context, k_ipad, 64); /* start with inner pad */
585: MD5Update(&context, text, text_len); /* then text of datagram */
586: MD5Final(digest, &context); /* finish up 1st pass */
587:
588: /* perform outer MD5 */
589:
590: MD5Init(&context); /* init context for 2nd */
591:
592: MD5Update(&context, k_opad, 64); /* start with outer pad */
593: MD5Update(&context, digest, 16); /* then results of 1st hash */
594: MD5Final(digest, &context); /* finish up 2nd pass */
595: }
596:
597: /* Hexdumping on screen in a fancy format for debuging purposes */
598: int hexdump(unsigned char *zone, int len) {
599: int rc=0,i;
600: unsigned char *ptr;
601:
602: ptr = zone;
603: fprintf(stderr,"-- hexdump at %p (%d bytes long) --",zone,len);
604: for( i = 0 ;i < len;i++) {
605: if((i%16)==0)
606: fprintf(stderr,"\n%p ",ptr+i);
607: if((i%8)==0)
608: fprintf(stderr," ");
609: fprintf(stderr,"0x%.2x ",*(ptr+i));
610: }
611: fprintf(stderr,"\n");
612: return rc;
613: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>