1 /* $KAME: sctp_hashdriver.c,v 1.5 2004/01/19 09:48:26 itojun Exp $ */
2 /* $DragonFly: src/sys/netinet/sctp_hashdriver.c,v 1.1 2005/07/15 14:46:16 eirikn Exp $ */
5 * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Cisco Systems, Inc.
19 * 4. Neither the name of the project nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL CISCO SYSTEMS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
39 #include <sys/domain.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
44 #include <sys/kernel.h>
45 #include <sys/sysctl.h>
46 #include <sys/types.h>
47 #include <netinet/sctp_constants.h>
49 #include <crypto/md5.h>
51 #include <netinet/sctp_sha1.h>
53 #include <netinet/sctp_hashdriver.h>
56 * Main driver for SCTP's hashing.
57 * passing a two pointers and two lengths, returning a digest pointer
58 * filled. The md5 code was taken directly from the RFC (2104) so to
59 * understand it you may want to go look at the RFC referenced in the
60 * SCTP spec. We did modify this code to either user OURs implementation
61 * of SLA1 or the MD5 that comes from its RFC. SLA1 may have IPR issues
62 * so you need to check in to this if you wish to use it... Or at least
63 * that is what the FIP-180.1 web page says.
66 void sctp_hash_digest(char *key, int key_len, char *text, int text_len,
67 unsigned char *digest)
72 struct sha1_context context;
74 /* inner padding - key XORd with ipad */
75 unsigned char k_ipad[65];
76 /* outer padding - key XORd with opad */
77 unsigned char k_opad[65];
85 MD5Update(&tctx, key, key_len);
90 struct sha1_context tctx;
92 SHA1_Process(&tctx, key, key_len);
93 SHA1_Final(&tctx, tk);
100 * the HMAC_MD5 transform looks like:
102 * MD5(K XOR opad, MD5(K XOR ipad, text))
104 * where K is an n byte key
105 * ipad is the byte 0x36 repeated 64 times
106 * opad is the byte 0x5c repeated 64 times
107 * and text is the data being protected
110 /* start out by storing key in pads */
111 bzero(k_ipad, sizeof k_ipad);
112 bzero(k_opad, sizeof k_opad);
113 bcopy(key, k_ipad, key_len);
114 bcopy(key, k_opad, key_len);
116 /* XOR key with ipad and opad values */
117 for (i = 0; i < 64; i++) {
125 MD5Init(&context); /* init context for 1st pass */
126 MD5Update(&context, k_ipad, 64); /* start with inner pad */
127 MD5Update(&context, text, text_len); /* then text of datagram */
128 MD5Final(digest, &context); /* finish up 1st pass */
130 SHA1_Init(&context); /* init context for 1st pass */
131 SHA1_Process(&context, k_ipad, 64); /* start with inner pad */
132 SHA1_Process(&context, text, text_len); /* then text of datagram */
133 SHA1_Final(&context, digest); /* finish up 1st pass */
140 MD5Init(&context); /* init context for 2nd pass */
141 MD5Update(&context, k_opad, 64); /* start with outer pad */
142 MD5Update(&context, digest, 16); /* then results of 1st hash */
143 MD5Final(digest, &context); /* finish up 2nd pass */
145 SHA1_Init(&context); /* init context for 2nd pass */
146 SHA1_Process(&context, k_opad, 64); /* start with outer pad */
147 SHA1_Process(&context, digest, 20); /* then results of 1st hash */
148 SHA1_Final(&context, digest); /* finish up 2nd pass */
152 void sctp_hash_digest_m(char *key, int key_len, struct mbuf *m, int offset,
153 unsigned char *digest)
159 struct sha1_context context;
161 /* inner padding - key XORd with ipad */
162 unsigned char k_ipad[65];
163 /* outer padding - key XORd with opad */
164 unsigned char k_opad[65];
165 unsigned char tk[20];
172 MD5Update(&tctx, key, key_len);
177 struct sha1_context tctx;
179 SHA1_Process(&tctx, key, key_len);
180 SHA1_Final(&tctx, tk);
187 * the HMAC_MD5 transform looks like:
189 * MD5(K XOR opad, MD5(K XOR ipad, text))
191 * where K is an n byte key
192 * ipad is the byte 0x36 repeated 64 times
193 * opad is the byte 0x5c repeated 64 times
194 * and text is the data being protected
197 /* start out by storing key in pads */
198 bzero(k_ipad, sizeof k_ipad);
199 bzero(k_opad, sizeof k_opad);
200 bcopy(key, k_ipad, key_len);
201 bcopy(key, k_opad, key_len);
203 /* XOR key with ipad and opad values */
204 for (i = 0; i < 64; i++) {
209 /* find the correct mbuf and offset into mbuf */
211 while ((m_at != NULL) && (offset > m_at->m_len)) {
212 offset -= m_at->m_len; /* update remaining offset left */
219 MD5Init(&context); /* init context for 1st pass */
220 MD5Update(&context, k_ipad, 64); /* start with inner pad */
222 while (m_at != NULL) {
223 /* then text of datagram... */
224 MD5Update(&context, mtod(m_at, char *)+offset,
226 /* only offset on the first mbuf */
231 MD5Final(digest, &context); /* finish up 1st pass */
233 SHA1_Init(&context); /* init context for 1st pass */
234 SHA1_Process(&context, k_ipad, 64); /* start with inner pad */
236 while (m_at != NULL) {
237 /* then text of datagram */
238 SHA1_Process(&context, mtod(m_at, char *)+offset,
240 /* only offset on the first mbuf */
245 SHA1_Final(&context, digest); /* finish up 1st pass */
252 MD5Init(&context); /* init context for 2nd pass */
253 MD5Update(&context, k_opad, 64); /* start with outer pad */
254 MD5Update(&context, digest, 16); /* then results of 1st hash */
255 MD5Final(digest, &context); /* finish up 2nd pass */
257 SHA1_Init(&context); /* init context for 2nd pass */
258 SHA1_Process(&context, k_opad, 64); /* start with outer pad */
259 SHA1_Process(&context, digest, 20); /* then results of 1st hash */
260 SHA1_Final(&context, digest); /* finish up 2nd pass */