2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
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>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
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 /*****************************************************************************
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
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
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 /**********************/
81 #define SHA_LONG unsigned int
83 #define SHA_CBLOCK (SHA_LBLOCK*4)
84 #define SHA_LAST_BLOCK (SHA_CBLOCK-8)
85 #define SHA_DIGEST_LENGTH 20
89 SHA_LONG h0
,h1
,h2
,h3
,h4
;
91 SHA_LONG data
[SHA_LBLOCK
];
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.
133 *****************************************************************************/
134 static void n8_HMAC_MD5_Precompute(const void *key
,
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
];
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
);
160 memcpy(hkey
,key
,*len
);
161 memcpy(hashedKey
, key
, *len
);
164 if (key_len
!= MD5_CBLOCK
)
165 memset(&hkey
[key_len
], 0, MD5_CBLOCK
- key_len
);
170 for (i
=0; i
<MD5_CBLOCK
; 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
);
181 DBG(("IPAD={A=%08x B=%08x C=%08x D=%08x}\n",
182 ctxi
.A
, ctxi
.B
, ctxi
.C
, ctxi
.D
));
185 for (i
=0; i
<MD5_CBLOCK
; 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
);
196 DBG(("OPAD={A=%08x B=%08x C=%08x D=%08x}\n",
197 ctxo
.A
, ctxo
.B
, ctxo
.C
, ctxo
.D
));
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.
234 *****************************************************************************/
235 static void n8_HMAC_SHA1_Precompute(const void *key
,
242 int i
,j
,key_len
,reset
=0;
243 unsigned char pad
[SHA_CBLOCK
];
244 unsigned char hkey
[SHA_CBLOCK
];
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
);
261 memcpy(hkey
,key
,*len
);
262 memcpy(hashedKey
, key
, *len
);
265 if (key_len
!= SHA_CBLOCK
)
266 memset(&hkey
[key_len
], 0, SHA_CBLOCK
- key_len
);
271 for (i
=0; i
<SHA_CBLOCK
; i
++)
275 n8_precomp_SHA1_Init(&ctxi
);
276 n8_precomp_SHA1_Update(&ctxi
,pad
,SHA_CBLOCK
);
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
));
287 for (i
=0; i
<SHA_CBLOCK
; i
++)
291 n8_precomp_SHA1_Init(&ctxo
);
292 n8_precomp_SHA1_Update(&ctxo
,pad
,SHA_CBLOCK
);
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
));
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.
326 * N8_STATUS_OK - the function succeeded.
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
,
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
);
353 DBG(("IPAD={A=%08x B=%08x C=%08x D=%08x}\n",
354 ctx
.A
, ctx
.B
, ctx
.C
, ctx
.D
));
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
);
366 DBG(("OPAD={A=%08x B=%08x C=%08x D=%08x}\n",
367 ctx
.A
, ctx
.B
, ctx
.C
, ctx
.D
));
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.
400 * N8_STATUS_OK - the function succeeded.
401 * N8_INVALID_HASH - hash_alg is not N8_MD5 or N8_SHA1.
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
,
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
);
435 /* Not a valid choice for the hash algorithm. */
436 status
= N8_INVALID_HASH
;