xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_tpm/common/mech_sha.c (revision 47e946e784719ae402ace34695f67b0e6e76ae5c)
1*47e946e7SWyllys Ingersoll /*
2*47e946e7SWyllys Ingersoll  * The Initial Developer of the Original Code is International
3*47e946e7SWyllys Ingersoll  * Business Machines Corporation. Portions created by IBM
4*47e946e7SWyllys Ingersoll  * Corporation are Copyright (C) 2005 International Business
5*47e946e7SWyllys Ingersoll  * Machines Corporation. All Rights Reserved.
6*47e946e7SWyllys Ingersoll  *
7*47e946e7SWyllys Ingersoll  * This program is free software; you can redistribute it and/or modify
8*47e946e7SWyllys Ingersoll  * it under the terms of the Common Public License as published by
9*47e946e7SWyllys Ingersoll  * IBM Corporation; either version 1 of the License, or (at your option)
10*47e946e7SWyllys Ingersoll  * any later version.
11*47e946e7SWyllys Ingersoll  *
12*47e946e7SWyllys Ingersoll  * This program is distributed in the hope that it will be useful,
13*47e946e7SWyllys Ingersoll  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*47e946e7SWyllys Ingersoll  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*47e946e7SWyllys Ingersoll  * Common Public License for more details.
16*47e946e7SWyllys Ingersoll  *
17*47e946e7SWyllys Ingersoll  * You should have received a copy of the Common Public License
18*47e946e7SWyllys Ingersoll  * along with this program; if not, a copy can be viewed at
19*47e946e7SWyllys Ingersoll  * http://www.opensource.org/licenses/cpl1.0.php.
20*47e946e7SWyllys Ingersoll  */
21*47e946e7SWyllys Ingersoll 
22*47e946e7SWyllys Ingersoll /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
23*47e946e7SWyllys Ingersoll /*
24*47e946e7SWyllys Ingersoll  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25*47e946e7SWyllys Ingersoll  * Use is subject to license terms.
26*47e946e7SWyllys Ingersoll  */
27*47e946e7SWyllys Ingersoll #include "tpmtok_int.h"
28*47e946e7SWyllys Ingersoll 
29*47e946e7SWyllys Ingersoll CK_RV
sha1_hash(SESSION * sess,CK_BBOOL length_only,DIGEST_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)30*47e946e7SWyllys Ingersoll sha1_hash(SESSION *sess,
31*47e946e7SWyllys Ingersoll 	CK_BBOOL length_only,
32*47e946e7SWyllys Ingersoll 	DIGEST_CONTEXT  *ctx,
33*47e946e7SWyllys Ingersoll 	CK_BYTE	 *in_data,
34*47e946e7SWyllys Ingersoll 	CK_ULONG in_data_len,
35*47e946e7SWyllys Ingersoll 	CK_BYTE	 *out_data,
36*47e946e7SWyllys Ingersoll 	CK_ULONG *out_data_len)
37*47e946e7SWyllys Ingersoll {
38*47e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! out_data_len) {
39*47e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
40*47e946e7SWyllys Ingersoll 	}
41*47e946e7SWyllys Ingersoll 	*out_data_len = SHA1_DIGEST_LENGTH;
42*47e946e7SWyllys Ingersoll 	if (length_only == TRUE) {
43*47e946e7SWyllys Ingersoll 		return (CKR_OK);
44*47e946e7SWyllys Ingersoll 	}
45*47e946e7SWyllys Ingersoll 
46*47e946e7SWyllys Ingersoll 	if (ctx->context.sha1ctx == NULL)
47*47e946e7SWyllys Ingersoll 		return (CKR_HOST_MEMORY);
48*47e946e7SWyllys Ingersoll 	SHA1Update(ctx->context.sha1ctx, in_data, in_data_len);
49*47e946e7SWyllys Ingersoll 
50*47e946e7SWyllys Ingersoll 	SHA1Final(out_data, ctx->context.sha1ctx);
51*47e946e7SWyllys Ingersoll 
52*47e946e7SWyllys Ingersoll 	return (CKR_OK);
53*47e946e7SWyllys Ingersoll }
54*47e946e7SWyllys Ingersoll 
55*47e946e7SWyllys Ingersoll CK_RV
sha1_hmac_sign(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)56*47e946e7SWyllys Ingersoll sha1_hmac_sign(SESSION		* sess,
57*47e946e7SWyllys Ingersoll 	CK_BBOOL		length_only,
58*47e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  * ctx,
59*47e946e7SWyllys Ingersoll 	CK_BYTE		* in_data,
60*47e946e7SWyllys Ingersoll 	CK_ULONG		in_data_len,
61*47e946e7SWyllys Ingersoll 	CK_BYTE		* out_data,
62*47e946e7SWyllys Ingersoll 	CK_ULONG		* out_data_len) {
63*47e946e7SWyllys Ingersoll 	OBJECT	  * key_obj = NULL;
64*47e946e7SWyllys Ingersoll 	CK_ATTRIBUTE    * attr    = NULL;
65*47e946e7SWyllys Ingersoll 	CK_BYTE	   hash[SHA1_DIGEST_LENGTH];
66*47e946e7SWyllys Ingersoll 	DIGEST_CONTEXT    digest_ctx;
67*47e946e7SWyllys Ingersoll 	CK_MECHANISM	digest_mech;
68*47e946e7SWyllys Ingersoll 	CK_BYTE	   k_ipad[SHA1_BLOCK_SIZE];
69*47e946e7SWyllys Ingersoll 	CK_BYTE	   k_opad[SHA1_BLOCK_SIZE];
70*47e946e7SWyllys Ingersoll 	CK_ULONG	  key_bytes, hash_len, hmac_len;
71*47e946e7SWyllys Ingersoll 	CK_ULONG	  i;
72*47e946e7SWyllys Ingersoll 	CK_RV		rc;
73*47e946e7SWyllys Ingersoll 
74*47e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! out_data_len) {
75*47e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
76*47e946e7SWyllys Ingersoll 	}
77*47e946e7SWyllys Ingersoll 
78*47e946e7SWyllys Ingersoll 	if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) {
79*47e946e7SWyllys Ingersoll 		hmac_len = *(CK_ULONG *)ctx->mech.pParameter;
80*47e946e7SWyllys Ingersoll 
81*47e946e7SWyllys Ingersoll 		if (hmac_len == 0) {
82*47e946e7SWyllys Ingersoll 			*out_data_len = 0;
83*47e946e7SWyllys Ingersoll 			return (CKR_OK);
84*47e946e7SWyllys Ingersoll 		}
85*47e946e7SWyllys Ingersoll 	} else {
86*47e946e7SWyllys Ingersoll 		hmac_len = SHA1_DIGEST_LENGTH;
87*47e946e7SWyllys Ingersoll 	}
88*47e946e7SWyllys Ingersoll 
89*47e946e7SWyllys Ingersoll 	*out_data_len = hmac_len;
90*47e946e7SWyllys Ingersoll 	if (length_only == TRUE) {
91*47e946e7SWyllys Ingersoll 		return (CKR_OK);
92*47e946e7SWyllys Ingersoll 	}
93*47e946e7SWyllys Ingersoll 
94*47e946e7SWyllys Ingersoll 	(void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT));
95*47e946e7SWyllys Ingersoll 
96*47e946e7SWyllys Ingersoll 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
97*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
98*47e946e7SWyllys Ingersoll 		return (rc);
99*47e946e7SWyllys Ingersoll 	}
100*47e946e7SWyllys Ingersoll 	rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr);
101*47e946e7SWyllys Ingersoll 	if (rc == FALSE) {
102*47e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
103*47e946e7SWyllys Ingersoll 	} else
104*47e946e7SWyllys Ingersoll 		key_bytes = attr->ulValueLen;
105*47e946e7SWyllys Ingersoll 
106*47e946e7SWyllys Ingersoll 
107*47e946e7SWyllys Ingersoll 	if (key_bytes > SHA1_BLOCK_SIZE) {
108*47e946e7SWyllys Ingersoll 		digest_mech.mechanism	= CKM_SHA_1;
109*47e946e7SWyllys Ingersoll 		digest_mech.ulParameterLen = 0;
110*47e946e7SWyllys Ingersoll 		digest_mech.pParameter	= NULL;
111*47e946e7SWyllys Ingersoll 
112*47e946e7SWyllys Ingersoll 		rc = digest_mgr_init(sess, &digest_ctx, &digest_mech);
113*47e946e7SWyllys Ingersoll 		if (rc != CKR_OK) {
114*47e946e7SWyllys Ingersoll 			(void) digest_mgr_cleanup(&digest_ctx);
115*47e946e7SWyllys Ingersoll 			return (rc);
116*47e946e7SWyllys Ingersoll 		}
117*47e946e7SWyllys Ingersoll 
118*47e946e7SWyllys Ingersoll 		hash_len = sizeof (hash);
119*47e946e7SWyllys Ingersoll 		rc = digest_mgr_digest(sess, FALSE, &digest_ctx,
120*47e946e7SWyllys Ingersoll 		    attr->pValue, attr->ulValueLen, hash,  &hash_len);
121*47e946e7SWyllys Ingersoll 		if (rc != CKR_OK) {
122*47e946e7SWyllys Ingersoll 			(void) digest_mgr_cleanup(&digest_ctx);
123*47e946e7SWyllys Ingersoll 			return (rc);
124*47e946e7SWyllys Ingersoll 		}
125*47e946e7SWyllys Ingersoll 
126*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
127*47e946e7SWyllys Ingersoll 		(void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT));
128*47e946e7SWyllys Ingersoll 
129*47e946e7SWyllys Ingersoll 		for (i = 0; i < hash_len; i++) {
130*47e946e7SWyllys Ingersoll 			k_ipad[i] = hash[i] ^ 0x36;
131*47e946e7SWyllys Ingersoll 			k_opad[i] = hash[i] ^ 0x5C;
132*47e946e7SWyllys Ingersoll 		}
133*47e946e7SWyllys Ingersoll 
134*47e946e7SWyllys Ingersoll 		(void) memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - i);
135*47e946e7SWyllys Ingersoll 		(void) memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - i);
136*47e946e7SWyllys Ingersoll 	} else {
137*47e946e7SWyllys Ingersoll 		CK_BYTE *key = attr->pValue;
138*47e946e7SWyllys Ingersoll 
139*47e946e7SWyllys Ingersoll 		for (i = 0; i < key_bytes; i++) {
140*47e946e7SWyllys Ingersoll 			k_ipad[i] = key[i] ^ 0x36;
141*47e946e7SWyllys Ingersoll 			k_opad[i] = key[i] ^ 0x5C;
142*47e946e7SWyllys Ingersoll 		}
143*47e946e7SWyllys Ingersoll 
144*47e946e7SWyllys Ingersoll 		(void) memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - key_bytes);
145*47e946e7SWyllys Ingersoll 		(void) memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - key_bytes);
146*47e946e7SWyllys Ingersoll 	}
147*47e946e7SWyllys Ingersoll 
148*47e946e7SWyllys Ingersoll 	digest_mech.mechanism	= CKM_SHA_1;
149*47e946e7SWyllys Ingersoll 	digest_mech.ulParameterLen = 0;
150*47e946e7SWyllys Ingersoll 	digest_mech.pParameter	= NULL;
151*47e946e7SWyllys Ingersoll 
152*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
153*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
154*47e946e7SWyllys Ingersoll 		return (rc);
155*47e946e7SWyllys Ingersoll 	}
156*47e946e7SWyllys Ingersoll 
157*47e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_update(sess, &digest_ctx,
158*47e946e7SWyllys Ingersoll 	    k_ipad, SHA1_BLOCK_SIZE);
159*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
160*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
161*47e946e7SWyllys Ingersoll 		return (rc);
162*47e946e7SWyllys Ingersoll 	}
163*47e946e7SWyllys Ingersoll 
164*47e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_update(sess, &digest_ctx, in_data, in_data_len);
165*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
166*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
167*47e946e7SWyllys Ingersoll 		return (rc);
168*47e946e7SWyllys Ingersoll 	}
169*47e946e7SWyllys Ingersoll 
170*47e946e7SWyllys Ingersoll 	hash_len = sizeof (hash);
171*47e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_final(sess, &digest_ctx, hash, &hash_len);
172*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
173*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
174*47e946e7SWyllys Ingersoll 		return (rc);
175*47e946e7SWyllys Ingersoll 	}
176*47e946e7SWyllys Ingersoll 
177*47e946e7SWyllys Ingersoll 	(void) digest_mgr_cleanup(&digest_ctx);
178*47e946e7SWyllys Ingersoll 	(void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT));
179*47e946e7SWyllys Ingersoll 
180*47e946e7SWyllys Ingersoll 	rc = digest_mgr_init(sess, &digest_ctx, &digest_mech);
181*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
182*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
183*47e946e7SWyllys Ingersoll 		return (rc);
184*47e946e7SWyllys Ingersoll 	}
185*47e946e7SWyllys Ingersoll 
186*47e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_update(sess, &digest_ctx,
187*47e946e7SWyllys Ingersoll 	    k_opad, SHA1_BLOCK_SIZE);
188*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
189*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
190*47e946e7SWyllys Ingersoll 		return (rc);
191*47e946e7SWyllys Ingersoll 	}
192*47e946e7SWyllys Ingersoll 
193*47e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_update(sess, &digest_ctx, hash, hash_len);
194*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
195*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
196*47e946e7SWyllys Ingersoll 		return (rc);
197*47e946e7SWyllys Ingersoll 	}
198*47e946e7SWyllys Ingersoll 
199*47e946e7SWyllys Ingersoll 	hash_len = sizeof (hash);
200*47e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_final(sess, &digest_ctx, hash, &hash_len);
201*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
202*47e946e7SWyllys Ingersoll 		(void) digest_mgr_cleanup(&digest_ctx);
203*47e946e7SWyllys Ingersoll 		return (rc);
204*47e946e7SWyllys Ingersoll 	}
205*47e946e7SWyllys Ingersoll 
206*47e946e7SWyllys Ingersoll 	(void) memcpy(out_data, hash, hmac_len);
207*47e946e7SWyllys Ingersoll 	*out_data_len = hmac_len;
208*47e946e7SWyllys Ingersoll 
209*47e946e7SWyllys Ingersoll 	(void) digest_mgr_cleanup(&digest_ctx);
210*47e946e7SWyllys Ingersoll 
211*47e946e7SWyllys Ingersoll 	return (CKR_OK);
212*47e946e7SWyllys Ingersoll }
213*47e946e7SWyllys Ingersoll 
214*47e946e7SWyllys Ingersoll CK_RV
sha1_hmac_verify(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * signature,CK_ULONG sig_len)215*47e946e7SWyllys Ingersoll sha1_hmac_verify(SESSION *sess,
216*47e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  *ctx,
217*47e946e7SWyllys Ingersoll 	CK_BYTE	*in_data,
218*47e946e7SWyllys Ingersoll 	CK_ULONG in_data_len,
219*47e946e7SWyllys Ingersoll 	CK_BYTE	*signature,
220*47e946e7SWyllys Ingersoll 	CK_ULONG sig_len)
221*47e946e7SWyllys Ingersoll {
222*47e946e7SWyllys Ingersoll 	CK_BYTE		hmac[SHA1_DIGEST_LENGTH];
223*47e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  hmac_ctx;
224*47e946e7SWyllys Ingersoll 	CK_ULONG	hmac_len, len;
225*47e946e7SWyllys Ingersoll 	CK_RV		rc;
226*47e946e7SWyllys Ingersoll 
227*47e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! in_data || ! signature) {
228*47e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
229*47e946e7SWyllys Ingersoll 	}
230*47e946e7SWyllys Ingersoll 	if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL)
231*47e946e7SWyllys Ingersoll 		hmac_len = *(CK_ULONG *)ctx->mech.pParameter;
232*47e946e7SWyllys Ingersoll 	else
233*47e946e7SWyllys Ingersoll 		hmac_len = SHA1_DIGEST_LENGTH;
234*47e946e7SWyllys Ingersoll 
235*47e946e7SWyllys Ingersoll 	(void) memset(&hmac_ctx, 0, sizeof (SIGN_VERIFY_CONTEXT));
236*47e946e7SWyllys Ingersoll 
237*47e946e7SWyllys Ingersoll 	rc = sign_mgr_init(sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key);
238*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
239*47e946e7SWyllys Ingersoll 		goto done;
240*47e946e7SWyllys Ingersoll 	}
241*47e946e7SWyllys Ingersoll 	len = sizeof (hmac);
242*47e946e7SWyllys Ingersoll 	rc = sign_mgr_sign(sess, FALSE, &hmac_ctx,
243*47e946e7SWyllys Ingersoll 	    in_data, in_data_len, hmac,   &len);
244*47e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
245*47e946e7SWyllys Ingersoll 		goto done;
246*47e946e7SWyllys Ingersoll 	}
247*47e946e7SWyllys Ingersoll 	if ((len != hmac_len) || (len != sig_len)) {
248*47e946e7SWyllys Ingersoll 		rc = CKR_SIGNATURE_LEN_RANGE;
249*47e946e7SWyllys Ingersoll 		goto done;
250*47e946e7SWyllys Ingersoll 	}
251*47e946e7SWyllys Ingersoll 
252*47e946e7SWyllys Ingersoll 	if (memcmp(hmac, signature, hmac_len) != 0) {
253*47e946e7SWyllys Ingersoll 		rc = CKR_SIGNATURE_INVALID;
254*47e946e7SWyllys Ingersoll 	}
255*47e946e7SWyllys Ingersoll 	done:
256*47e946e7SWyllys Ingersoll 	(void) sign_mgr_cleanup(&hmac_ctx);
257*47e946e7SWyllys Ingersoll 	return (rc);
258*47e946e7SWyllys Ingersoll }
259