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.2 2006/01/14 11:33:50 swildner 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.
67 sctp_hash_digest(char *key
, int key_len
, char *text
, int text_len
,
68 unsigned char *digest
)
73 struct sha1_context context
;
75 /* inner padding - key XORd with ipad */
76 unsigned char k_ipad
[65];
77 /* outer padding - key XORd with opad */
78 unsigned char k_opad
[65];
86 MD5Update(&tctx
, key
, key_len
);
91 struct sha1_context tctx
;
93 SHA1_Process(&tctx
, key
, key_len
);
94 SHA1_Final(&tctx
, tk
);
101 * the HMAC_MD5 transform looks like:
103 * MD5(K XOR opad, MD5(K XOR ipad, text))
105 * where K is an n byte key
106 * ipad is the byte 0x36 repeated 64 times
107 * opad is the byte 0x5c repeated 64 times
108 * and text is the data being protected
111 /* start out by storing key in pads */
112 bzero(k_ipad
, sizeof k_ipad
);
113 bzero(k_opad
, sizeof k_opad
);
114 bcopy(key
, k_ipad
, key_len
);
115 bcopy(key
, k_opad
, key_len
);
117 /* XOR key with ipad and opad values */
118 for (i
= 0; i
< 64; i
++) {
126 MD5Init(&context
); /* init context for 1st pass */
127 MD5Update(&context
, k_ipad
, 64); /* start with inner pad */
128 MD5Update(&context
, text
, text_len
); /* then text of datagram */
129 MD5Final(digest
, &context
); /* finish up 1st pass */
131 SHA1_Init(&context
); /* init context for 1st pass */
132 SHA1_Process(&context
, k_ipad
, 64); /* start with inner pad */
133 SHA1_Process(&context
, text
, text_len
); /* then text of datagram */
134 SHA1_Final(&context
, digest
); /* finish up 1st pass */
141 MD5Init(&context
); /* init context for 2nd pass */
142 MD5Update(&context
, k_opad
, 64); /* start with outer pad */
143 MD5Update(&context
, digest
, 16); /* then results of 1st hash */
144 MD5Final(digest
, &context
); /* finish up 2nd pass */
146 SHA1_Init(&context
); /* init context for 2nd pass */
147 SHA1_Process(&context
, k_opad
, 64); /* start with outer pad */
148 SHA1_Process(&context
, digest
, 20); /* then results of 1st hash */
149 SHA1_Final(&context
, digest
); /* finish up 2nd pass */
154 sctp_hash_digest_m(char *key
, int key_len
, struct mbuf
*m
, int offset
,
155 unsigned char *digest
)
161 struct sha1_context context
;
163 /* inner padding - key XORd with ipad */
164 unsigned char k_ipad
[65];
165 /* outer padding - key XORd with opad */
166 unsigned char k_opad
[65];
167 unsigned char tk
[20];
174 MD5Update(&tctx
, key
, key_len
);
179 struct sha1_context tctx
;
181 SHA1_Process(&tctx
, key
, key_len
);
182 SHA1_Final(&tctx
, tk
);
189 * the HMAC_MD5 transform looks like:
191 * MD5(K XOR opad, MD5(K XOR ipad, text))
193 * where K is an n byte key
194 * ipad is the byte 0x36 repeated 64 times
195 * opad is the byte 0x5c repeated 64 times
196 * and text is the data being protected
199 /* start out by storing key in pads */
200 bzero(k_ipad
, sizeof k_ipad
);
201 bzero(k_opad
, sizeof k_opad
);
202 bcopy(key
, k_ipad
, key_len
);
203 bcopy(key
, k_opad
, key_len
);
205 /* XOR key with ipad and opad values */
206 for (i
= 0; i
< 64; i
++) {
211 /* find the correct mbuf and offset into mbuf */
213 while ((m_at
!= NULL
) && (offset
> m_at
->m_len
)) {
214 offset
-= m_at
->m_len
; /* update remaining offset left */
221 MD5Init(&context
); /* init context for 1st pass */
222 MD5Update(&context
, k_ipad
, 64); /* start with inner pad */
224 while (m_at
!= NULL
) {
225 /* then text of datagram... */
226 MD5Update(&context
, mtod(m_at
, char *)+offset
,
228 /* only offset on the first mbuf */
233 MD5Final(digest
, &context
); /* finish up 1st pass */
235 SHA1_Init(&context
); /* init context for 1st pass */
236 SHA1_Process(&context
, k_ipad
, 64); /* start with inner pad */
238 while (m_at
!= NULL
) {
239 /* then text of datagram */
240 SHA1_Process(&context
, mtod(m_at
, char *)+offset
,
242 /* only offset on the first mbuf */
247 SHA1_Final(&context
, digest
); /* finish up 1st pass */
254 MD5Init(&context
); /* init context for 2nd pass */
255 MD5Update(&context
, k_opad
, 64); /* start with outer pad */
256 MD5Update(&context
, digest
, 16); /* then results of 1st hash */
257 MD5Final(digest
, &context
); /* finish up 2nd pass */
259 SHA1_Init(&context
); /* init context for 2nd pass */
260 SHA1_Process(&context
, k_opad
, 64); /* start with outer pad */
261 SHA1_Process(&context
, digest
, 20); /* then results of 1st hash */
262 SHA1_Final(&context
, digest
); /* finish up 2nd pass */