xref: /onnv-gate/usr/src/common/crypto/fips/fips_sha1_util.c (revision 10500:a10fbcfc2f21)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/param.h>
28 #include <sys/errno.h>
29 #include <sys/kmem.h>
30 #include <sys/systm.h>
31 #include <sys/sha1.h>
32 #include <sys/crypto/common.h>
33 #include <sys/cmn_err.h>
34 #ifndef _KERNEL
35 #include <stdlib.h>
36 #include <string.h>
37 #include <strings.h>
38 #include <stdio.h>
39 #include <security/cryptoki.h>
40 #include <cryptoutil.h>
41 #include "softMAC.h"
42 #endif
43 #include <sha1/sha1_impl.h>
44 
45 /*
46  * fips_sha1_build_context()
47  *
48  * Description:
49  *	This function allocates and initializes SHA1 context
50  *	context.
51  */
52 SHA1_CTX *
53 fips_sha1_build_context(void)
54 {
55 	SHA1_CTX *sha1_context;
56 
57 
58 #ifndef _KERNEL
59 	if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL)
60 #else
61 	if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX),
62 	    KM_SLEEP)) == NULL)
63 #endif
64 		return (NULL);
65 
66 	SHA1Init(sha1_context);
67 
68 	return (sha1_context);
69 
70 }
71 
72 /*
73  * fips_sha1_hash()
74  *
75  * Arguments:
76  *	sha1_context:	pointer to SHA1 context
77  *	in:	pointer to the input data to be hashed
78  *	inlen:	length of the input data
79  *	out:	pointer to the output data after hashing
80  *
81  * Description:
82  *	This function calls the low-level SHA1 routines for hashing.
83  *
84  */
85 int
86 fips_sha1_hash(SHA1_CTX *sha1_context, uchar_t *in, ulong_t inlen, uchar_t *out)
87 {
88 
89 	if (in != NULL) {
90 #ifdef	__sparcv9
91 		SHA1Update((SHA1_CTX *)sha1_context, in, (uint_t)inlen);
92 #else	/* !__sparcv9 */
93 		SHA1Update((SHA1_CTX *)sha1_context, in, inlen);
94 #endif	/* __sparcv9 */
95 		SHA1Final(out, (SHA1_CTX *)sha1_context);
96 		return (CKR_OK);
97 	} else
98 		return (CKR_ARGUMENTS_BAD);
99 
100 }
101 
102 
103 #ifndef _KERNEL
104 soft_hmac_ctx_t *
105 fips_sha1_hmac_build_context(uint8_t *secret_key,
106 	unsigned int secret_key_length)
107 {
108 
109 	soft_hmac_ctx_t *hmac_ctx;
110 	uint32_t sha1_ipad[SHA1_HMAC_INTS_PER_BLOCK];
111 	uint32_t sha1_opad[SHA1_HMAC_INTS_PER_BLOCK];
112 
113 	hmac_ctx = malloc(sizeof (soft_hmac_ctx_t));
114 
115 	if (hmac_ctx == NULL) {
116 		return (NULL);
117 	}
118 
119 	hmac_ctx->hmac_len = SHA1_HASH_SIZE;
120 	bzero(sha1_ipad, SHA1_HMAC_BLOCK_SIZE);
121 	bzero(sha1_opad, SHA1_HMAC_BLOCK_SIZE);
122 
123 	(void) memcpy(sha1_ipad, secret_key, secret_key_length);
124 	(void) memcpy(sha1_opad, secret_key, secret_key_length);
125 
126 	sha1_hmac_ctx_init(&hmac_ctx->hc_ctx_u.sha1_ctx, sha1_ipad,
127 	    sha1_opad);
128 
129 	return (hmac_ctx);
130 
131 }
132 
133 CK_RV
134 fips_hmac_sha1_hash(unsigned char *hmac_computed,
135 	uint8_t *secret_key,
136 	unsigned int secret_key_length,
137 	uint8_t *message,
138 	unsigned int message_length)
139 {
140 
141 	soft_hmac_ctx_t *hmac_ctx = NULL;
142 
143 	hmac_ctx = fips_sha1_hmac_build_context(secret_key,
144 	    secret_key_length);
145 
146 	if (hmac_ctx == NULL)
147 		return (CKR_HOST_MEMORY);
148 
149 	if (message != NULL) {
150 		SOFT_MAC_UPDATE(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx),
151 		    message, message_length);
152 	}
153 
154 	SOFT_MAC_FINAL(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx), hmac_computed);
155 
156 	free(hmac_ctx);
157 	return (CKR_OK);
158 }
159 
160 #else /* _KERNEL */
161 
162 /*
163  * Initialize a SHA1-HMAC context.
164  */
165 void
166 sha1_mac_init_ctx(sha1_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
167 {
168 	uint32_t ipad[SHA1_HMAC_INTS_PER_BLOCK];
169 	uint32_t opad[SHA1_HMAC_INTS_PER_BLOCK];
170 	uint_t i;
171 
172 	bzero(ipad, SHA1_HMAC_BLOCK_SIZE);
173 	bzero(opad, SHA1_HMAC_BLOCK_SIZE);
174 
175 	bcopy(keyval, ipad, length_in_bytes);
176 	bcopy(keyval, opad, length_in_bytes);
177 
178 	/* XOR key with ipad (0x36) and opad (0x5c) */
179 	for (i = 0; i < SHA1_HMAC_INTS_PER_BLOCK; i++) {
180 		ipad[i] ^= 0x36363636;
181 		opad[i] ^= 0x5c5c5c5c;
182 	}
183 
184 	/* perform SHA1 on ipad */
185 	SHA1Init(&ctx->hc_icontext);
186 	SHA1Update(&ctx->hc_icontext, (uint8_t *)ipad, SHA1_HMAC_BLOCK_SIZE);
187 
188 	/* perform SHA1 on opad */
189 	SHA1Init(&ctx->hc_ocontext);
190 	SHA1Update(&ctx->hc_ocontext, (uint8_t *)opad, SHA1_HMAC_BLOCK_SIZE);
191 }
192 
193 sha1_hmac_ctx_t *
194 fips_sha1_hmac_build_context(uint8_t *secret_key,
195 	unsigned int secret_key_length)
196 {
197 	sha1_hmac_ctx_t *sha1_hmac_ctx_tmpl;
198 
199 
200 	/*
201 	 * Allocate and initialize SHA1 context.
202 	 */
203 	sha1_hmac_ctx_tmpl = kmem_alloc(sizeof (sha1_hmac_ctx_t),
204 	    KM_SLEEP);
205 	if (sha1_hmac_ctx_tmpl == NULL)
206 		return (NULL);
207 
208 	/*
209 	 * initialize ctx->hc_icontext and ctx->hc_ocontext
210 	 */
211 	sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, secret_key,
212 	    secret_key_length);
213 
214 
215 	sha1_hmac_ctx_tmpl->hc_mech_type = SHA1_HMAC_MECH_INFO_TYPE;
216 
217 
218 	return (sha1_hmac_ctx_tmpl);
219 }
220 
221 void
222 fips_hmac_sha1_hash(sha1_hmac_ctx_t *sha1_hmac_ctx,
223 	uint8_t *message, uint32_t message_len,
224 	uint8_t *hmac_computed)
225 {
226 
227 	/* do a SHA1 update of the inner context using the specified data */
228 	SHA1Update(&((sha1_hmac_ctx)->hc_icontext), message,
229 	    message_len);
230 
231 	/*
232 	 * Do a SHA1 final on the inner context.
233 	 */
234 	SHA1Final(hmac_computed, &((sha1_hmac_ctx)->hc_icontext));
235 
236 	/*
237 	 * Do an SHA1 update on the outer context, feeding the inner
238 	 * digest as data.
239 	 */
240 	SHA1Update(&((sha1_hmac_ctx)->hc_ocontext), hmac_computed,
241 	    SHA1_HASH_SIZE);
242 
243 	/*
244 	 * Do a SHA1 final on the outer context, storing the computed
245 	 * digest in the caller's buffer.
246 	 */
247 	SHA1Final(hmac_computed, &((sha1_hmac_ctx)->hc_ocontext));
248 
249 }
250 
251 #endif
252 
253 /*
254  * SHA1 Power-On SelfTest(s).
255  */
256 int
257 fips_sha1_post(void)
258 {
259 
260 	/*
261 	 * SHA-1 Known Hash Message
262 	 * Source from NIST SHA1ShortMsg (L = 512-bits).
263 	 */
264 	static uint8_t sha1_known_hash_message[] = {
265 		0x7e, 0x3a, 0x4c, 0x32, 0x5c, 0xb9, 0xc5, 0x2b,
266 		0x88, 0x38, 0x7f, 0x93, 0xd0, 0x1a, 0xe8, 0x6d,
267 		0x42, 0x09, 0x8f, 0x5e, 0xfa, 0x7f, 0x94, 0x57,
268 		0x38, 0x8b, 0x5e, 0x74, 0xb6, 0xd2, 0x8b, 0x24,
269 		0x38, 0xd4, 0x2d, 0x8b, 0x64, 0x70, 0x33, 0x24,
270 		0xd4, 0xaa, 0x25, 0xab, 0x6a, 0xad, 0x15, 0x3a,
271 		0xe3, 0x0c, 0xd2, 0xb2, 0xaf, 0x4d, 0x5e, 0x5c,
272 		0x00, 0xa8, 0xa2, 0xd0, 0x22, 0x0c, 0x61, 0x16
273 	};
274 
275 	/* SHA-1 Known Digest Message (160-bits). */
276 	static  uint8_t sha1_known_digest[] = {
277 		0xa3, 0x05, 0x44, 0x27, 0xcd, 0xb1, 0x3f, 0x16,
278 		0x4a, 0x61, 0x0b, 0x34, 0x87, 0x02, 0x72, 0x4c,
279 		0x80, 0x8a, 0x0d, 0xcc
280 	};
281 
282 	/* Source from NIST HMAC.txt Count = 0 */
283 	static uint8_t HMAC_known_secret_key[] = {
284 		0x7b, 0x10, 0xf4, 0x12, 0x4b, 0x15, 0xc8, 0x2e
285 	};
286 
287 	static uint8_t HMAC_known_secret_key_length
288 	    = sizeof (HMAC_known_secret_key);
289 
290 	/* known SHA1 hmac - truncated (10 bytes) */
291 	static uint8_t known_SHA1_hmac[] = {
292 		0x4e, 0xad, 0x12, 0xc2, 0xfe, 0x3d, 0x6e, 0xa4,
293 		0x3a, 0xcb
294 	};
295 
296 	static uint8_t hmac_sha1_known_hash_message[] = {
297 		0x27, 0xdc, 0xb5, 0xb1, 0xda, 0xf6, 0x0c, 0xfd,
298 		0x3e, 0x2f, 0x73, 0xd4, 0xd6, 0x4c, 0xa9, 0xc6,
299 		0x84, 0xf8, 0xbf, 0x71, 0xfc, 0x68, 0x2a, 0x46,
300 		0x79, 0x3b, 0x17, 0x90, 0xaf, 0xa4, 0xfe, 0xb1,
301 		0x00, 0xca, 0x7a, 0xaf, 0xf2, 0x6f, 0x58, 0xf0,
302 		0xe1, 0xd0, 0xed, 0x42, 0xf1, 0xcd, 0xad, 0x1f,
303 		0x47, 0x4a, 0xfa, 0x2e, 0x79, 0xd5, 0x3a, 0x0c,
304 		0x42, 0x89, 0x2c, 0x4d, 0x7b, 0x32, 0x7c, 0xbe,
305 		0x46, 0xb2, 0x95, 0xed, 0x8d, 0xa3, 0xb6, 0xec,
306 		0xab, 0x3d, 0x48, 0x51, 0x68, 0x7a, 0x6f, 0x81,
307 		0x2b, 0x79, 0xdf, 0x2f, 0x6b, 0x20, 0xf1, 0x1f,
308 		0x67, 0x06, 0xf5, 0x30, 0x17, 0x90, 0xca, 0x99,
309 		0x62, 0x5a, 0xad, 0x73, 0x91, 0xd8, 0x4f, 0x78,
310 		0x04, 0x3d, 0x2a, 0x0a, 0x23, 0x9b, 0x14, 0x77,
311 		0x98, 0x4c, 0x15, 0x7b, 0xbc, 0x92, 0x76, 0x06,
312 		0x4e, 0x7a, 0x1a, 0x40, 0x6b, 0x06, 0x12, 0xca
313 	};
314 
315 	/* SHA-1 variables. */
316 	uint8_t sha1_computed_digest[SHA1_DIGEST_LENGTH];
317 	uint8_t hmac_computed[SHA1_HMAC_BLOCK_SIZE];
318 	SHA1_CTX *sha1_context = NULL;
319 
320 #ifdef _KERNEL
321 	sha1_hmac_ctx_t *sha1_hmac_ctx = NULL;
322 #endif
323 
324 	int rv;
325 
326 	/* SHA-1 Known Answer Hashing Test. */
327 	sha1_context = fips_sha1_build_context();
328 	if (sha1_context == NULL)
329 		return (CKR_HOST_MEMORY);
330 
331 	rv = fips_sha1_hash(sha1_context, sha1_known_hash_message,
332 	    FIPS_KNOWN_HMAC_MESSAGE_LENGTH, sha1_computed_digest);
333 
334 	if ((rv != CKR_OK) ||
335 	    (memcmp(sha1_computed_digest, sha1_known_digest,
336 	    SHA1_DIGEST_LENGTH) != 0))
337 		return (CKR_DEVICE_ERROR);
338 
339 #ifdef _KERNEL
340 	/* SHA-1 HMAC Known Answer Hashing Test */
341 	sha1_hmac_ctx = fips_sha1_hmac_build_context(HMAC_known_secret_key,
342 	    HMAC_known_secret_key_length);
343 
344 	if (sha1_hmac_ctx == NULL)
345 		return (CKR_HOST_MEMORY);
346 
347 	fips_hmac_sha1_hash(sha1_hmac_ctx, hmac_sha1_known_hash_message,
348 	    sizeof (hmac_sha1_known_hash_message), hmac_computed);
349 #else
350 	rv = fips_hmac_sha1_hash(hmac_computed, HMAC_known_secret_key,
351 	    HMAC_known_secret_key_length, hmac_sha1_known_hash_message,
352 	    sizeof (hmac_sha1_known_hash_message));
353 
354 #endif
355 
356 #ifdef _KERNEL
357 	if (memcmp(hmac_computed, known_SHA1_hmac,
358 	    sizeof (known_SHA1_hmac)) != 0)
359 	return (CKR_DEVICE_ERROR);
360 #else
361 	if ((rv != CKR_OK) ||
362 	    (memcmp(hmac_computed, known_SHA1_hmac,
363 	    sizeof (known_SHA1_hmac)) != 0))
364 	return (CKR_DEVICE_ERROR);
365 #endif
366 
367 	return (rv);
368 
369 }
370