Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_precompute.c
bloba49d683f4ccbca7df93635e5299dc06815621ab9
1 /*-
2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
3 * All rights reserved.
5 * NBMK Encryption Technologies provides no support of any kind for
6 * this software. Questions or concerns about it may be addressed to
7 * the members of the relevant open-source community at
8 * <tech-crypto@netbsd.org>.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
12 * met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 static char const n8_id[] = "$Id: n8_precompute.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_precompute.c
38 * @brief Precomputes IPAD and OPAD values for SSL and TLS MACs.
40 * A more detailed description of the file.
42 *****************************************************************************/
44 /*****************************************************************************
45 * Revision history:
46 * 08/06/02 bac Fixed Bug #842 -- user's cipher info was being modified. Now
47 * n8_precompute_tls_ipad_opad accepts a separate parameter for
48 * returning the hashed key and passes it to
49 * n8_HMAC_MD5_Precompute and n8_HMAC_SHA1_Precompute.
50 * 03/06/02 brr Removed openssl includes.
51 * 02/22/02 spm Converted printf's to DBG's.
52 * 02/15/02 brr Modified include files to build in kernel context.
53 * 01/25/02 bac Corrected signatures to placate the compiler on all
54 * platforms.
55 * 01/23/02 dws Changed TLS functions to return the hashed key and it's
56 * length. The length of the hashed key is the hash function's
57 * digest size.
58 * 01/23/02 bac Removed debug printfs.
59 * 01/22/02 dws Original version.
60 ****************************************************************************/
61 /** @defgroup subsystem_name Subsystem Title (not used for a header file)
64 #include "n8_pub_types.h"
65 #include "n8_common.h"
66 #include "n8_precomp_md5.h"
67 #include "n8_precompute.h"
70 /* SSL MAC padding strings */
71 static char pad_1[49] = "666666666666666666666666666666666666666666666666";
72 static char pad_2[49] = "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
73 "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\";
74 #define SSL_MD5_Pad_Length 48
75 #define SSL_MD5_Secret_Length 16
77 /**********************/
78 /* SHA-1 definitions. */
79 /**********************/
80 #define SHA_1
81 #define SHA_LONG unsigned int
82 #define SHA_LBLOCK 16
83 #define SHA_CBLOCK (SHA_LBLOCK*4)
84 #define SHA_LAST_BLOCK (SHA_CBLOCK-8)
85 #define SHA_DIGEST_LENGTH 20
87 typedef struct
89 SHA_LONG h0,h1,h2,h3,h4;
90 SHA_LONG Nl,Nh;
91 SHA_LONG data[SHA_LBLOCK];
92 int num;
93 } SHA_CTX;
95 /******************************************************/
96 /* Including this header instantiates the SHA-1 code. */
97 /******************************************************/
98 #include "n8_precomp_sha_locl.h"
101 /*****************************************************************************
102 * n8_HMAC_MD5_Precompute
103 *****************************************************************************/
104 /** @ingroup substem_name
105 * @brief Compute HMAC-MD5 IPAD and OPAD values.
107 * Computes a partial HMAC of secret key. These values are later used
108 * to compute a complete HMAC. This code was adapted from the OpenSSL
109 * HMAC_Init function. If the key is longer than the hash block size,
110 * the key is hashed. The hashed key is returned in hashedKey and its length
111 * is written back to the len parameter.
113 * @param key RO: Pointer to the key string.
114 * @param hashedKey WO: Pointer to the key string.
115 * @param len RW: Pointer to the length of the key string.
116 * @param IPAD WO: Pointer to the IPAD result buffer.
117 * @param OPAD WO: Pointer to the OPAD result buffer.
119 * @par Externals:
120 * None.
122 * @return
123 * None.
125 * @par Errors:
126 * None.
128 * @par Locks:
129 * None.
131 * @par Assumptions:
132 * None.
133 *****************************************************************************/
134 static void n8_HMAC_MD5_Precompute(const void *key,
135 void *hashedKey,
136 uint32_t *len,
137 uint32_t *IPAD,
138 uint32_t *OPAD)
140 N8_PRECOMP_MD5_CTX ctxi, ctxo;
141 int i,j,key_len,reset=0;
142 unsigned char pad[MD5_CBLOCK];
143 unsigned char hkey[MD5_CBLOCK];
145 if (key != NULL)
147 reset=1;
148 j=MD5_CBLOCK;
149 if (j < *len)
151 n8_precomp_MD5_Init(&ctxi);
152 n8_precomp_MD5_Update(&ctxi,key,*len);
153 n8_precomp_MD5_Final(hkey, &ctxi);
154 key_len = MD5_DIGEST_LENGTH;
155 memcpy(hashedKey, hkey, key_len);
156 *len = key_len;
158 else
160 memcpy(hkey,key,*len);
161 memcpy(hashedKey, key, *len);
162 key_len = *len;
164 if (key_len != MD5_CBLOCK)
165 memset(&hkey[key_len], 0, MD5_CBLOCK - key_len);
168 if (reset)
170 for (i=0; i<MD5_CBLOCK; i++)
172 pad[i]=0x36^hkey[i];
174 n8_precomp_MD5_Init(&ctxi);
175 n8_precomp_MD5_Update(&ctxi,pad,MD5_CBLOCK);
176 IPAD[0] = swap_uint32(ctxi.A);
177 IPAD[1] = swap_uint32(ctxi.B);
178 IPAD[2] = swap_uint32(ctxi.C);
179 IPAD[3] = swap_uint32(ctxi.D);
180 #ifdef HMAC_DEBUG
181 DBG(("IPAD={A=%08x B=%08x C=%08x D=%08x}\n",
182 ctxi.A, ctxi.B, ctxi.C, ctxi.D));
183 #endif
185 for (i=0; i<MD5_CBLOCK; i++)
187 pad[i]=0x5c^hkey[i];
189 n8_precomp_MD5_Init(&ctxo);
190 n8_precomp_MD5_Update(&ctxo,pad,MD5_CBLOCK);
191 OPAD[0] = swap_uint32(ctxo.A);
192 OPAD[1] = swap_uint32(ctxo.B);
193 OPAD[2] = swap_uint32(ctxo.C);
194 OPAD[3] = swap_uint32(ctxo.D);
195 #ifdef HMAC_DEBUG
196 DBG(("OPAD={A=%08x B=%08x C=%08x D=%08x}\n",
197 ctxo.A, ctxo.B, ctxo.C, ctxo.D));
198 #endif
200 } /* n8_HMAC_MD5_Precompute */
203 /*****************************************************************************
204 * n8_HMAC_SHA1_Precompute
205 *****************************************************************************/
206 /** @ingroup substem_name
207 * @brief Compute HMAC-SHA1 IPAD and OPAD values.
209 * Computes a partial HMAC of secret key. These values are later used
210 * to compute a complete HMAC. This code was adapted from the OpenSSL
211 * HMAC_Init function. If the key is longer than the hash block size,
212 * the key is hashed. The hashed key and its length are written back
213 * to the key and len parameters.
215 * @param key RW: Pointer to the key string.
216 * @param len RW: Pointer to the length of the key string.
217 * @param IPAD WO: Pointer to the IPAD result buffer.
218 * @param OPAD WO: Pointer to the OPAD result buffer.
220 * @par Externals:
221 * None.
223 * @return
224 * None.
226 * @par Errors:
227 * None.
229 * @par Locks:
230 * None.
232 * @par Assumptions:
233 * None.
234 *****************************************************************************/
235 static void n8_HMAC_SHA1_Precompute(const void *key,
236 void *hashedKey,
237 uint32_t *len,
238 uint32_t *IPAD,
239 uint32_t *OPAD)
241 SHA_CTX ctxi, ctxo;
242 int i,j,key_len,reset=0;
243 unsigned char pad[SHA_CBLOCK];
244 unsigned char hkey[SHA_CBLOCK];
246 if (key != NULL)
248 reset=1;
249 j=SHA_CBLOCK;
250 if (j < *len)
252 n8_precomp_SHA1_Init(&ctxi);
253 n8_precomp_SHA1_Update(&ctxi,key,*len);
254 n8_precomp_SHA1_Final(hkey, &ctxi);
255 key_len = SHA_DIGEST_LENGTH;
256 memcpy(hashedKey, hkey, key_len);
257 *len = key_len;
259 else
261 memcpy(hkey,key,*len);
262 memcpy(hashedKey, key, *len);
263 key_len = *len;
265 if (key_len != SHA_CBLOCK)
266 memset(&hkey[key_len], 0, SHA_CBLOCK - key_len);
269 if (reset)
271 for (i=0; i<SHA_CBLOCK; i++)
273 pad[i]=0x36^hkey[i];
275 n8_precomp_SHA1_Init(&ctxi);
276 n8_precomp_SHA1_Update(&ctxi,pad,SHA_CBLOCK);
277 IPAD[0] = ctxi.h0;
278 IPAD[1] = ctxi.h1;
279 IPAD[2] = ctxi.h2;
280 IPAD[3] = ctxi.h3;
281 IPAD[4] = ctxi.h4;
282 #ifdef HMAC_DEBUG
283 DBG(("IPAD={A=%08x B=%08x C=%08x D=%08x E=%08x}\n",
284 ctxi.h0, ctxi.h1, ctxi.h2, ctxi.h3, ctxi.h4));
285 #endif
287 for (i=0; i<SHA_CBLOCK; i++)
289 pad[i]=0x5c^hkey[i];
291 n8_precomp_SHA1_Init(&ctxo);
292 n8_precomp_SHA1_Update(&ctxo,pad,SHA_CBLOCK);
293 OPAD[0] = ctxo.h0;
294 OPAD[1] = ctxo.h1;
295 OPAD[2] = ctxo.h2;
296 OPAD[3] = ctxo.h3;
297 OPAD[4] = ctxo.h4;
298 #ifdef HMAC_DEBUG
299 DBG(("OPAD={A=%08x B=%08x C=%08x D=%08x E=%08x}\n",
300 ctxo.h0, ctxo.h1, ctxo.h2, ctxo.h3, ctxo.h4));
301 #endif
306 /*****************************************************************************
307 * n8_precompute_ssl_ipad_opad
308 *****************************************************************************/
309 /** @ingroup substem_name
310 * @brief Compute SSL IPAD and OPAD values.
312 * Computes a partial SSL MAC of the SSL secret. These values are later used
313 * to compute the complete SSL MAC of a packet. The hash algorith for the MAC
314 * is MD5. (SHA-1 SSL MACs don't us IPAD/OPAD values.)
316 * @param secret_p RO: Pointer to the 16-byte MAC secret key.
317 * @param ipad_p WO: Pointer to the buffer that is to receive the
318 * precomputed IPAD values.
319 * @param opad_p WO: Pointer to the buffer that is to receive the
320 * precomputed OPAD values.
322 * @par Externals:
323 * None.
325 * @return
326 * N8_STATUS_OK - the function succeeded.
328 * @par Errors:
329 * None.
331 * @par Locks:
332 * None.
334 * @par Assumptions:
335 * IPAD and OPAD values are returned as arrays of uint32_t.
336 *****************************************************************************/
337 N8_Status_t n8_precompute_ssl_ipad_opad(N8_Buffer_t *secret_p,
338 uint32_t *ipad_p,
339 uint32_t *opad_p)
341 N8_Status_t status = N8_STATUS_OK;
342 N8_PRECOMP_MD5_CTX ctx;
344 /* Hash the secret and pad_1 string using the IPAD context. */
345 n8_precomp_MD5_Init(&ctx);
346 n8_precomp_MD5_Update(&ctx, secret_p, SSL_MD5_Secret_Length);
347 n8_precomp_MD5_Update(&ctx, pad_1, SSL_MD5_Pad_Length);
348 ipad_p[0] = swap_uint32(ctx.A);
349 ipad_p[1] = swap_uint32(ctx.B);
350 ipad_p[2] = swap_uint32(ctx.C);
351 ipad_p[3] = swap_uint32(ctx.D);
352 #ifdef HMAC_DEBUG
353 DBG(("IPAD={A=%08x B=%08x C=%08x D=%08x}\n",
354 ctx.A, ctx.B, ctx.C, ctx.D));
355 #endif
357 /* Hash the secret and pad_2 string using the OPAD context. */
358 n8_precomp_MD5_Init(&ctx);
359 n8_precomp_MD5_Update(&ctx, secret_p, SSL_MD5_Secret_Length);
360 n8_precomp_MD5_Update(&ctx, pad_2, SSL_MD5_Pad_Length);
361 opad_p[0] = swap_uint32(ctx.A);
362 opad_p[1] = swap_uint32(ctx.B);
363 opad_p[2] = swap_uint32(ctx.C);
364 opad_p[3] = swap_uint32(ctx.D);
365 #ifdef HMAC_DEBUG
366 DBG(("OPAD={A=%08x B=%08x C=%08x D=%08x}\n",
367 ctx.A, ctx.B, ctx.C, ctx.D));
368 #endif
370 return status;
371 } /* n8_precompute_ssl_ipad_opad */
375 /*****************************************************************************
376 * n8_precompute_tls_ipad_opad
377 *****************************************************************************/
378 /** @ingroup substem_name
379 * @brief Compute TLS IPAD and OPAD values.
381 * Computes a partial HMAC of the TLS secret. These values are later used
382 * to compute the complete TLS MAC of a packet. Note that keys longer than
383 * 64 bytes are handled correctly. (They are hashed.) If the key is hashed,
384 * the new value and length are written back through the secret_p and
385 * secret_length_p parameters.
387 * @param hash_alg RO: Hash algorithm - must be N8_MD5 or N8_SHA1.
388 * @param secret_p RW: Pointer to the HMAC secret key.
389 * @param hashed_key_p WO: Pointer to the computed hashed key.
390 * @param secret_length_p RW: Pointer to the length in bytes of the secret.
391 * @param ipad_p WO: Pointer to the buffer that is to receive the
392 * precomputed IPAD values.
393 * @param opad_p WO: Pointer to the buffer that is to receive the
394 * precomputed OPAD values.
396 * @par Externals:
397 * None.
399 * @return
400 * N8_STATUS_OK - the function succeeded.
401 * N8_INVALID_HASH - hash_alg is not N8_MD5 or N8_SHA1.
403 * @par Errors:
404 * See return.
406 * @par Locks:
407 * None.
409 * @par Assumptions:
410 * IPAD and OPAD values are returned as arrays of uint32_t.
411 *****************************************************************************/
412 N8_Status_t n8_precompute_tls_ipad_opad(const N8_HashAlgorithm_t hash_alg,
413 const N8_Buffer_t *secret_p,
414 N8_Buffer_t *hashed_key_p,
415 uint32_t *secret_length_p,
416 uint32_t *ipad_p,
417 uint32_t *opad_p)
419 N8_Status_t status = N8_STATUS_OK;
421 /* Check for a valid hash algorithm. */
422 if ((hash_alg == N8_MD5) ||
423 (hash_alg == N8_HMAC_MD5) ||
424 (hash_alg == N8_HMAC_MD5_96))
426 n8_HMAC_MD5_Precompute(secret_p, hashed_key_p, secret_length_p, ipad_p, opad_p);
428 else if ((hash_alg == N8_SHA1) || (hash_alg == N8_HMAC_SHA1) ||
429 (hash_alg == N8_HMAC_SHA1_96))
431 n8_HMAC_SHA1_Precompute(secret_p, hashed_key_p, secret_length_p, ipad_p, opad_p);
433 else
435 /* Not a valid choice for the hash algorithm. */
436 status = N8_INVALID_HASH;
438 return status;