1 /* $KAME: sctp_hashdriver.c,v 1.6 2004/02/24 21:52:26 itojun Exp $ */ 2 /* $NetBSD: sctp_hashdriver.c,v 1.1 2015/10/13 21:28:35 rjs Exp $ */ 3 4 /* 5 * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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. 22 * 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 33 * SUCH DAMAGE. 34 */ 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: sctp_hashdriver.c,v 1.1 2015/10/13 21:28:35 rjs Exp $"); 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/malloc.h> 41 #include <sys/mbuf.h> 42 #include <sys/domain.h> 43 #include <sys/protosw.h> 44 #include <sys/socket.h> 45 #include <sys/socketvar.h> 46 #include <sys/proc.h> 47 #include <sys/kernel.h> 48 #include <sys/sysctl.h> 49 #include <sys/types.h> 50 #include <netinet/sctp_constants.h> 51 #ifdef USE_MD5 52 #include <sys/md5.h> 53 #else 54 #include <sys/sha1.h> 55 #endif 56 #include <netinet/sctp_hashdriver.h> 57 58 /* 59 * Main driver for SCTP's hashing. 60 * passing a two pointers and two lengths, returning a digest pointer 61 * filled. The md5 code was taken directly from the RFC (2104) so to 62 * understand it you may want to go look at the RFC referenced in the 63 * SCTP spec. We did modify this code to either user OURs implementation 64 * of SLA1 or the MD5 that comes from its RFC. SLA1 may have IPR issues 65 * so you need to check in to this if you wish to use it... Or at least 66 * that is what the FIP-180.1 web page says. 67 */ 68 69 void sctp_hash_digest(char *key, int key_len, char *text, int text_len, 70 unsigned char *digest) 71 { 72 #ifdef USE_MD5 73 MD5Context context; 74 #else 75 SHA1_CTX context; 76 #endif /* USE_MD5 */ 77 /* inner padding - key XORd with ipad */ 78 unsigned char k_ipad[65]; 79 /* outer padding - key XORd with opad */ 80 unsigned char k_opad[65]; 81 unsigned char tk[20]; 82 int i; 83 84 if (key_len > 64) { 85 #ifdef USE_MD5 86 md5_ctxt tctx; 87 MD5Init(&tctx); 88 MD5Update(&tctx, key, key_len); 89 MD5Final(tk, &tctx); 90 key = tk; 91 key_len = 16; 92 #else 93 SHA1_CTX tctx; 94 SHA1Init(&tctx); 95 SHA1Update(&tctx, key, key_len); 96 SHA1Final(tk, &tctx); 97 key = tk; 98 key_len = 20; 99 #endif /* USE_MD5 */ 100 } 101 102 /* 103 * the HMAC_MD5 transform looks like: 104 * 105 * MD5(K XOR opad, MD5(K XOR ipad, text)) 106 * 107 * where K is an n byte key 108 * ipad is the byte 0x36 repeated 64 times 109 * opad is the byte 0x5c repeated 64 times 110 * and text is the data being protected 111 */ 112 113 /* start out by storing key in pads */ 114 memset(k_ipad, 0, sizeof k_ipad); 115 memset(k_opad, 0, sizeof k_opad); 116 bcopy(key, k_ipad, key_len); 117 bcopy(key, k_opad, key_len); 118 119 /* XOR key with ipad and opad values */ 120 for (i = 0; i < 64; i++) { 121 k_ipad[i] ^= 0x36; 122 k_opad[i] ^= 0x5c; 123 } 124 /* 125 * perform inner MD5 126 */ 127 #ifdef USE_MD5 128 MD5Init(&context); /* init context for 1st pass */ 129 MD5Update(&context, k_ipad, 64); /* start with inner pad */ 130 MD5Update(&context, text, text_len); /* then text of datagram */ 131 MD5Final(digest, &context); /* finish up 1st pass */ 132 #else 133 SHA1Init(&context); /* init context for 1st pass */ 134 SHA1Update(&context, k_ipad, 64); /* start with inner pad */ 135 SHA1Update(&context, text, text_len); /* then text of datagram */ 136 SHA1Final(digest, &context); /* finish up 1st pass */ 137 #endif /* USE_MD5 */ 138 139 /* 140 * perform outer MD5 141 */ 142 #ifdef USE_MD5 143 MD5Init(&context); /* init context for 2nd pass */ 144 MD5Update(&context, k_opad, 64); /* start with outer pad */ 145 MD5Update(&context, digest, 16); /* then results of 1st hash */ 146 MD5Final(digest, &context); /* finish up 2nd pass */ 147 #else 148 SHA1Init(&context); /* init context for 2nd pass */ 149 SHA1Update(&context, k_opad, 64); /* start with outer pad */ 150 SHA1Update(&context, digest, 20); /* then results of 1st hash */ 151 SHA1Final(digest, &context); /* finish up 2nd pass */ 152 #endif /* USE_MD5 */ 153 } 154 155 void sctp_hash_digest_m(char *key, int key_len, struct mbuf *m, int offset, 156 unsigned char *digest) 157 { 158 struct mbuf *m_at; 159 #ifdef USE_MD5 160 MD5Context context; 161 #else 162 SHA1_CTX context; 163 #endif /* USE_MD5 */ 164 /* inner padding - key XORd with ipad */ 165 unsigned char k_ipad[65]; 166 /* outer padding - key XORd with opad */ 167 unsigned char k_opad[65]; 168 unsigned char tk[20]; 169 int i; 170 171 if (key_len > 64) { 172 #ifdef USE_MD5 173 MD5Context tctx; 174 MD5Init(&tctx); 175 MD5Update(&tctx, key, key_len); 176 MD5Final(tk, &tctx); 177 key = tk; 178 key_len = 16; 179 #else 180 SHA1_CTX tctx; 181 SHA1Init(&tctx); 182 SHA1Update(&tctx, key, key_len); 183 SHA1Final(tk, &tctx); 184 key = tk; 185 key_len = 20; 186 #endif /* USE_MD5 */ 187 } 188 189 /* 190 * the HMAC_MD5 transform looks like: 191 * 192 * MD5(K XOR opad, MD5(K XOR ipad, text)) 193 * 194 * where K is an n byte key 195 * ipad is the byte 0x36 repeated 64 times 196 * opad is the byte 0x5c repeated 64 times 197 * and text is the data being protected 198 */ 199 200 /* start out by storing key in pads */ 201 memset(k_ipad, 0, sizeof k_ipad); 202 memset(k_opad, 0, sizeof k_opad); 203 bcopy(key, k_ipad, key_len); 204 bcopy(key, k_opad, key_len); 205 206 /* XOR key with ipad and opad values */ 207 for (i = 0; i < 64; i++) { 208 k_ipad[i] ^= 0x36; 209 k_opad[i] ^= 0x5c; 210 } 211 212 /* find the correct mbuf and offset into mbuf */ 213 m_at = m; 214 while ((m_at != NULL) && (offset > m_at->m_len)) { 215 offset -= m_at->m_len; /* update remaining offset left */ 216 m_at = m_at->m_next; 217 } 218 /* 219 * perform inner MD5 220 */ 221 #ifdef USE_MD5 222 MD5Init(&context); /* init context for 1st pass */ 223 MD5Update(&context, k_ipad, 64); /* start with inner pad */ 224 /******/ 225 while (m_at != NULL) { 226 /* then text of datagram... */ 227 MD5Update(&context, mtod(m_at, char *)+offset, 228 m_at->m_len-offset); 229 /* only offset on the first mbuf */ 230 offset = 0; 231 m_at = m_at->m_next; 232 } 233 /******/ 234 MD5Final(digest, &context); /* finish up 1st pass */ 235 #else 236 SHA1Init(&context); /* init context for 1st pass */ 237 SHA1Update(&context, k_ipad, 64); /* start with inner pad */ 238 /******/ 239 while (m_at != NULL) { 240 /* then text of datagram */ 241 SHA1Update(&context, mtod(m_at, char *)+offset, 242 m_at->m_len-offset); 243 /* only offset on the first mbuf */ 244 offset = 0; 245 m_at = m_at->m_next; 246 } 247 /******/ 248 SHA1Final(digest, &context); /* finish up 1st pass */ 249 #endif /* USE_MD5 */ 250 251 /* 252 * perform outer MD5 253 */ 254 #ifdef USE_MD5 255 MD5Init(&context); /* init context for 2nd pass */ 256 MD5Update(&context, k_opad, 64); /* start with outer pad */ 257 MD5Update(&context, digest, 16); /* then results of 1st hash */ 258 MD5Final(digest, &context); /* finish up 2nd pass */ 259 #else 260 SHA1Init(&context); /* init context for 2nd pass */ 261 SHA1Update(&context, k_opad, 64); /* start with outer pad */ 262 SHA1Update(&context, digest, 20); /* then results of 1st hash */ 263 SHA1Final(digest, &context); /* finish up 2nd pass */ 264 #endif /* USE_MD5 */ 265 } 266