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