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
28 #include "tpmtok_int.h"
29
30 CK_RV
sign_mgr_init(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_MECHANISM * mech,CK_BBOOL recover_mode,CK_OBJECT_HANDLE key)31 sign_mgr_init(SESSION * sess,
32 SIGN_VERIFY_CONTEXT * ctx,
33 CK_MECHANISM * mech,
34 CK_BBOOL recover_mode,
35 CK_OBJECT_HANDLE key)
36 {
37 OBJECT * key_obj = NULL;
38 CK_ATTRIBUTE * attr = NULL;
39 CK_BYTE * ptr = NULL;
40 CK_KEY_TYPE keytype;
41 CK_OBJECT_CLASS class;
42 CK_BBOOL flag;
43 CK_RV rc;
44
45 if (! sess || ! ctx) {
46 return (CKR_FUNCTION_FAILED);
47 }
48 if (ctx->active != FALSE) {
49 return (CKR_OPERATION_ACTIVE);
50 }
51
52 rc = object_mgr_find_in_map1(sess->hContext, key, &key_obj);
53 if (rc != CKR_OK) {
54 return (CKR_KEY_HANDLE_INVALID);
55 }
56 rc = template_attribute_find(key_obj->template, CKA_SIGN, &attr);
57 if (rc == FALSE) {
58 return (CKR_KEY_TYPE_INCONSISTENT);
59 } else {
60 flag = *(CK_BBOOL *)attr->pValue;
61 if (flag != TRUE) {
62 return (CKR_KEY_FUNCTION_NOT_PERMITTED);
63 }
64 }
65
66 switch (mech->mechanism) {
67 case CKM_RSA_PKCS:
68 {
69 rc = template_attribute_find(key_obj->template,
70 CKA_KEY_TYPE, &attr);
71 if (rc == FALSE) {
72 return (CKR_KEY_TYPE_INCONSISTENT);
73 } else {
74 keytype = *(CK_KEY_TYPE *)attr->pValue;
75 if (keytype != CKK_RSA) {
76 return (CKR_KEY_TYPE_INCONSISTENT);
77 }
78 }
79
80 // must be a PRIVATE key
81 //
82 flag = template_attribute_find(key_obj->template,
83 CKA_CLASS, &attr);
84 if (flag == FALSE) {
85 return (CKR_KEY_TYPE_INCONSISTENT);
86 }
87 else
88 class = *(CK_OBJECT_CLASS *)attr->pValue;
89
90 if (class != CKO_PRIVATE_KEY) {
91 return (CKR_KEY_TYPE_INCONSISTENT);
92 }
93 // PKCS #11 doesn't allow multi - part RSA operations
94 //
95 ctx->context_len = 0;
96 ctx->context = NULL;
97 }
98 break;
99 case CKM_MD5_RSA_PKCS:
100 case CKM_SHA1_RSA_PKCS:
101 {
102 rc = template_attribute_find(key_obj->template,
103 CKA_KEY_TYPE, &attr);
104 if (rc == FALSE) {
105 return (CKR_KEY_TYPE_INCONSISTENT);
106 } else {
107 keytype = *(CK_KEY_TYPE *)attr->pValue;
108 if (keytype != CKK_RSA) {
109 return (CKR_KEY_TYPE_INCONSISTENT);
110 }
111 }
112
113 // must be a PRIVATE key operation
114 //
115 flag = template_attribute_find(key_obj->template,
116 CKA_CLASS, &attr);
117 if (flag == FALSE) {
118 return (CKR_FUNCTION_FAILED);
119 }
120 else
121 class = *(CK_OBJECT_CLASS *)attr->pValue;
122
123 if (class != CKO_PRIVATE_KEY) {
124 return (CKR_FUNCTION_FAILED);
125 }
126 ctx->context_len = sizeof (RSA_DIGEST_CONTEXT);
127 ctx->context = (CK_BYTE *)malloc(
128 sizeof (RSA_DIGEST_CONTEXT));
129 if (! ctx->context) {
130 return (CKR_HOST_MEMORY);
131 }
132 (void) memset(ctx->context, 0x0,
133 sizeof (RSA_DIGEST_CONTEXT));
134 }
135 break;
136 case CKM_MD5_HMAC:
137 case CKM_SHA_1_HMAC:
138 {
139 if (mech->ulParameterLen != 0) {
140 return (CKR_MECHANISM_PARAM_INVALID);
141 }
142 rc = template_attribute_find(key_obj->template,
143 CKA_KEY_TYPE, &attr);
144 if (rc == FALSE) {
145 return (CKR_KEY_TYPE_INCONSISTENT);
146 } else {
147 keytype = *(CK_KEY_TYPE *)attr->pValue;
148 if (keytype != CKK_GENERIC_SECRET) {
149 return (CKR_KEY_TYPE_INCONSISTENT);
150 }
151 }
152
153 // PKCS #11 doesn't allow multi - part HMAC operations
154 //
155 ctx->context_len = 0;
156 ctx->context = NULL;
157 }
158 break;
159
160 case CKM_MD5_HMAC_GENERAL:
161 case CKM_SHA_1_HMAC_GENERAL:
162 {
163 CK_MAC_GENERAL_PARAMS *param =
164 (CK_MAC_GENERAL_PARAMS *)mech->pParameter;
165
166 if (mech->ulParameterLen !=
167 sizeof (CK_MAC_GENERAL_PARAMS)) {
168 return (CKR_MECHANISM_PARAM_INVALID);
169 }
170
171 if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) &&
172 (*param > 16)) {
173 return (CKR_MECHANISM_PARAM_INVALID);
174 }
175 if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) &&
176 (*param > 20)) {
177 return (CKR_MECHANISM_PARAM_INVALID);
178 }
179 rc = template_attribute_find(key_obj->template,
180 CKA_KEY_TYPE, &attr);
181 if (rc == FALSE) {
182 return (CKR_KEY_TYPE_INCONSISTENT);
183 } else {
184 keytype = *(CK_KEY_TYPE *)attr->pValue;
185 if (keytype != CKK_GENERIC_SECRET) {
186 return (CKR_KEY_TYPE_INCONSISTENT);
187 }
188 }
189
190 // PKCS #11 doesn't allow multi - part HMAC operations
191 //
192 ctx->context_len = 0;
193 ctx->context = NULL;
194 }
195 break;
196 default:
197 return (CKR_MECHANISM_INVALID);
198 }
199
200 if (mech->ulParameterLen > 0 && mech->pParameter == NULL)
201 return (CKR_ARGUMENTS_BAD);
202
203 if (mech->ulParameterLen > 0) {
204 ptr = (CK_BYTE *)malloc(mech->ulParameterLen);
205 if (! ptr) {
206 return (CKR_HOST_MEMORY);
207 }
208 (void) memcpy(ptr, mech->pParameter, mech->ulParameterLen);
209 }
210
211 ctx->key = key;
212 ctx->mech.ulParameterLen = mech->ulParameterLen;
213 ctx->mech.mechanism = mech->mechanism;
214 ctx->mech.pParameter = ptr;
215 ctx->multi = FALSE;
216 ctx->active = TRUE;
217 ctx->recover = recover_mode;
218
219 return (CKR_OK);
220 }
221
222 CK_RV
sign_mgr_cleanup(SIGN_VERIFY_CONTEXT * ctx)223 sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
224 {
225 if (! ctx) {
226 return (CKR_FUNCTION_FAILED);
227 }
228 ctx->key = 0;
229 ctx->mech.ulParameterLen = 0;
230 ctx->mech.mechanism = 0;
231 ctx->multi = FALSE;
232 ctx->active = FALSE;
233 ctx->recover = FALSE;
234 ctx->context_len = 0;
235
236 if (ctx->mech.pParameter) {
237 free(ctx->mech.pParameter);
238 ctx->mech.pParameter = NULL;
239 }
240
241 if (ctx->context) {
242 free(ctx->context);
243 ctx->context = NULL;
244 }
245
246 return (CKR_OK);
247 }
248
249 CK_RV
sign_mgr_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)250 sign_mgr_sign(SESSION * sess,
251 CK_BBOOL length_only,
252 SIGN_VERIFY_CONTEXT * ctx,
253 CK_BYTE * in_data,
254 CK_ULONG in_data_len,
255 CK_BYTE * out_data,
256 CK_ULONG * out_data_len)
257 {
258 if (! sess || ! ctx) {
259 return (CKR_FUNCTION_FAILED);
260 }
261 if (ctx->active == FALSE) {
262 return (CKR_OPERATION_NOT_INITIALIZED);
263 }
264 if (ctx->recover == TRUE) {
265 return (CKR_OPERATION_NOT_INITIALIZED);
266 }
267
268 // if the caller just wants the signature length, there is no reason to
269 // specify the input data. I just need the input data length
270 //
271 if ((length_only == FALSE) && (! in_data || ! out_data)) {
272 return (CKR_FUNCTION_FAILED);
273 }
274 if (ctx->multi == TRUE) {
275 return (CKR_OPERATION_ACTIVE);
276 }
277 switch (ctx->mech.mechanism) {
278 case CKM_RSA_PKCS:
279 return (rsa_pkcs_sign(sess, length_only, ctx,
280 in_data, in_data_len,
281 out_data, out_data_len));
282 case CKM_MD5_RSA_PKCS:
283 case CKM_SHA1_RSA_PKCS:
284 return (rsa_hash_pkcs_sign(sess, length_only, ctx,
285 in_data, in_data_len,
286 out_data, out_data_len));
287
288 case CKM_MD5_HMAC:
289 case CKM_MD5_HMAC_GENERAL:
290 return (md5_hmac_sign(sess, length_only, ctx,
291 in_data, in_data_len,
292 out_data, out_data_len));
293 case CKM_SHA_1_HMAC:
294 case CKM_SHA_1_HMAC_GENERAL:
295 return (sha1_hmac_sign(sess, length_only, ctx,
296 in_data, in_data_len,
297 out_data, out_data_len));
298 default:
299 return (CKR_MECHANISM_INVALID);
300 }
301 }
302
303 CK_RV
sign_mgr_sign_update(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len)304 sign_mgr_sign_update(SESSION * sess,
305 SIGN_VERIFY_CONTEXT * ctx,
306 CK_BYTE * in_data,
307 CK_ULONG in_data_len)
308 {
309 if (! sess || ! ctx || ! in_data) {
310 return (CKR_FUNCTION_FAILED);
311 }
312
313 if (ctx->active == FALSE) {
314 return (CKR_OPERATION_NOT_INITIALIZED);
315 }
316 if (ctx->recover == TRUE) {
317 return (CKR_OPERATION_NOT_INITIALIZED);
318 }
319 ctx->multi = TRUE;
320
321 switch (ctx->mech.mechanism) {
322 case CKM_MD5_RSA_PKCS:
323 case CKM_SHA1_RSA_PKCS:
324 return (rsa_hash_pkcs_sign_update(sess, ctx,
325 in_data, in_data_len));
326 default:
327 return (CKR_MECHANISM_INVALID);
328 }
329 }
330
331 CK_RV
sign_mgr_sign_final(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * signature,CK_ULONG * sig_len)332 sign_mgr_sign_final(SESSION * sess,
333 CK_BBOOL length_only,
334 SIGN_VERIFY_CONTEXT * ctx,
335 CK_BYTE * signature,
336 CK_ULONG * sig_len)
337 {
338 if (! sess || ! ctx) {
339 return (CKR_FUNCTION_FAILED);
340 }
341 if (ctx->active == FALSE) {
342 return (CKR_OPERATION_NOT_INITIALIZED);
343 }
344 if (ctx->recover == TRUE) {
345 return (CKR_OPERATION_NOT_INITIALIZED);
346 }
347 switch (ctx->mech.mechanism) {
348 case CKM_MD5_RSA_PKCS:
349 case CKM_SHA1_RSA_PKCS:
350 return (rsa_hash_pkcs_sign_final(sess, length_only,
351 ctx, signature, sig_len));
352 default:
353 return (CKR_MECHANISM_INVALID);
354 }
355 }
356
357 CK_RV
sign_mgr_sign_recover(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)358 sign_mgr_sign_recover(SESSION * sess,
359 CK_BBOOL length_only,
360 SIGN_VERIFY_CONTEXT * ctx,
361 CK_BYTE * in_data,
362 CK_ULONG in_data_len,
363 CK_BYTE * out_data,
364 CK_ULONG * out_data_len)
365 {
366 if (! sess || ! ctx) {
367 return (CKR_FUNCTION_FAILED);
368 }
369 if (ctx->active == FALSE) {
370 return (CKR_OPERATION_NOT_INITIALIZED);
371 }
372 if (ctx->recover == FALSE) {
373 return (CKR_OPERATION_NOT_INITIALIZED);
374 }
375
376 // if the caller just wants the signature length, there is no reason to
377 // specify the input data. I just need the input data length
378 //
379 if ((length_only == FALSE) && (! in_data || ! out_data)) {
380 return (CKR_FUNCTION_FAILED);
381 }
382 if (ctx->multi == TRUE) {
383 return (CKR_OPERATION_ACTIVE);
384 }
385 switch (ctx->mech.mechanism) {
386 case CKM_RSA_PKCS:
387 return (rsa_pkcs_sign(sess, length_only, ctx,
388 in_data, in_data_len,
389 out_data, out_data_len));
390 default:
391 return (CKR_MECHANISM_INVALID);
392 }
393 }
394