|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 /* |
|
5 * This file implements PKCS 11 on top of our existing security modules |
|
6 * |
|
7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. |
|
8 * This implementation has two slots: |
|
9 * slot 1 is our generic crypto support. It does not require login. |
|
10 * It supports Public Key ops, and all they bulk ciphers and hashes. |
|
11 * It can also support Private Key ops for imported Private keys. It does |
|
12 * not have any token storage. |
|
13 * slot 2 is our private key support. It requires a login before use. It |
|
14 * can store Private Keys and Certs as token objects. Currently only private |
|
15 * keys and their associated Certificates are saved on the token. |
|
16 * |
|
17 * In this implementation, session objects are only visible to the session |
|
18 * that created or generated them. |
|
19 */ |
|
20 #include "seccomon.h" |
|
21 #include "secitem.h" |
|
22 #include "secport.h" |
|
23 #include "blapi.h" |
|
24 #include "pkcs11.h" |
|
25 #include "pkcs11i.h" |
|
26 #include "pkcs1sig.h" |
|
27 #include "lowkeyi.h" |
|
28 #include "secder.h" |
|
29 #include "secdig.h" |
|
30 #include "lowpbe.h" /* We do PBE below */ |
|
31 #include "pkcs11t.h" |
|
32 #include "secoid.h" |
|
33 #include "alghmac.h" |
|
34 #include "softoken.h" |
|
35 #include "secasn1.h" |
|
36 #include "secerr.h" |
|
37 |
|
38 #include "prprf.h" |
|
39 |
|
40 #define __PASTE(x,y) x##y |
|
41 |
|
42 /* |
|
43 * we renamed all our internal functions, get the correct |
|
44 * definitions for them... |
|
45 */ |
|
46 #undef CK_PKCS11_FUNCTION_INFO |
|
47 #undef CK_NEED_ARG_LIST |
|
48 |
|
49 #define CK_EXTERN extern |
|
50 #define CK_PKCS11_FUNCTION_INFO(func) \ |
|
51 CK_RV __PASTE(NS,func) |
|
52 #define CK_NEED_ARG_LIST 1 |
|
53 |
|
54 #include "pkcs11f.h" |
|
55 |
|
56 typedef struct { |
|
57 PRUint8 client_version[2]; |
|
58 PRUint8 random[46]; |
|
59 } SSL3RSAPreMasterSecret; |
|
60 |
|
61 static void sftk_Null(void *data, PRBool freeit) |
|
62 { |
|
63 return; |
|
64 } |
|
65 |
|
66 #ifndef NSS_DISABLE_ECC |
|
67 #ifdef EC_DEBUG |
|
68 #define SEC_PRINT(str1, str2, num, sitem) \ |
|
69 printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \ |
|
70 str1, str2, num, sitem->len); \ |
|
71 for (i = 0; i < sitem->len; i++) { \ |
|
72 printf("%02x:", sitem->data[i]); \ |
|
73 } \ |
|
74 printf("\n") |
|
75 #else |
|
76 #define SEC_PRINT(a, b, c, d) |
|
77 #endif |
|
78 #endif /* NSS_DISABLE_ECC */ |
|
79 |
|
80 /* |
|
81 * free routines.... Free local type allocated data, and convert |
|
82 * other free routines to the destroy signature. |
|
83 */ |
|
84 static void |
|
85 sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit) |
|
86 { |
|
87 nsslowkey_DestroyPrivateKey(key); |
|
88 } |
|
89 |
|
90 static void |
|
91 sftk_Space(void *data, PRBool freeit) |
|
92 { |
|
93 PORT_Free(data); |
|
94 } |
|
95 |
|
96 /* |
|
97 * map all the SEC_ERROR_xxx error codes that may be returned by freebl |
|
98 * functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward |
|
99 * compatibility. |
|
100 */ |
|
101 static CK_RV |
|
102 sftk_MapCryptError(int error) |
|
103 { |
|
104 switch (error) { |
|
105 case SEC_ERROR_INVALID_ARGS: |
|
106 case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */ |
|
107 return CKR_ARGUMENTS_BAD; |
|
108 case SEC_ERROR_INPUT_LEN: |
|
109 return CKR_DATA_LEN_RANGE; |
|
110 case SEC_ERROR_OUTPUT_LEN: |
|
111 return CKR_BUFFER_TOO_SMALL; |
|
112 case SEC_ERROR_LIBRARY_FAILURE: |
|
113 return CKR_GENERAL_ERROR; |
|
114 case SEC_ERROR_NO_MEMORY: |
|
115 return CKR_HOST_MEMORY; |
|
116 case SEC_ERROR_BAD_SIGNATURE: |
|
117 return CKR_SIGNATURE_INVALID; |
|
118 case SEC_ERROR_INVALID_KEY: |
|
119 return CKR_KEY_SIZE_RANGE; |
|
120 case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */ |
|
121 return CKR_KEY_SIZE_RANGE; /* the closest error code */ |
|
122 case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM: |
|
123 return CKR_TEMPLATE_INCONSISTENT; |
|
124 /* EC functions set this error if NSS_DISABLE_ECC is defined */ |
|
125 case SEC_ERROR_UNSUPPORTED_KEYALG: |
|
126 return CKR_MECHANISM_INVALID; |
|
127 case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE: |
|
128 return CKR_DOMAIN_PARAMS_INVALID; |
|
129 /* key pair generation failed after max number of attempts */ |
|
130 case SEC_ERROR_NEED_RANDOM: |
|
131 return CKR_FUNCTION_FAILED; |
|
132 } |
|
133 return CKR_DEVICE_ERROR; |
|
134 } |
|
135 |
|
136 /* used by Decrypt and UnwrapKey (indirectly) */ |
|
137 static CK_RV |
|
138 sftk_MapDecryptError(int error) |
|
139 { |
|
140 switch (error) { |
|
141 case SEC_ERROR_BAD_DATA: |
|
142 return CKR_ENCRYPTED_DATA_INVALID; |
|
143 default: |
|
144 return sftk_MapCryptError(error); |
|
145 } |
|
146 } |
|
147 |
|
148 /* |
|
149 * return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for |
|
150 * backward compatibilty. |
|
151 */ |
|
152 static CK_RV |
|
153 sftk_MapVerifyError(int error) |
|
154 { |
|
155 CK_RV crv = sftk_MapCryptError(error); |
|
156 if (crv == CKR_DEVICE_ERROR) |
|
157 crv = CKR_SIGNATURE_INVALID; |
|
158 return crv; |
|
159 } |
|
160 |
|
161 |
|
162 /* |
|
163 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by |
|
164 * Deprecating a full des key to 40 bit key strenth. |
|
165 */ |
|
166 static CK_RV |
|
167 sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey) |
|
168 { |
|
169 unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae }; |
|
170 unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 }; |
|
171 unsigned char enc_src[8]; |
|
172 unsigned char enc_dest[8]; |
|
173 unsigned int leng,i; |
|
174 DESContext *descx; |
|
175 SECStatus rv; |
|
176 |
|
177 |
|
178 /* zero the parity bits */ |
|
179 for (i=0; i < 8; i++) { |
|
180 enc_src[i] = cdmfkey[i] & 0xfe; |
|
181 } |
|
182 |
|
183 /* encrypt with key 1 */ |
|
184 descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE); |
|
185 if (descx == NULL) return CKR_HOST_MEMORY; |
|
186 rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8); |
|
187 DES_DestroyContext(descx,PR_TRUE); |
|
188 if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError()); |
|
189 |
|
190 /* xor source with des, zero the parity bits and deprecate the key*/ |
|
191 for (i=0; i < 8; i++) { |
|
192 if (i & 1) { |
|
193 enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe; |
|
194 } else { |
|
195 enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e; |
|
196 } |
|
197 } |
|
198 |
|
199 /* encrypt with key 2 */ |
|
200 descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE); |
|
201 if (descx == NULL) return CKR_HOST_MEMORY; |
|
202 rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8); |
|
203 DES_DestroyContext(descx,PR_TRUE); |
|
204 if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError()); |
|
205 |
|
206 /* set the corret parity on our new des key */ |
|
207 sftk_FormatDESKey(deskey, 8); |
|
208 return CKR_OK; |
|
209 } |
|
210 |
|
211 |
|
212 /* NSC_DestroyObject destroys an object. */ |
|
213 CK_RV |
|
214 NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) |
|
215 { |
|
216 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
|
217 SFTKSession *session; |
|
218 SFTKObject *object; |
|
219 SFTKFreeStatus status; |
|
220 |
|
221 CHECK_FORK(); |
|
222 |
|
223 if (slot == NULL) { |
|
224 return CKR_SESSION_HANDLE_INVALID; |
|
225 } |
|
226 /* |
|
227 * This whole block just makes sure we really can destroy the |
|
228 * requested object. |
|
229 */ |
|
230 session = sftk_SessionFromHandle(hSession); |
|
231 if (session == NULL) { |
|
232 return CKR_SESSION_HANDLE_INVALID; |
|
233 } |
|
234 |
|
235 object = sftk_ObjectFromHandle(hObject,session); |
|
236 if (object == NULL) { |
|
237 sftk_FreeSession(session); |
|
238 return CKR_OBJECT_HANDLE_INVALID; |
|
239 } |
|
240 |
|
241 /* don't destroy a private object if we aren't logged in */ |
|
242 if ((!slot->isLoggedIn) && (slot->needLogin) && |
|
243 (sftk_isTrue(object,CKA_PRIVATE))) { |
|
244 sftk_FreeSession(session); |
|
245 sftk_FreeObject(object); |
|
246 return CKR_USER_NOT_LOGGED_IN; |
|
247 } |
|
248 |
|
249 /* don't destroy a token object if we aren't in a rw session */ |
|
250 |
|
251 if (((session->info.flags & CKF_RW_SESSION) == 0) && |
|
252 (sftk_isTrue(object,CKA_TOKEN))) { |
|
253 sftk_FreeSession(session); |
|
254 sftk_FreeObject(object); |
|
255 return CKR_SESSION_READ_ONLY; |
|
256 } |
|
257 |
|
258 sftk_DeleteObject(session,object); |
|
259 |
|
260 sftk_FreeSession(session); |
|
261 |
|
262 /* |
|
263 * get some indication if the object is destroyed. Note: this is not |
|
264 * 100%. Someone may have an object reference outstanding (though that |
|
265 * should not be the case by here. Also note that the object is "half" |
|
266 * destroyed. Our internal representation is destroyed, but it may still |
|
267 * be in the data base. |
|
268 */ |
|
269 status = sftk_FreeObject(object); |
|
270 |
|
271 return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR; |
|
272 } |
|
273 |
|
274 |
|
275 /* |
|
276 ************** Crypto Functions: Utilities ************************ |
|
277 */ |
|
278 /* |
|
279 * Utility function for converting PSS/OAEP parameter types into |
|
280 * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447. |
|
281 */ |
|
282 static HASH_HashType |
|
283 GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech) |
|
284 { |
|
285 switch (mech) { |
|
286 case CKM_SHA_1: |
|
287 case CKG_MGF1_SHA1: |
|
288 return HASH_AlgSHA1; |
|
289 case CKM_SHA224: |
|
290 case CKG_MGF1_SHA224: |
|
291 return HASH_AlgSHA224; |
|
292 case CKM_SHA256: |
|
293 case CKG_MGF1_SHA256: |
|
294 return HASH_AlgSHA256; |
|
295 case CKM_SHA384: |
|
296 case CKG_MGF1_SHA384: |
|
297 return HASH_AlgSHA384; |
|
298 case CKM_SHA512: |
|
299 case CKG_MGF1_SHA512: |
|
300 return HASH_AlgSHA512; |
|
301 default: |
|
302 return HASH_AlgNULL; |
|
303 } |
|
304 } |
|
305 |
|
306 /* |
|
307 * Returns true if "params" contains a valid set of PSS parameters |
|
308 */ |
|
309 static PRBool |
|
310 sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params) |
|
311 { |
|
312 if (!params) { |
|
313 return PR_FALSE; |
|
314 } |
|
315 if (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL || |
|
316 GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) { |
|
317 return PR_FALSE; |
|
318 } |
|
319 return PR_TRUE; |
|
320 } |
|
321 |
|
322 /* |
|
323 * Returns true if "params" contains a valid set of OAEP parameters |
|
324 */ |
|
325 static PRBool |
|
326 sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params) |
|
327 { |
|
328 if (!params) { |
|
329 return PR_FALSE; |
|
330 } |
|
331 /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which |
|
332 * state: |
|
333 * If the parameter is empty, pSourceData must be NULL and |
|
334 * ulSourceDataLen must be zero. |
|
335 */ |
|
336 if (params->source != CKZ_DATA_SPECIFIED || |
|
337 (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) || |
|
338 (GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) || |
|
339 (params->ulSourceDataLen == 0 && params->pSourceData != NULL) || |
|
340 (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) { |
|
341 return PR_FALSE; |
|
342 } |
|
343 return PR_TRUE; |
|
344 } |
|
345 |
|
346 /* |
|
347 * return a context based on the SFTKContext type. |
|
348 */ |
|
349 SFTKSessionContext * |
|
350 sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type) |
|
351 { |
|
352 switch (type) { |
|
353 case SFTK_ENCRYPT: |
|
354 case SFTK_DECRYPT: |
|
355 return session->enc_context; |
|
356 case SFTK_HASH: |
|
357 return session->hash_context; |
|
358 case SFTK_SIGN: |
|
359 case SFTK_SIGN_RECOVER: |
|
360 case SFTK_VERIFY: |
|
361 case SFTK_VERIFY_RECOVER: |
|
362 return session->hash_context; |
|
363 } |
|
364 return NULL; |
|
365 } |
|
366 |
|
367 /* |
|
368 * change a context based on the SFTKContext type. |
|
369 */ |
|
370 void |
|
371 sftk_SetContextByType(SFTKSession *session, SFTKContextType type, |
|
372 SFTKSessionContext *context) |
|
373 { |
|
374 switch (type) { |
|
375 case SFTK_ENCRYPT: |
|
376 case SFTK_DECRYPT: |
|
377 session->enc_context = context; |
|
378 break; |
|
379 case SFTK_HASH: |
|
380 session->hash_context = context; |
|
381 break; |
|
382 case SFTK_SIGN: |
|
383 case SFTK_SIGN_RECOVER: |
|
384 case SFTK_VERIFY: |
|
385 case SFTK_VERIFY_RECOVER: |
|
386 session->hash_context = context; |
|
387 break; |
|
388 } |
|
389 return; |
|
390 } |
|
391 |
|
392 /* |
|
393 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal, |
|
394 * and C_XXX function. The function takes a session handle, the context type, |
|
395 * and wether or not the session needs to be multipart. It returns the context, |
|
396 * and optionally returns the session pointer (if sessionPtr != NULL) if session |
|
397 * pointer is returned, the caller is responsible for freeing it. |
|
398 */ |
|
399 static CK_RV |
|
400 sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext **contextPtr, |
|
401 SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr) |
|
402 { |
|
403 SFTKSession *session; |
|
404 SFTKSessionContext *context; |
|
405 |
|
406 session = sftk_SessionFromHandle(handle); |
|
407 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; |
|
408 context = sftk_ReturnContextByType(session,type); |
|
409 /* make sure the context is valid */ |
|
410 if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){ |
|
411 sftk_FreeSession(session); |
|
412 return CKR_OPERATION_NOT_INITIALIZED; |
|
413 } |
|
414 *contextPtr = context; |
|
415 if (sessionPtr != NULL) { |
|
416 *sessionPtr = session; |
|
417 } else { |
|
418 sftk_FreeSession(session); |
|
419 } |
|
420 return CKR_OK; |
|
421 } |
|
422 |
|
423 /** Terminate operation (in the PKCS#11 spec sense). |
|
424 * Intuitive name for FreeContext/SetNullContext pair. |
|
425 */ |
|
426 static void |
|
427 sftk_TerminateOp( SFTKSession *session, SFTKContextType ctype, |
|
428 SFTKSessionContext *context ) |
|
429 { |
|
430 sftk_FreeContext( context ); |
|
431 sftk_SetContextByType( session, ctype, NULL ); |
|
432 } |
|
433 |
|
434 /* |
|
435 ************** Crypto Functions: Encrypt ************************ |
|
436 */ |
|
437 |
|
438 /* |
|
439 * All the NSC_InitXXX functions have a set of common checks and processing they |
|
440 * all need to do at the beginning. This is done here. |
|
441 */ |
|
442 static CK_RV |
|
443 sftk_InitGeneric(SFTKSession *session,SFTKSessionContext **contextPtr, |
|
444 SFTKContextType ctype,SFTKObject **keyPtr, |
|
445 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, |
|
446 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation) |
|
447 { |
|
448 SFTKObject *key = NULL; |
|
449 SFTKAttribute *att; |
|
450 SFTKSessionContext *context; |
|
451 |
|
452 /* We can only init if there is not current context active */ |
|
453 if (sftk_ReturnContextByType(session,ctype) != NULL) { |
|
454 return CKR_OPERATION_ACTIVE; |
|
455 } |
|
456 |
|
457 /* find the key */ |
|
458 if (keyPtr) { |
|
459 key = sftk_ObjectFromHandle(hKey,session); |
|
460 if (key == NULL) { |
|
461 return CKR_KEY_HANDLE_INVALID; |
|
462 } |
|
463 |
|
464 /* make sure it's a valid key for this operation */ |
|
465 if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType)) |
|
466 || !sftk_isTrue(key,operation)) { |
|
467 sftk_FreeObject(key); |
|
468 return CKR_KEY_TYPE_INCONSISTENT; |
|
469 } |
|
470 /* get the key type */ |
|
471 att = sftk_FindAttribute(key,CKA_KEY_TYPE); |
|
472 if (att == NULL) { |
|
473 sftk_FreeObject(key); |
|
474 return CKR_KEY_TYPE_INCONSISTENT; |
|
475 } |
|
476 PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE)); |
|
477 if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) { |
|
478 sftk_FreeAttribute(att); |
|
479 sftk_FreeObject(key); |
|
480 return CKR_ATTRIBUTE_VALUE_INVALID; |
|
481 } |
|
482 PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE)); |
|
483 sftk_FreeAttribute(att); |
|
484 *keyPtr = key; |
|
485 } |
|
486 |
|
487 /* allocate the context structure */ |
|
488 context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext)); |
|
489 if (context == NULL) { |
|
490 if (key) sftk_FreeObject(key); |
|
491 return CKR_HOST_MEMORY; |
|
492 } |
|
493 context->type = ctype; |
|
494 context->multi = PR_TRUE; |
|
495 context->rsa = PR_FALSE; |
|
496 context->cipherInfo = NULL; |
|
497 context->hashInfo = NULL; |
|
498 context->doPad = PR_FALSE; |
|
499 context->padDataLength = 0; |
|
500 context->key = key; |
|
501 context->blockSize = 0; |
|
502 context->maxLen = 0; |
|
503 |
|
504 *contextPtr = context; |
|
505 return CKR_OK; |
|
506 } |
|
507 |
|
508 static int |
|
509 sftk_aes_mode(CK_MECHANISM_TYPE mechanism) |
|
510 { |
|
511 switch (mechanism) { |
|
512 case CKM_AES_CBC_PAD: |
|
513 case CKM_AES_CBC: |
|
514 return NSS_AES_CBC; |
|
515 case CKM_AES_ECB: |
|
516 return NSS_AES; |
|
517 case CKM_AES_CTS: |
|
518 return NSS_AES_CTS; |
|
519 case CKM_AES_CTR: |
|
520 return NSS_AES_CTR; |
|
521 case CKM_AES_GCM: |
|
522 return NSS_AES_GCM; |
|
523 } |
|
524 return -1; |
|
525 } |
|
526 |
|
527 static SECStatus |
|
528 sftk_RSAEncryptRaw(NSSLOWKEYPublicKey *key, unsigned char *output, |
|
529 unsigned int *outputLen, unsigned int maxLen, |
|
530 const unsigned char *input, unsigned int inputLen) |
|
531 { |
|
532 SECStatus rv = SECFailure; |
|
533 |
|
534 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
535 if (key->keyType != NSSLOWKEYRSAKey) { |
|
536 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
537 return SECFailure; |
|
538 } |
|
539 |
|
540 rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input, |
|
541 inputLen); |
|
542 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
543 sftk_fatalError = PR_TRUE; |
|
544 } |
|
545 |
|
546 return rv; |
|
547 } |
|
548 |
|
549 static SECStatus |
|
550 sftk_RSADecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, |
|
551 unsigned int *outputLen, unsigned int maxLen, |
|
552 const unsigned char *input, unsigned int inputLen) |
|
553 { |
|
554 SECStatus rv = SECFailure; |
|
555 |
|
556 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
557 if (key->keyType != NSSLOWKEYRSAKey) { |
|
558 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
559 return SECFailure; |
|
560 } |
|
561 |
|
562 rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input, |
|
563 inputLen); |
|
564 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
565 sftk_fatalError = PR_TRUE; |
|
566 } |
|
567 |
|
568 return rv; |
|
569 } |
|
570 |
|
571 static SECStatus |
|
572 sftk_RSAEncrypt(NSSLOWKEYPublicKey *key, unsigned char *output, |
|
573 unsigned int *outputLen, unsigned int maxLen, |
|
574 const unsigned char *input, unsigned int inputLen) |
|
575 { |
|
576 SECStatus rv = SECFailure; |
|
577 |
|
578 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
579 if (key->keyType != NSSLOWKEYRSAKey) { |
|
580 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
581 return SECFailure; |
|
582 } |
|
583 |
|
584 rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
|
585 inputLen); |
|
586 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
587 sftk_fatalError = PR_TRUE; |
|
588 } |
|
589 |
|
590 return rv; |
|
591 } |
|
592 |
|
593 static SECStatus |
|
594 sftk_RSADecrypt(NSSLOWKEYPrivateKey *key, unsigned char *output, |
|
595 unsigned int *outputLen, unsigned int maxLen, |
|
596 const unsigned char *input, unsigned int inputLen) |
|
597 { |
|
598 SECStatus rv = SECFailure; |
|
599 |
|
600 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
601 if (key->keyType != NSSLOWKEYRSAKey) { |
|
602 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
603 return SECFailure; |
|
604 } |
|
605 |
|
606 rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
|
607 inputLen); |
|
608 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
609 sftk_fatalError = PR_TRUE; |
|
610 } |
|
611 |
|
612 return rv; |
|
613 } |
|
614 |
|
615 static SECStatus |
|
616 sftk_RSAEncryptOAEP(SFTKOAEPEncryptInfo *info, unsigned char *output, |
|
617 unsigned int *outputLen, unsigned int maxLen, |
|
618 const unsigned char *input, unsigned int inputLen) |
|
619 { |
|
620 HASH_HashType hashAlg; |
|
621 HASH_HashType maskHashAlg; |
|
622 |
|
623 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
|
624 if (info->key->keyType != NSSLOWKEYRSAKey) { |
|
625 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
626 return SECFailure; |
|
627 } |
|
628 |
|
629 hashAlg = GetHashTypeFromMechanism(info->params->hashAlg); |
|
630 maskHashAlg = GetHashTypeFromMechanism(info->params->mgf); |
|
631 |
|
632 return RSA_EncryptOAEP(&info->key->u.rsa, hashAlg, maskHashAlg, |
|
633 (const unsigned char*)info->params->pSourceData, |
|
634 info->params->ulSourceDataLen, NULL, 0, |
|
635 output, outputLen, maxLen, input, inputLen); |
|
636 } |
|
637 |
|
638 static SECStatus |
|
639 sftk_RSADecryptOAEP(SFTKOAEPDecryptInfo *info, unsigned char *output, |
|
640 unsigned int *outputLen, unsigned int maxLen, |
|
641 const unsigned char *input, unsigned int inputLen) |
|
642 { |
|
643 SECStatus rv = SECFailure; |
|
644 HASH_HashType hashAlg; |
|
645 HASH_HashType maskHashAlg; |
|
646 |
|
647 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
|
648 if (info->key->keyType != NSSLOWKEYRSAKey) { |
|
649 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
650 return SECFailure; |
|
651 } |
|
652 |
|
653 hashAlg = GetHashTypeFromMechanism(info->params->hashAlg); |
|
654 maskHashAlg = GetHashTypeFromMechanism(info->params->mgf); |
|
655 |
|
656 rv = RSA_DecryptOAEP(&info->key->u.rsa, hashAlg, maskHashAlg, |
|
657 (const unsigned char*)info->params->pSourceData, |
|
658 info->params->ulSourceDataLen, |
|
659 output, outputLen, maxLen, input, inputLen); |
|
660 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
661 sftk_fatalError = PR_TRUE; |
|
662 } |
|
663 return rv; |
|
664 } |
|
665 |
|
666 /** NSC_CryptInit initializes an encryption/Decryption operation. |
|
667 * |
|
668 * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. |
|
669 * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block |
|
670 * ciphers MAC'ing. |
|
671 */ |
|
672 static CK_RV |
|
673 sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
|
674 CK_OBJECT_HANDLE hKey, |
|
675 CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage, |
|
676 SFTKContextType contextType, PRBool isEncrypt) |
|
677 { |
|
678 SFTKSession *session; |
|
679 SFTKObject *key; |
|
680 SFTKSessionContext *context; |
|
681 SFTKAttribute *att; |
|
682 CK_RC2_CBC_PARAMS *rc2_param; |
|
683 #if NSS_SOFTOKEN_DOES_RC5 |
|
684 CK_RC5_CBC_PARAMS *rc5_param; |
|
685 SECItem rc5Key; |
|
686 #endif |
|
687 CK_KEY_TYPE key_type; |
|
688 CK_RV crv = CKR_OK; |
|
689 unsigned effectiveKeyLength; |
|
690 unsigned char newdeskey[24]; |
|
691 PRBool useNewKey=PR_FALSE; |
|
692 int t; |
|
693 |
|
694 crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage ); |
|
695 if (crv != CKR_OK) |
|
696 return crv; |
|
697 |
|
698 session = sftk_SessionFromHandle(hSession); |
|
699 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; |
|
700 |
|
701 crv = sftk_InitGeneric(session,&context,contextType,&key,hKey,&key_type, |
|
702 isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, keyUsage); |
|
703 |
|
704 if (crv != CKR_OK) { |
|
705 sftk_FreeSession(session); |
|
706 return crv; |
|
707 } |
|
708 |
|
709 context->doPad = PR_FALSE; |
|
710 switch(pMechanism->mechanism) { |
|
711 case CKM_RSA_PKCS: |
|
712 case CKM_RSA_X_509: |
|
713 if (key_type != CKK_RSA) { |
|
714 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
715 break; |
|
716 } |
|
717 context->multi = PR_FALSE; |
|
718 context->rsa = PR_TRUE; |
|
719 if (isEncrypt) { |
|
720 NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); |
|
721 if (pubKey == NULL) { |
|
722 crv = CKR_KEY_HANDLE_INVALID; |
|
723 break; |
|
724 } |
|
725 context->maxLen = nsslowkey_PublicModulusLen(pubKey); |
|
726 context->cipherInfo = (void *)pubKey; |
|
727 context->update = (SFTKCipher) |
|
728 (pMechanism->mechanism == CKM_RSA_X_509 |
|
729 ? sftk_RSAEncryptRaw : sftk_RSAEncrypt); |
|
730 } else { |
|
731 NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv); |
|
732 if (privKey == NULL) { |
|
733 crv = CKR_KEY_HANDLE_INVALID; |
|
734 break; |
|
735 } |
|
736 context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
|
737 context->cipherInfo = (void *)privKey; |
|
738 context->update = (SFTKCipher) |
|
739 (pMechanism->mechanism == CKM_RSA_X_509 |
|
740 ? sftk_RSADecryptRaw : sftk_RSADecrypt); |
|
741 } |
|
742 context->destroy = sftk_Null; |
|
743 break; |
|
744 case CKM_RSA_PKCS_OAEP: |
|
745 if (key_type != CKK_RSA) { |
|
746 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
747 break; |
|
748 } |
|
749 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) || |
|
750 !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter)) { |
|
751 crv = CKR_MECHANISM_PARAM_INVALID; |
|
752 break; |
|
753 } |
|
754 context->multi = PR_FALSE; |
|
755 context->rsa = PR_TRUE; |
|
756 if (isEncrypt) { |
|
757 SFTKOAEPEncryptInfo *info = PORT_New(SFTKOAEPEncryptInfo); |
|
758 if (info == NULL) { |
|
759 crv = CKR_HOST_MEMORY; |
|
760 break; |
|
761 } |
|
762 info->params = pMechanism->pParameter; |
|
763 info->key = sftk_GetPubKey(key, CKK_RSA, &crv); |
|
764 if (info->key == NULL) { |
|
765 PORT_Free(info); |
|
766 crv = CKR_KEY_HANDLE_INVALID; |
|
767 break; |
|
768 } |
|
769 context->update = (SFTKCipher) sftk_RSAEncryptOAEP; |
|
770 context->maxLen = nsslowkey_PublicModulusLen(info->key); |
|
771 context->cipherInfo = info; |
|
772 } else { |
|
773 SFTKOAEPDecryptInfo *info = PORT_New(SFTKOAEPDecryptInfo); |
|
774 if (info == NULL) { |
|
775 crv = CKR_HOST_MEMORY; |
|
776 break; |
|
777 } |
|
778 info->params = pMechanism->pParameter; |
|
779 info->key = sftk_GetPrivKey(key, CKK_RSA, &crv); |
|
780 if (info->key == NULL) { |
|
781 PORT_Free(info); |
|
782 crv = CKR_KEY_HANDLE_INVALID; |
|
783 break; |
|
784 } |
|
785 context->update = (SFTKCipher) sftk_RSADecryptOAEP; |
|
786 context->maxLen = nsslowkey_PrivateModulusLen(info->key); |
|
787 context->cipherInfo = info; |
|
788 } |
|
789 context->destroy = (SFTKDestroy) sftk_Space; |
|
790 break; |
|
791 case CKM_RC2_CBC_PAD: |
|
792 context->doPad = PR_TRUE; |
|
793 /* fall thru */ |
|
794 case CKM_RC2_ECB: |
|
795 case CKM_RC2_CBC: |
|
796 context->blockSize = 8; |
|
797 if (key_type != CKK_RC2) { |
|
798 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
799 break; |
|
800 } |
|
801 att = sftk_FindAttribute(key,CKA_VALUE); |
|
802 if (att == NULL) { |
|
803 crv = CKR_KEY_HANDLE_INVALID; |
|
804 break; |
|
805 } |
|
806 rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; |
|
807 effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8; |
|
808 context->cipherInfo = |
|
809 RC2_CreateContext((unsigned char*)att->attrib.pValue, |
|
810 att->attrib.ulValueLen, rc2_param->iv, |
|
811 pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : |
|
812 NSS_RC2_CBC,effectiveKeyLength); |
|
813 sftk_FreeAttribute(att); |
|
814 if (context->cipherInfo == NULL) { |
|
815 crv = CKR_HOST_MEMORY; |
|
816 break; |
|
817 } |
|
818 context->update = (SFTKCipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt); |
|
819 context->destroy = (SFTKDestroy) RC2_DestroyContext; |
|
820 break; |
|
821 #if NSS_SOFTOKEN_DOES_RC5 |
|
822 case CKM_RC5_CBC_PAD: |
|
823 context->doPad = PR_TRUE; |
|
824 /* fall thru */ |
|
825 case CKM_RC5_ECB: |
|
826 case CKM_RC5_CBC: |
|
827 if (key_type != CKK_RC5) { |
|
828 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
829 break; |
|
830 } |
|
831 att = sftk_FindAttribute(key,CKA_VALUE); |
|
832 if (att == NULL) { |
|
833 crv = CKR_KEY_HANDLE_INVALID; |
|
834 break; |
|
835 } |
|
836 rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; |
|
837 context->blockSize = rc5_param->ulWordsize*2; |
|
838 rc5Key.data = (unsigned char*)att->attrib.pValue; |
|
839 rc5Key.len = att->attrib.ulValueLen; |
|
840 context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds, |
|
841 rc5_param->ulWordsize,rc5_param->pIv, |
|
842 pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); |
|
843 sftk_FreeAttribute(att); |
|
844 if (context->cipherInfo == NULL) { |
|
845 crv = CKR_HOST_MEMORY; |
|
846 break; |
|
847 } |
|
848 context->update = (SFTKCipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt); |
|
849 context->destroy = (SFTKDestroy) RC5_DestroyContext; |
|
850 break; |
|
851 #endif |
|
852 case CKM_RC4: |
|
853 if (key_type != CKK_RC4) { |
|
854 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
855 break; |
|
856 } |
|
857 att = sftk_FindAttribute(key,CKA_VALUE); |
|
858 if (att == NULL) { |
|
859 crv = CKR_KEY_HANDLE_INVALID; |
|
860 break; |
|
861 } |
|
862 context->cipherInfo = |
|
863 RC4_CreateContext((unsigned char*)att->attrib.pValue, |
|
864 att->attrib.ulValueLen); |
|
865 sftk_FreeAttribute(att); |
|
866 if (context->cipherInfo == NULL) { |
|
867 crv = CKR_HOST_MEMORY; /* WRONG !!! */ |
|
868 break; |
|
869 } |
|
870 context->update = (SFTKCipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt); |
|
871 context->destroy = (SFTKDestroy) RC4_DestroyContext; |
|
872 break; |
|
873 case CKM_CDMF_CBC_PAD: |
|
874 context->doPad = PR_TRUE; |
|
875 /* fall thru */ |
|
876 case CKM_CDMF_ECB: |
|
877 case CKM_CDMF_CBC: |
|
878 if (key_type != CKK_CDMF) { |
|
879 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
880 break; |
|
881 } |
|
882 t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; |
|
883 if (crv != CKR_OK) break; |
|
884 goto finish_des; |
|
885 case CKM_DES_ECB: |
|
886 if (key_type != CKK_DES) { |
|
887 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
888 break; |
|
889 } |
|
890 t = NSS_DES; |
|
891 goto finish_des; |
|
892 case CKM_DES_CBC_PAD: |
|
893 context->doPad = PR_TRUE; |
|
894 /* fall thru */ |
|
895 case CKM_DES_CBC: |
|
896 if (key_type != CKK_DES) { |
|
897 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
898 break; |
|
899 } |
|
900 t = NSS_DES_CBC; |
|
901 goto finish_des; |
|
902 case CKM_DES3_ECB: |
|
903 if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
|
904 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
905 break; |
|
906 } |
|
907 t = NSS_DES_EDE3; |
|
908 goto finish_des; |
|
909 case CKM_DES3_CBC_PAD: |
|
910 context->doPad = PR_TRUE; |
|
911 /* fall thru */ |
|
912 case CKM_DES3_CBC: |
|
913 if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
|
914 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
915 break; |
|
916 } |
|
917 t = NSS_DES_EDE3_CBC; |
|
918 finish_des: |
|
919 context->blockSize = 8; |
|
920 att = sftk_FindAttribute(key,CKA_VALUE); |
|
921 if (att == NULL) { |
|
922 crv = CKR_KEY_HANDLE_INVALID; |
|
923 break; |
|
924 } |
|
925 if (key_type == CKK_DES2 && |
|
926 (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) { |
|
927 /* extend DES2 key to DES3 key. */ |
|
928 memcpy(newdeskey, att->attrib.pValue, 16); |
|
929 memcpy(newdeskey + 16, newdeskey, 8); |
|
930 useNewKey=PR_TRUE; |
|
931 } else if (key_type == CKK_CDMF) { |
|
932 crv = sftk_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey); |
|
933 if (crv != CKR_OK) { |
|
934 sftk_FreeAttribute(att); |
|
935 break; |
|
936 } |
|
937 useNewKey=PR_TRUE; |
|
938 } |
|
939 context->cipherInfo = DES_CreateContext( |
|
940 useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue, |
|
941 (unsigned char*)pMechanism->pParameter,t, isEncrypt); |
|
942 if (useNewKey) |
|
943 memset(newdeskey, 0, sizeof newdeskey); |
|
944 sftk_FreeAttribute(att); |
|
945 if (context->cipherInfo == NULL) { |
|
946 crv = CKR_HOST_MEMORY; |
|
947 break; |
|
948 } |
|
949 context->update = (SFTKCipher) (isEncrypt ? DES_Encrypt : DES_Decrypt); |
|
950 context->destroy = (SFTKDestroy) DES_DestroyContext; |
|
951 break; |
|
952 case CKM_SEED_CBC_PAD: |
|
953 context->doPad = PR_TRUE; |
|
954 /* fall thru */ |
|
955 case CKM_SEED_CBC: |
|
956 if (!pMechanism->pParameter || |
|
957 pMechanism->ulParameterLen != 16) { |
|
958 crv = CKR_MECHANISM_PARAM_INVALID; |
|
959 break; |
|
960 } |
|
961 /* fall thru */ |
|
962 case CKM_SEED_ECB: |
|
963 context->blockSize = 16; |
|
964 if (key_type != CKK_SEED) { |
|
965 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
966 break; |
|
967 } |
|
968 att = sftk_FindAttribute(key,CKA_VALUE); |
|
969 if (att == NULL) { |
|
970 crv = CKR_KEY_HANDLE_INVALID; |
|
971 break; |
|
972 } |
|
973 context->cipherInfo = SEED_CreateContext( |
|
974 (unsigned char*)att->attrib.pValue, |
|
975 (unsigned char*)pMechanism->pParameter, |
|
976 pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC, |
|
977 isEncrypt); |
|
978 sftk_FreeAttribute(att); |
|
979 if (context->cipherInfo == NULL) { |
|
980 crv = CKR_HOST_MEMORY; |
|
981 break; |
|
982 } |
|
983 context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt); |
|
984 context->destroy = (SFTKDestroy) SEED_DestroyContext; |
|
985 break; |
|
986 |
|
987 case CKM_CAMELLIA_CBC_PAD: |
|
988 context->doPad = PR_TRUE; |
|
989 /* fall thru */ |
|
990 case CKM_CAMELLIA_CBC: |
|
991 if (!pMechanism->pParameter || |
|
992 pMechanism->ulParameterLen != 16) { |
|
993 crv = CKR_MECHANISM_PARAM_INVALID; |
|
994 break; |
|
995 } |
|
996 /* fall thru */ |
|
997 case CKM_CAMELLIA_ECB: |
|
998 context->blockSize = 16; |
|
999 if (key_type != CKK_CAMELLIA) { |
|
1000 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
1001 break; |
|
1002 } |
|
1003 att = sftk_FindAttribute(key,CKA_VALUE); |
|
1004 if (att == NULL) { |
|
1005 crv = CKR_KEY_HANDLE_INVALID; |
|
1006 break; |
|
1007 } |
|
1008 context->cipherInfo = Camellia_CreateContext( |
|
1009 (unsigned char*)att->attrib.pValue, |
|
1010 (unsigned char*)pMechanism->pParameter, |
|
1011 pMechanism->mechanism == |
|
1012 CKM_CAMELLIA_ECB ? NSS_CAMELLIA : NSS_CAMELLIA_CBC, |
|
1013 isEncrypt, att->attrib.ulValueLen); |
|
1014 sftk_FreeAttribute(att); |
|
1015 if (context->cipherInfo == NULL) { |
|
1016 crv = CKR_HOST_MEMORY; |
|
1017 break; |
|
1018 } |
|
1019 context->update = (SFTKCipher) (isEncrypt ? |
|
1020 Camellia_Encrypt : Camellia_Decrypt); |
|
1021 context->destroy = (SFTKDestroy) Camellia_DestroyContext; |
|
1022 break; |
|
1023 |
|
1024 case CKM_AES_CBC_PAD: |
|
1025 context->doPad = PR_TRUE; |
|
1026 /* fall thru */ |
|
1027 case CKM_AES_ECB: |
|
1028 case CKM_AES_CBC: |
|
1029 context->blockSize = 16; |
|
1030 case CKM_AES_CTS: |
|
1031 case CKM_AES_CTR: |
|
1032 case CKM_AES_GCM: |
|
1033 if (pMechanism->mechanism == CKM_AES_GCM) { |
|
1034 context->multi = PR_FALSE; |
|
1035 } |
|
1036 if (key_type != CKK_AES) { |
|
1037 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
1038 break; |
|
1039 } |
|
1040 att = sftk_FindAttribute(key,CKA_VALUE); |
|
1041 if (att == NULL) { |
|
1042 crv = CKR_KEY_HANDLE_INVALID; |
|
1043 break; |
|
1044 } |
|
1045 context->cipherInfo = AES_CreateContext( |
|
1046 (unsigned char*)att->attrib.pValue, |
|
1047 (unsigned char*)pMechanism->pParameter, |
|
1048 sftk_aes_mode(pMechanism->mechanism), |
|
1049 isEncrypt, att->attrib.ulValueLen, 16); |
|
1050 sftk_FreeAttribute(att); |
|
1051 if (context->cipherInfo == NULL) { |
|
1052 crv = CKR_HOST_MEMORY; |
|
1053 break; |
|
1054 } |
|
1055 context->update = (SFTKCipher) (isEncrypt ? AES_Encrypt : AES_Decrypt); |
|
1056 context->destroy = (SFTKDestroy) AES_DestroyContext; |
|
1057 break; |
|
1058 |
|
1059 case CKM_NETSCAPE_AES_KEY_WRAP_PAD: |
|
1060 context->doPad = PR_TRUE; |
|
1061 /* fall thru */ |
|
1062 case CKM_NETSCAPE_AES_KEY_WRAP: |
|
1063 context->multi = PR_FALSE; |
|
1064 context->blockSize = 8; |
|
1065 if (key_type != CKK_AES) { |
|
1066 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
1067 break; |
|
1068 } |
|
1069 att = sftk_FindAttribute(key,CKA_VALUE); |
|
1070 if (att == NULL) { |
|
1071 crv = CKR_KEY_HANDLE_INVALID; |
|
1072 break; |
|
1073 } |
|
1074 context->cipherInfo = AESKeyWrap_CreateContext( |
|
1075 (unsigned char*)att->attrib.pValue, |
|
1076 (unsigned char*)pMechanism->pParameter, |
|
1077 isEncrypt, att->attrib.ulValueLen); |
|
1078 sftk_FreeAttribute(att); |
|
1079 if (context->cipherInfo == NULL) { |
|
1080 crv = CKR_HOST_MEMORY; |
|
1081 break; |
|
1082 } |
|
1083 context->update = (SFTKCipher) (isEncrypt ? AESKeyWrap_Encrypt |
|
1084 : AESKeyWrap_Decrypt); |
|
1085 context->destroy = (SFTKDestroy) AESKeyWrap_DestroyContext; |
|
1086 break; |
|
1087 |
|
1088 default: |
|
1089 crv = CKR_MECHANISM_INVALID; |
|
1090 break; |
|
1091 } |
|
1092 |
|
1093 if (crv != CKR_OK) { |
|
1094 sftk_FreeContext(context); |
|
1095 sftk_FreeSession(session); |
|
1096 return crv; |
|
1097 } |
|
1098 sftk_SetContextByType(session, contextType, context); |
|
1099 sftk_FreeSession(session); |
|
1100 return CKR_OK; |
|
1101 } |
|
1102 |
|
1103 /* NSC_EncryptInit initializes an encryption operation. */ |
|
1104 CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession, |
|
1105 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
|
1106 { |
|
1107 CHECK_FORK(); |
|
1108 return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT, |
|
1109 SFTK_ENCRYPT, PR_TRUE); |
|
1110 } |
|
1111 |
|
1112 /* NSC_EncryptUpdate continues a multiple-part encryption operation. */ |
|
1113 CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, |
|
1114 CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
|
1115 CK_ULONG_PTR pulEncryptedPartLen) |
|
1116 { |
|
1117 SFTKSessionContext *context; |
|
1118 unsigned int outlen,i; |
|
1119 unsigned int padoutlen = 0; |
|
1120 unsigned int maxout = *pulEncryptedPartLen; |
|
1121 CK_RV crv; |
|
1122 SECStatus rv; |
|
1123 |
|
1124 CHECK_FORK(); |
|
1125 |
|
1126 /* make sure we're legal */ |
|
1127 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,NULL); |
|
1128 if (crv != CKR_OK) return crv; |
|
1129 |
|
1130 if (!pEncryptedPart) { |
|
1131 if (context->doPad) { |
|
1132 CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; |
|
1133 CK_ULONG blocksToSend = totalDataAvailable/context->blockSize; |
|
1134 |
|
1135 *pulEncryptedPartLen = blocksToSend * context->blockSize; |
|
1136 return CKR_OK; |
|
1137 } |
|
1138 *pulEncryptedPartLen = ulPartLen; |
|
1139 return CKR_OK; |
|
1140 } |
|
1141 |
|
1142 /* do padding */ |
|
1143 if (context->doPad) { |
|
1144 /* deal with previous buffered data */ |
|
1145 if (context->padDataLength != 0) { |
|
1146 /* fill in the padded to a full block size */ |
|
1147 for (i=context->padDataLength; |
|
1148 (ulPartLen != 0) && i < context->blockSize; i++) { |
|
1149 context->padBuf[i] = *pPart++; |
|
1150 ulPartLen--; |
|
1151 context->padDataLength++; |
|
1152 } |
|
1153 |
|
1154 /* not enough data to encrypt yet? then return */ |
|
1155 if (context->padDataLength != context->blockSize) { |
|
1156 *pulEncryptedPartLen = 0; |
|
1157 return CKR_OK; |
|
1158 } |
|
1159 /* encrypt the current padded data */ |
|
1160 rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
|
1161 &padoutlen, context->blockSize, context->padBuf, |
|
1162 context->blockSize); |
|
1163 if (rv != SECSuccess) { |
|
1164 return sftk_MapCryptError(PORT_GetError()); |
|
1165 } |
|
1166 pEncryptedPart += padoutlen; |
|
1167 maxout -= padoutlen; |
|
1168 } |
|
1169 /* save the residual */ |
|
1170 context->padDataLength = ulPartLen % context->blockSize; |
|
1171 if (context->padDataLength) { |
|
1172 PORT_Memcpy(context->padBuf, |
|
1173 &pPart[ulPartLen-context->padDataLength], |
|
1174 context->padDataLength); |
|
1175 ulPartLen -= context->padDataLength; |
|
1176 } |
|
1177 /* if we've exhausted our new buffer, we're done */ |
|
1178 if (ulPartLen == 0) { |
|
1179 *pulEncryptedPartLen = padoutlen; |
|
1180 return CKR_OK; |
|
1181 } |
|
1182 } |
|
1183 |
|
1184 |
|
1185 /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
|
1186 rv = (*context->update)(context->cipherInfo,pEncryptedPart, |
|
1187 &outlen, maxout, pPart, ulPartLen); |
|
1188 *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen); |
|
1189 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
|
1190 } |
|
1191 |
|
1192 |
|
1193 /* NSC_EncryptFinal finishes a multiple-part encryption operation. */ |
|
1194 CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession, |
|
1195 CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) |
|
1196 { |
|
1197 SFTKSession *session; |
|
1198 SFTKSessionContext *context; |
|
1199 unsigned int outlen,i; |
|
1200 unsigned int maxout = *pulLastEncryptedPartLen; |
|
1201 CK_RV crv; |
|
1202 SECStatus rv = SECSuccess; |
|
1203 PRBool contextFinished = PR_TRUE; |
|
1204 |
|
1205 CHECK_FORK(); |
|
1206 |
|
1207 /* make sure we're legal */ |
|
1208 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,&session); |
|
1209 if (crv != CKR_OK) return crv; |
|
1210 |
|
1211 *pulLastEncryptedPartLen = 0; |
|
1212 if (!pLastEncryptedPart) { |
|
1213 /* caller is checking the amount of remaining data */ |
|
1214 if (context->blockSize > 0 && context->doPad) { |
|
1215 *pulLastEncryptedPartLen = context->blockSize; |
|
1216 contextFinished = PR_FALSE; /* still have padding to go */ |
|
1217 } |
|
1218 goto finish; |
|
1219 } |
|
1220 |
|
1221 /* do padding */ |
|
1222 if (context->doPad) { |
|
1223 unsigned char padbyte = (unsigned char) |
|
1224 (context->blockSize - context->padDataLength); |
|
1225 /* fill out rest of pad buffer with pad magic*/ |
|
1226 for (i=context->padDataLength; i < context->blockSize; i++) { |
|
1227 context->padBuf[i] = padbyte; |
|
1228 } |
|
1229 rv = (*context->update)(context->cipherInfo,pLastEncryptedPart, |
|
1230 &outlen, maxout, context->padBuf, context->blockSize); |
|
1231 if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen; |
|
1232 } |
|
1233 |
|
1234 finish: |
|
1235 if (contextFinished) |
|
1236 sftk_TerminateOp( session, SFTK_ENCRYPT, context ); |
|
1237 sftk_FreeSession(session); |
|
1238 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
|
1239 } |
|
1240 |
|
1241 /* NSC_Encrypt encrypts single-part data. */ |
|
1242 CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
|
1243 CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, |
|
1244 CK_ULONG_PTR pulEncryptedDataLen) |
|
1245 { |
|
1246 SFTKSession *session; |
|
1247 SFTKSessionContext *context; |
|
1248 unsigned int outlen; |
|
1249 unsigned int maxoutlen = *pulEncryptedDataLen; |
|
1250 CK_RV crv; |
|
1251 CK_RV crv2; |
|
1252 SECStatus rv = SECSuccess; |
|
1253 SECItem pText; |
|
1254 |
|
1255 pText.type = siBuffer; |
|
1256 pText.data = pData; |
|
1257 pText.len = ulDataLen; |
|
1258 |
|
1259 CHECK_FORK(); |
|
1260 |
|
1261 /* make sure we're legal */ |
|
1262 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,&session); |
|
1263 if (crv != CKR_OK) return crv; |
|
1264 |
|
1265 if (!pEncryptedData) { |
|
1266 *pulEncryptedDataLen = context->rsa ? context->maxLen : |
|
1267 ulDataLen + 2 * context->blockSize; |
|
1268 goto finish; |
|
1269 } |
|
1270 |
|
1271 if (context->doPad) { |
|
1272 if (context->multi) { |
|
1273 CK_ULONG finalLen; |
|
1274 /* padding is fairly complicated, have the update and final |
|
1275 * code deal with it */ |
|
1276 sftk_FreeSession(session); |
|
1277 crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, |
|
1278 pulEncryptedDataLen); |
|
1279 if (crv != CKR_OK) |
|
1280 *pulEncryptedDataLen = 0; |
|
1281 maxoutlen -= *pulEncryptedDataLen; |
|
1282 pEncryptedData += *pulEncryptedDataLen; |
|
1283 finalLen = maxoutlen; |
|
1284 crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen); |
|
1285 if (crv2 == CKR_OK) |
|
1286 *pulEncryptedDataLen += finalLen; |
|
1287 return crv == CKR_OK ? crv2 : crv; |
|
1288 } |
|
1289 /* doPad without multi means that padding must be done on the first |
|
1290 ** and only update. There will be no final. |
|
1291 */ |
|
1292 PORT_Assert(context->blockSize > 1); |
|
1293 if (context->blockSize > 1) { |
|
1294 CK_ULONG remainder = ulDataLen % context->blockSize; |
|
1295 CK_ULONG padding = context->blockSize - remainder; |
|
1296 pText.len += padding; |
|
1297 pText.data = PORT_ZAlloc(pText.len); |
|
1298 if (pText.data) { |
|
1299 memcpy(pText.data, pData, ulDataLen); |
|
1300 memset(pText.data + ulDataLen, padding, padding); |
|
1301 } else { |
|
1302 crv = CKR_HOST_MEMORY; |
|
1303 goto fail; |
|
1304 } |
|
1305 } |
|
1306 } |
|
1307 |
|
1308 /* do it: NOTE: this assumes buf size is big enough. */ |
|
1309 rv = (*context->update)(context->cipherInfo, pEncryptedData, |
|
1310 &outlen, maxoutlen, pText.data, pText.len); |
|
1311 crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
|
1312 *pulEncryptedDataLen = (CK_ULONG) outlen; |
|
1313 if (pText.data != pData) |
|
1314 PORT_ZFree(pText.data, pText.len); |
|
1315 fail: |
|
1316 sftk_TerminateOp( session, SFTK_ENCRYPT, context ); |
|
1317 finish: |
|
1318 sftk_FreeSession(session); |
|
1319 |
|
1320 return crv; |
|
1321 } |
|
1322 |
|
1323 |
|
1324 /* |
|
1325 ************** Crypto Functions: Decrypt ************************ |
|
1326 */ |
|
1327 |
|
1328 /* NSC_DecryptInit initializes a decryption operation. */ |
|
1329 CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession, |
|
1330 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
|
1331 { |
|
1332 CHECK_FORK(); |
|
1333 return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT, |
|
1334 SFTK_DECRYPT, PR_FALSE); |
|
1335 } |
|
1336 |
|
1337 /* NSC_DecryptUpdate continues a multiple-part decryption operation. */ |
|
1338 CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, |
|
1339 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
|
1340 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
|
1341 { |
|
1342 SFTKSessionContext *context; |
|
1343 unsigned int padoutlen = 0; |
|
1344 unsigned int outlen; |
|
1345 unsigned int maxout = *pulPartLen; |
|
1346 CK_RV crv; |
|
1347 SECStatus rv; |
|
1348 |
|
1349 CHECK_FORK(); |
|
1350 |
|
1351 /* make sure we're legal */ |
|
1352 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,NULL); |
|
1353 if (crv != CKR_OK) return crv; |
|
1354 |
|
1355 /* this can only happen on an NSS programming error */ |
|
1356 PORT_Assert((context->padDataLength == 0) |
|
1357 || context->padDataLength == context->blockSize); |
|
1358 |
|
1359 |
|
1360 if (context->doPad) { |
|
1361 /* Check the data length for block ciphers. If we are padding, |
|
1362 * then we must be using a block cipher. In the non-padding case |
|
1363 * the error will be returned by the underlying decryption |
|
1364 * function when we do the actual decrypt. We need to do the |
|
1365 * check here to avoid returning a negative length to the caller |
|
1366 * or reading before the beginning of the pEncryptedPart buffer. |
|
1367 */ |
|
1368 if ((ulEncryptedPartLen == 0) || |
|
1369 (ulEncryptedPartLen % context->blockSize) != 0) { |
|
1370 return CKR_ENCRYPTED_DATA_LEN_RANGE; |
|
1371 } |
|
1372 } |
|
1373 |
|
1374 if (!pPart) { |
|
1375 if (context->doPad) { |
|
1376 *pulPartLen = |
|
1377 ulEncryptedPartLen + context->padDataLength - context->blockSize; |
|
1378 return CKR_OK; |
|
1379 } |
|
1380 /* for stream ciphers there is are no constraints on ulEncryptedPartLen. |
|
1381 * for block ciphers, it must be a multiple of blockSize. The error is |
|
1382 * detected when this function is called again do decrypt the output. |
|
1383 */ |
|
1384 *pulPartLen = ulEncryptedPartLen; |
|
1385 return CKR_OK; |
|
1386 } |
|
1387 |
|
1388 if (context->doPad) { |
|
1389 /* first decrypt our saved buffer */ |
|
1390 if (context->padDataLength != 0) { |
|
1391 rv = (*context->update)(context->cipherInfo, pPart, &padoutlen, |
|
1392 maxout, context->padBuf, context->blockSize); |
|
1393 if (rv != SECSuccess) return sftk_MapDecryptError(PORT_GetError()); |
|
1394 pPart += padoutlen; |
|
1395 maxout -= padoutlen; |
|
1396 } |
|
1397 /* now save the final block for the next decrypt or the final */ |
|
1398 PORT_Memcpy(context->padBuf,&pEncryptedPart[ulEncryptedPartLen - |
|
1399 context->blockSize], context->blockSize); |
|
1400 context->padDataLength = context->blockSize; |
|
1401 ulEncryptedPartLen -= context->padDataLength; |
|
1402 } |
|
1403 |
|
1404 /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
|
1405 rv = (*context->update)(context->cipherInfo,pPart, &outlen, |
|
1406 maxout, pEncryptedPart, ulEncryptedPartLen); |
|
1407 *pulPartLen = (CK_ULONG) (outlen + padoutlen); |
|
1408 return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); |
|
1409 } |
|
1410 |
|
1411 |
|
1412 /* NSC_DecryptFinal finishes a multiple-part decryption operation. */ |
|
1413 CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession, |
|
1414 CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) |
|
1415 { |
|
1416 SFTKSession *session; |
|
1417 SFTKSessionContext *context; |
|
1418 unsigned int outlen; |
|
1419 unsigned int maxout = *pulLastPartLen; |
|
1420 CK_RV crv; |
|
1421 SECStatus rv = SECSuccess; |
|
1422 |
|
1423 CHECK_FORK(); |
|
1424 |
|
1425 /* make sure we're legal */ |
|
1426 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,&session); |
|
1427 if (crv != CKR_OK) return crv; |
|
1428 |
|
1429 *pulLastPartLen = 0; |
|
1430 if (!pLastPart) { |
|
1431 /* caller is checking the amount of remaining data */ |
|
1432 if (context->padDataLength > 0) { |
|
1433 *pulLastPartLen = context->padDataLength; |
|
1434 } |
|
1435 goto finish; |
|
1436 } |
|
1437 |
|
1438 if (context->doPad) { |
|
1439 /* decrypt our saved buffer */ |
|
1440 if (context->padDataLength != 0) { |
|
1441 /* this assumes that pLastPart is big enough to hold the *whole* |
|
1442 * buffer!!! */ |
|
1443 rv = (*context->update)(context->cipherInfo, pLastPart, &outlen, |
|
1444 maxout, context->padBuf, context->blockSize); |
|
1445 if (rv != SECSuccess) { |
|
1446 crv = sftk_MapDecryptError(PORT_GetError()); |
|
1447 } else { |
|
1448 unsigned int padSize = |
|
1449 (unsigned int) pLastPart[context->blockSize-1]; |
|
1450 if ((padSize > context->blockSize) || (padSize == 0)) { |
|
1451 crv = CKR_ENCRYPTED_DATA_INVALID; |
|
1452 } else { |
|
1453 unsigned int i; |
|
1454 unsigned int badPadding = 0; /* used as a boolean */ |
|
1455 for (i = 0; i < padSize; i++) { |
|
1456 badPadding |= |
|
1457 (unsigned int) pLastPart[context->blockSize-1-i] ^ |
|
1458 padSize; |
|
1459 } |
|
1460 if (badPadding) { |
|
1461 crv = CKR_ENCRYPTED_DATA_INVALID; |
|
1462 } else { |
|
1463 *pulLastPartLen = outlen - padSize; |
|
1464 } |
|
1465 } |
|
1466 } |
|
1467 } |
|
1468 } |
|
1469 |
|
1470 sftk_TerminateOp( session, SFTK_DECRYPT, context ); |
|
1471 finish: |
|
1472 sftk_FreeSession(session); |
|
1473 return crv; |
|
1474 } |
|
1475 |
|
1476 /* NSC_Decrypt decrypts encrypted data in a single part. */ |
|
1477 CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession, |
|
1478 CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData, |
|
1479 CK_ULONG_PTR pulDataLen) |
|
1480 { |
|
1481 SFTKSession *session; |
|
1482 SFTKSessionContext *context; |
|
1483 unsigned int outlen; |
|
1484 unsigned int maxoutlen = *pulDataLen; |
|
1485 CK_RV crv; |
|
1486 CK_RV crv2; |
|
1487 SECStatus rv = SECSuccess; |
|
1488 |
|
1489 CHECK_FORK(); |
|
1490 |
|
1491 /* make sure we're legal */ |
|
1492 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_FALSE,&session); |
|
1493 if (crv != CKR_OK) return crv; |
|
1494 |
|
1495 if (!pData) { |
|
1496 *pulDataLen = ulEncryptedDataLen + context->blockSize; |
|
1497 goto finish; |
|
1498 } |
|
1499 |
|
1500 if (context->doPad && context->multi) { |
|
1501 CK_ULONG finalLen; |
|
1502 /* padding is fairly complicated, have the update and final |
|
1503 * code deal with it */ |
|
1504 sftk_FreeSession(session); |
|
1505 crv = NSC_DecryptUpdate(hSession,pEncryptedData,ulEncryptedDataLen, |
|
1506 pData, pulDataLen); |
|
1507 if (crv != CKR_OK) |
|
1508 *pulDataLen = 0; |
|
1509 maxoutlen -= *pulDataLen; |
|
1510 pData += *pulDataLen; |
|
1511 finalLen = maxoutlen; |
|
1512 crv2 = NSC_DecryptFinal(hSession, pData, &finalLen); |
|
1513 if (crv2 == CKR_OK) |
|
1514 *pulDataLen += finalLen; |
|
1515 return crv == CKR_OK ? crv2 : crv; |
|
1516 } |
|
1517 |
|
1518 rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
|
1519 pEncryptedData, ulEncryptedDataLen); |
|
1520 /* XXX need to do MUCH better error mapping than this. */ |
|
1521 crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); |
|
1522 if (rv == SECSuccess && context->doPad) { |
|
1523 unsigned int padding = pData[outlen - 1]; |
|
1524 if (padding > context->blockSize || !padding) { |
|
1525 crv = CKR_ENCRYPTED_DATA_INVALID; |
|
1526 } else { |
|
1527 unsigned int i; |
|
1528 unsigned int badPadding = 0; /* used as a boolean */ |
|
1529 for (i = 0; i < padding; i++) { |
|
1530 badPadding |= (unsigned int) pData[outlen - 1 - i] ^ padding; |
|
1531 } |
|
1532 if (badPadding) { |
|
1533 crv = CKR_ENCRYPTED_DATA_INVALID; |
|
1534 } else { |
|
1535 outlen -= padding; |
|
1536 } |
|
1537 } |
|
1538 } |
|
1539 *pulDataLen = (CK_ULONG) outlen; |
|
1540 sftk_TerminateOp( session, SFTK_DECRYPT, context ); |
|
1541 finish: |
|
1542 sftk_FreeSession(session); |
|
1543 return crv; |
|
1544 } |
|
1545 |
|
1546 |
|
1547 |
|
1548 /* |
|
1549 ************** Crypto Functions: Digest (HASH) ************************ |
|
1550 */ |
|
1551 |
|
1552 /* NSC_DigestInit initializes a message-digesting operation. */ |
|
1553 CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession, |
|
1554 CK_MECHANISM_PTR pMechanism) |
|
1555 { |
|
1556 SFTKSession *session; |
|
1557 SFTKSessionContext *context; |
|
1558 CK_RV crv = CKR_OK; |
|
1559 |
|
1560 CHECK_FORK(); |
|
1561 |
|
1562 session = sftk_SessionFromHandle(hSession); |
|
1563 if (session == NULL) |
|
1564 return CKR_SESSION_HANDLE_INVALID; |
|
1565 crv = sftk_InitGeneric(session,&context,SFTK_HASH,NULL,0,NULL, 0, 0); |
|
1566 if (crv != CKR_OK) { |
|
1567 sftk_FreeSession(session); |
|
1568 return crv; |
|
1569 } |
|
1570 |
|
1571 |
|
1572 #define INIT_MECH(mech,mmm) \ |
|
1573 case mech: { \ |
|
1574 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \ |
|
1575 context->cipherInfo = (void *)mmm ## _ctx; \ |
|
1576 context->cipherInfoLen = mmm ## _FlattenSize(mmm ## _ctx); \ |
|
1577 context->currentMech = mech; \ |
|
1578 context->hashUpdate = (SFTKHash) mmm ## _Update; \ |
|
1579 context->end = (SFTKEnd) mmm ## _End; \ |
|
1580 context->destroy = (SFTKDestroy) mmm ## _DestroyContext; \ |
|
1581 context->maxLen = mmm ## _LENGTH; \ |
|
1582 if (mmm ## _ctx) \ |
|
1583 mmm ## _Begin(mmm ## _ctx); \ |
|
1584 else \ |
|
1585 crv = CKR_HOST_MEMORY; \ |
|
1586 break; \ |
|
1587 } |
|
1588 |
|
1589 switch(pMechanism->mechanism) { |
|
1590 INIT_MECH(CKM_MD2, MD2) |
|
1591 INIT_MECH(CKM_MD5, MD5) |
|
1592 INIT_MECH(CKM_SHA_1, SHA1) |
|
1593 INIT_MECH(CKM_SHA224, SHA224) |
|
1594 INIT_MECH(CKM_SHA256, SHA256) |
|
1595 INIT_MECH(CKM_SHA384, SHA384) |
|
1596 INIT_MECH(CKM_SHA512, SHA512) |
|
1597 |
|
1598 default: |
|
1599 crv = CKR_MECHANISM_INVALID; |
|
1600 break; |
|
1601 } |
|
1602 |
|
1603 if (crv != CKR_OK) { |
|
1604 sftk_FreeContext(context); |
|
1605 sftk_FreeSession(session); |
|
1606 return crv; |
|
1607 } |
|
1608 sftk_SetContextByType(session, SFTK_HASH, context); |
|
1609 sftk_FreeSession(session); |
|
1610 return CKR_OK; |
|
1611 } |
|
1612 |
|
1613 |
|
1614 /* NSC_Digest digests data in a single part. */ |
|
1615 CK_RV NSC_Digest(CK_SESSION_HANDLE hSession, |
|
1616 CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, |
|
1617 CK_ULONG_PTR pulDigestLen) |
|
1618 { |
|
1619 SFTKSession *session; |
|
1620 SFTKSessionContext *context; |
|
1621 unsigned int digestLen; |
|
1622 unsigned int maxout = *pulDigestLen; |
|
1623 CK_RV crv; |
|
1624 |
|
1625 CHECK_FORK(); |
|
1626 |
|
1627 /* make sure we're legal */ |
|
1628 crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_FALSE,&session); |
|
1629 if (crv != CKR_OK) return crv; |
|
1630 |
|
1631 if (pDigest == NULL) { |
|
1632 *pulDigestLen = context->maxLen; |
|
1633 goto finish; |
|
1634 } |
|
1635 |
|
1636 /* do it: */ |
|
1637 (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen); |
|
1638 /* NOTE: this assumes buf size is bigenough for the algorithm */ |
|
1639 (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout); |
|
1640 *pulDigestLen = digestLen; |
|
1641 |
|
1642 sftk_TerminateOp( session, SFTK_HASH, context ); |
|
1643 finish: |
|
1644 sftk_FreeSession(session); |
|
1645 return CKR_OK; |
|
1646 } |
|
1647 |
|
1648 |
|
1649 /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */ |
|
1650 CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, |
|
1651 CK_ULONG ulPartLen) |
|
1652 { |
|
1653 SFTKSessionContext *context; |
|
1654 CK_RV crv; |
|
1655 |
|
1656 CHECK_FORK(); |
|
1657 |
|
1658 /* make sure we're legal */ |
|
1659 crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_TRUE,NULL); |
|
1660 if (crv != CKR_OK) return crv; |
|
1661 /* do it: */ |
|
1662 (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen); |
|
1663 return CKR_OK; |
|
1664 } |
|
1665 |
|
1666 |
|
1667 /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */ |
|
1668 CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest, |
|
1669 CK_ULONG_PTR pulDigestLen) |
|
1670 { |
|
1671 SFTKSession *session; |
|
1672 SFTKSessionContext *context; |
|
1673 unsigned int maxout = *pulDigestLen; |
|
1674 unsigned int digestLen; |
|
1675 CK_RV crv; |
|
1676 |
|
1677 CHECK_FORK(); |
|
1678 |
|
1679 /* make sure we're legal */ |
|
1680 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
|
1681 if (crv != CKR_OK) return crv; |
|
1682 |
|
1683 if (pDigest != NULL) { |
|
1684 (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
|
1685 *pulDigestLen = digestLen; |
|
1686 sftk_TerminateOp( session, SFTK_HASH, context ); |
|
1687 } else { |
|
1688 *pulDigestLen = context->maxLen; |
|
1689 } |
|
1690 |
|
1691 sftk_FreeSession(session); |
|
1692 return CKR_OK; |
|
1693 } |
|
1694 |
|
1695 /* |
|
1696 * these helper functions are used by Generic Macing and Signing functions |
|
1697 * that use hashes as part of their operations. |
|
1698 */ |
|
1699 #define DOSUB(mmm) \ |
|
1700 static CK_RV \ |
|
1701 sftk_doSub ## mmm(SFTKSessionContext *context) { \ |
|
1702 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \ |
|
1703 context->hashInfo = (void *) mmm ## _ctx; \ |
|
1704 context->hashUpdate = (SFTKHash) mmm ## _Update; \ |
|
1705 context->end = (SFTKEnd) mmm ## _End; \ |
|
1706 context->hashdestroy = (SFTKDestroy) mmm ## _DestroyContext; \ |
|
1707 if (!context->hashInfo) { \ |
|
1708 return CKR_HOST_MEMORY; \ |
|
1709 } \ |
|
1710 mmm ## _Begin( mmm ## _ctx ); \ |
|
1711 return CKR_OK; \ |
|
1712 } |
|
1713 |
|
1714 DOSUB(MD2) |
|
1715 DOSUB(MD5) |
|
1716 DOSUB(SHA1) |
|
1717 DOSUB(SHA224) |
|
1718 DOSUB(SHA256) |
|
1719 DOSUB(SHA384) |
|
1720 DOSUB(SHA512) |
|
1721 |
|
1722 static SECStatus |
|
1723 sftk_SignCopy( |
|
1724 CK_ULONG *copyLen, |
|
1725 void *out, unsigned int *outLength, |
|
1726 unsigned int maxLength, |
|
1727 const unsigned char *hashResult, |
|
1728 unsigned int hashResultLength) |
|
1729 { |
|
1730 unsigned int toCopy = *copyLen; |
|
1731 if (toCopy > maxLength) { |
|
1732 toCopy = maxLength; |
|
1733 } |
|
1734 if (toCopy > hashResultLength) { |
|
1735 toCopy = hashResultLength; |
|
1736 } |
|
1737 memcpy(out, hashResult, toCopy); |
|
1738 if (outLength) { |
|
1739 *outLength = toCopy; |
|
1740 } |
|
1741 return SECSuccess; |
|
1742 } |
|
1743 |
|
1744 /* Verify is just a compare for HMAC */ |
|
1745 static SECStatus |
|
1746 sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen, |
|
1747 unsigned char *hash, unsigned int hashLen) |
|
1748 { |
|
1749 return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ; |
|
1750 } |
|
1751 |
|
1752 /* |
|
1753 * common HMAC initalization routine |
|
1754 */ |
|
1755 static CK_RV |
|
1756 sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash, |
|
1757 SFTKObject *key, CK_ULONG mac_size) |
|
1758 { |
|
1759 SFTKAttribute *keyval; |
|
1760 HMACContext *HMACcontext; |
|
1761 CK_ULONG *intpointer; |
|
1762 const SECHashObject *hashObj = HASH_GetRawHashObject(hash); |
|
1763 PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID); |
|
1764 |
|
1765 /* required by FIPS 198 Section 4 */ |
|
1766 if (isFIPS && (mac_size < 4 || mac_size < hashObj->length/2)) { |
|
1767 return CKR_BUFFER_TOO_SMALL; |
|
1768 } |
|
1769 |
|
1770 keyval = sftk_FindAttribute(key,CKA_VALUE); |
|
1771 if (keyval == NULL) return CKR_KEY_SIZE_RANGE; |
|
1772 |
|
1773 HMACcontext = HMAC_Create(hashObj, |
|
1774 (const unsigned char*)keyval->attrib.pValue, |
|
1775 keyval->attrib.ulValueLen, isFIPS); |
|
1776 context->hashInfo = HMACcontext; |
|
1777 context->multi = PR_TRUE; |
|
1778 sftk_FreeAttribute(keyval); |
|
1779 if (context->hashInfo == NULL) { |
|
1780 if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) { |
|
1781 return CKR_KEY_SIZE_RANGE; |
|
1782 } |
|
1783 return CKR_HOST_MEMORY; |
|
1784 } |
|
1785 context->hashUpdate = (SFTKHash) HMAC_Update; |
|
1786 context->end = (SFTKEnd) HMAC_Finish; |
|
1787 |
|
1788 context->hashdestroy = (SFTKDestroy) HMAC_Destroy; |
|
1789 intpointer = PORT_New(CK_ULONG); |
|
1790 if (intpointer == NULL) { |
|
1791 return CKR_HOST_MEMORY; |
|
1792 } |
|
1793 *intpointer = mac_size; |
|
1794 context->cipherInfo = intpointer; |
|
1795 context->destroy = (SFTKDestroy) sftk_Space; |
|
1796 context->update = (SFTKCipher) sftk_SignCopy; |
|
1797 context->verify = (SFTKVerify) sftk_HMACCmp; |
|
1798 context->maxLen = hashObj->length; |
|
1799 HMAC_Begin(HMACcontext); |
|
1800 return CKR_OK; |
|
1801 } |
|
1802 |
|
1803 /* |
|
1804 * SSL Macing support. SSL Macs are inited, then update with the base |
|
1805 * hashing algorithm, then finalized in sign and verify |
|
1806 */ |
|
1807 |
|
1808 /* |
|
1809 * FROM SSL: |
|
1810 * 60 bytes is 3 times the maximum length MAC size that is supported. |
|
1811 * We probably should have one copy of this table. We still need this table |
|
1812 * in ssl to 'sign' the handshake hashes. |
|
1813 */ |
|
1814 static unsigned char ssl_pad_1 [60] = { |
|
1815 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
|
1816 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
|
1817 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
|
1818 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
|
1819 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
|
1820 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
|
1821 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
|
1822 0x36, 0x36, 0x36, 0x36 |
|
1823 }; |
|
1824 static unsigned char ssl_pad_2 [60] = { |
|
1825 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
|
1826 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
|
1827 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
|
1828 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
|
1829 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
|
1830 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
|
1831 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
|
1832 0x5c, 0x5c, 0x5c, 0x5c |
|
1833 }; |
|
1834 |
|
1835 static SECStatus |
|
1836 sftk_SSLMACSign(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int *sigLen, |
|
1837 unsigned int maxLen,unsigned char *hash, unsigned int hashLen) |
|
1838 { |
|
1839 unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
|
1840 unsigned int out; |
|
1841 |
|
1842 info->begin(info->hashContext); |
|
1843 info->update(info->hashContext,info->key,info->keySize); |
|
1844 info->update(info->hashContext,ssl_pad_2,info->padSize); |
|
1845 info->update(info->hashContext,hash,hashLen); |
|
1846 info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH); |
|
1847 PORT_Memcpy(sig,tmpBuf,info->macSize); |
|
1848 *sigLen = info->macSize; |
|
1849 return SECSuccess; |
|
1850 } |
|
1851 |
|
1852 static SECStatus |
|
1853 sftk_SSLMACVerify(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int sigLen, |
|
1854 unsigned char *hash, unsigned int hashLen) |
|
1855 { |
|
1856 unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
|
1857 unsigned int out; |
|
1858 |
|
1859 info->begin(info->hashContext); |
|
1860 info->update(info->hashContext,info->key,info->keySize); |
|
1861 info->update(info->hashContext,ssl_pad_2,info->padSize); |
|
1862 info->update(info->hashContext,hash,hashLen); |
|
1863 info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH); |
|
1864 return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ? |
|
1865 SECSuccess : SECFailure; |
|
1866 } |
|
1867 |
|
1868 /* |
|
1869 * common HMAC initalization routine |
|
1870 */ |
|
1871 static CK_RV |
|
1872 sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid, |
|
1873 SFTKObject *key, CK_ULONG mac_size) |
|
1874 { |
|
1875 SFTKAttribute *keyval; |
|
1876 SFTKBegin begin; |
|
1877 int padSize; |
|
1878 SFTKSSLMACInfo *sslmacinfo; |
|
1879 CK_RV crv = CKR_MECHANISM_INVALID; |
|
1880 |
|
1881 if (oid == SEC_OID_SHA1) { |
|
1882 crv = sftk_doSubSHA1(context); |
|
1883 if (crv != CKR_OK) return crv; |
|
1884 begin = (SFTKBegin) SHA1_Begin; |
|
1885 padSize = 40; |
|
1886 } else { |
|
1887 crv = sftk_doSubMD5(context); |
|
1888 if (crv != CKR_OK) return crv; |
|
1889 begin = (SFTKBegin) MD5_Begin; |
|
1890 padSize = 48; |
|
1891 } |
|
1892 context->multi = PR_TRUE; |
|
1893 |
|
1894 keyval = sftk_FindAttribute(key,CKA_VALUE); |
|
1895 if (keyval == NULL) return CKR_KEY_SIZE_RANGE; |
|
1896 |
|
1897 context->hashUpdate(context->hashInfo,keyval->attrib.pValue, |
|
1898 keyval->attrib.ulValueLen); |
|
1899 context->hashUpdate(context->hashInfo,ssl_pad_1,padSize); |
|
1900 sslmacinfo = (SFTKSSLMACInfo *) PORT_Alloc(sizeof(SFTKSSLMACInfo)); |
|
1901 if (sslmacinfo == NULL) { |
|
1902 sftk_FreeAttribute(keyval); |
|
1903 return CKR_HOST_MEMORY; |
|
1904 } |
|
1905 sslmacinfo->macSize = mac_size; |
|
1906 sslmacinfo->hashContext = context->hashInfo; |
|
1907 PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue, |
|
1908 keyval->attrib.ulValueLen); |
|
1909 sslmacinfo->keySize = keyval->attrib.ulValueLen; |
|
1910 sslmacinfo->begin = begin; |
|
1911 sslmacinfo->end = context->end; |
|
1912 sslmacinfo->update = context->hashUpdate; |
|
1913 sslmacinfo->padSize = padSize; |
|
1914 sftk_FreeAttribute(keyval); |
|
1915 context->cipherInfo = (void *) sslmacinfo; |
|
1916 context->destroy = (SFTKDestroy) sftk_Space; |
|
1917 context->update = (SFTKCipher) sftk_SSLMACSign; |
|
1918 context->verify = (SFTKVerify) sftk_SSLMACVerify; |
|
1919 context->maxLen = mac_size; |
|
1920 return CKR_OK; |
|
1921 } |
|
1922 |
|
1923 /* |
|
1924 ************** Crypto Functions: Sign ************************ |
|
1925 */ |
|
1926 |
|
1927 /** |
|
1928 * Check if We're using CBCMacing and initialize the session context if we are. |
|
1929 * @param contextType SFTK_SIGN or SFTK_VERIFY |
|
1930 * @param keyUsage check whether key allows this usage |
|
1931 */ |
|
1932 static CK_RV |
|
1933 sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
|
1934 CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, |
|
1935 SFTKContextType contextType) |
|
1936 |
|
1937 { |
|
1938 CK_MECHANISM cbc_mechanism; |
|
1939 CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE; |
|
1940 CK_RC2_CBC_PARAMS rc2_params; |
|
1941 #if NSS_SOFTOKEN_DOES_RC5 |
|
1942 CK_RC5_CBC_PARAMS rc5_params; |
|
1943 CK_RC5_MAC_GENERAL_PARAMS *rc5_mac; |
|
1944 #endif |
|
1945 unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE]; |
|
1946 SFTKSessionContext *context; |
|
1947 CK_RV crv; |
|
1948 unsigned int blockSize; |
|
1949 |
|
1950 switch (pMechanism->mechanism) { |
|
1951 case CKM_RC2_MAC_GENERAL: |
|
1952 mac_bytes = |
|
1953 ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
|
1954 /* fall through */ |
|
1955 case CKM_RC2_MAC: |
|
1956 /* this works because ulEffectiveBits is in the same place in both the |
|
1957 * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ |
|
1958 rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) |
|
1959 pMechanism->pParameter)->ulEffectiveBits; |
|
1960 PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv)); |
|
1961 cbc_mechanism.mechanism = CKM_RC2_CBC; |
|
1962 cbc_mechanism.pParameter = &rc2_params; |
|
1963 cbc_mechanism.ulParameterLen = sizeof(rc2_params); |
|
1964 blockSize = 8; |
|
1965 break; |
|
1966 #if NSS_SOFTOKEN_DOES_RC5 |
|
1967 case CKM_RC5_MAC_GENERAL: |
|
1968 mac_bytes = |
|
1969 ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
|
1970 /* fall through */ |
|
1971 case CKM_RC5_MAC: |
|
1972 /* this works because ulEffectiveBits is in the same place in both the |
|
1973 * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ |
|
1974 rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; |
|
1975 rc5_params.ulWordsize = rc5_mac->ulWordsize; |
|
1976 rc5_params.ulRounds = rc5_mac->ulRounds; |
|
1977 rc5_params.pIv = ivBlock; |
|
1978 if( (blockSize = rc5_mac->ulWordsize*2) > SFTK_MAX_BLOCK_SIZE ) |
|
1979 return CKR_MECHANISM_PARAM_INVALID; |
|
1980 rc5_params.ulIvLen = blockSize; |
|
1981 PORT_Memset(ivBlock,0,blockSize); |
|
1982 cbc_mechanism.mechanism = CKM_RC5_CBC; |
|
1983 cbc_mechanism.pParameter = &rc5_params; |
|
1984 cbc_mechanism.ulParameterLen = sizeof(rc5_params); |
|
1985 break; |
|
1986 #endif |
|
1987 /* add cast and idea later */ |
|
1988 case CKM_DES_MAC_GENERAL: |
|
1989 mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
|
1990 /* fall through */ |
|
1991 case CKM_DES_MAC: |
|
1992 blockSize = 8; |
|
1993 PORT_Memset(ivBlock,0,blockSize); |
|
1994 cbc_mechanism.mechanism = CKM_DES_CBC; |
|
1995 cbc_mechanism.pParameter = &ivBlock; |
|
1996 cbc_mechanism.ulParameterLen = blockSize; |
|
1997 break; |
|
1998 case CKM_DES3_MAC_GENERAL: |
|
1999 mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
|
2000 /* fall through */ |
|
2001 case CKM_DES3_MAC: |
|
2002 blockSize = 8; |
|
2003 PORT_Memset(ivBlock,0,blockSize); |
|
2004 cbc_mechanism.mechanism = CKM_DES3_CBC; |
|
2005 cbc_mechanism.pParameter = &ivBlock; |
|
2006 cbc_mechanism.ulParameterLen = blockSize; |
|
2007 break; |
|
2008 case CKM_CDMF_MAC_GENERAL: |
|
2009 mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
|
2010 /* fall through */ |
|
2011 case CKM_CDMF_MAC: |
|
2012 blockSize = 8; |
|
2013 PORT_Memset(ivBlock,0,blockSize); |
|
2014 cbc_mechanism.mechanism = CKM_CDMF_CBC; |
|
2015 cbc_mechanism.pParameter = &ivBlock; |
|
2016 cbc_mechanism.ulParameterLen = blockSize; |
|
2017 break; |
|
2018 case CKM_SEED_MAC_GENERAL: |
|
2019 mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
|
2020 /* fall through */ |
|
2021 case CKM_SEED_MAC: |
|
2022 blockSize = 16; |
|
2023 PORT_Memset(ivBlock,0,blockSize); |
|
2024 cbc_mechanism.mechanism = CKM_SEED_CBC; |
|
2025 cbc_mechanism.pParameter = &ivBlock; |
|
2026 cbc_mechanism.ulParameterLen = blockSize; |
|
2027 break; |
|
2028 case CKM_CAMELLIA_MAC_GENERAL: |
|
2029 mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
|
2030 /* fall through */ |
|
2031 case CKM_CAMELLIA_MAC: |
|
2032 blockSize = 16; |
|
2033 PORT_Memset(ivBlock,0,blockSize); |
|
2034 cbc_mechanism.mechanism = CKM_CAMELLIA_CBC; |
|
2035 cbc_mechanism.pParameter = &ivBlock; |
|
2036 cbc_mechanism.ulParameterLen = blockSize; |
|
2037 break; |
|
2038 case CKM_AES_MAC_GENERAL: |
|
2039 mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
|
2040 /* fall through */ |
|
2041 case CKM_AES_MAC: |
|
2042 blockSize = 16; |
|
2043 PORT_Memset(ivBlock,0,blockSize); |
|
2044 cbc_mechanism.mechanism = CKM_AES_CBC; |
|
2045 cbc_mechanism.pParameter = &ivBlock; |
|
2046 cbc_mechanism.ulParameterLen = blockSize; |
|
2047 break; |
|
2048 default: |
|
2049 return CKR_FUNCTION_NOT_SUPPORTED; |
|
2050 } |
|
2051 |
|
2052 /* if MAC size is externally supplied, it should be checked. |
|
2053 */ |
|
2054 if (mac_bytes == SFTK_INVALID_MAC_SIZE) |
|
2055 mac_bytes = blockSize >> 1; |
|
2056 else { |
|
2057 if( mac_bytes > blockSize ) |
|
2058 return CKR_MECHANISM_PARAM_INVALID; |
|
2059 } |
|
2060 |
|
2061 crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, |
|
2062 CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ |
|
2063 keyUsage, contextType, PR_TRUE ); |
|
2064 if (crv != CKR_OK) return crv; |
|
2065 crv = sftk_GetContext(hSession,&context,contextType,PR_TRUE,NULL); |
|
2066 |
|
2067 /* this shouldn't happen! */ |
|
2068 PORT_Assert(crv == CKR_OK); |
|
2069 if (crv != CKR_OK) return crv; |
|
2070 context->blockSize = blockSize; |
|
2071 context->macSize = mac_bytes; |
|
2072 return CKR_OK; |
|
2073 } |
|
2074 |
|
2075 /* |
|
2076 * encode RSA PKCS #1 Signature data before signing... |
|
2077 */ |
|
2078 static SECStatus |
|
2079 sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig, |
|
2080 unsigned int *sigLen, unsigned int maxLen, |
|
2081 const unsigned char *hash, unsigned int hashLen) |
|
2082 { |
|
2083 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
|
2084 if (info->key->keyType != NSSLOWKEYRSAKey) { |
|
2085 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
2086 return SECFailure; |
|
2087 } |
|
2088 |
|
2089 return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen, |
|
2090 hash, hashLen); |
|
2091 } |
|
2092 |
|
2093 /* XXX Old template; want to expunge it eventually. */ |
|
2094 static DERTemplate SECAlgorithmIDTemplate[] = { |
|
2095 { DER_SEQUENCE, |
|
2096 0, NULL, sizeof(SECAlgorithmID) }, |
|
2097 { DER_OBJECT_ID, |
|
2098 offsetof(SECAlgorithmID,algorithm), }, |
|
2099 { DER_OPTIONAL | DER_ANY, |
|
2100 offsetof(SECAlgorithmID,parameters), }, |
|
2101 { 0, } |
|
2102 }; |
|
2103 |
|
2104 /* |
|
2105 * XXX OLD Template. Once all uses have been switched over to new one, |
|
2106 * remove this. |
|
2107 */ |
|
2108 static DERTemplate SGNDigestInfoTemplate[] = { |
|
2109 { DER_SEQUENCE, |
|
2110 0, NULL, sizeof(SGNDigestInfo) }, |
|
2111 { DER_INLINE, |
|
2112 offsetof(SGNDigestInfo,digestAlgorithm), |
|
2113 SECAlgorithmIDTemplate, }, |
|
2114 { DER_OCTET_STRING, |
|
2115 offsetof(SGNDigestInfo,digest), }, |
|
2116 { 0, } |
|
2117 }; |
|
2118 |
|
2119 /* |
|
2120 * encode RSA PKCS #1 Signature data before signing... |
|
2121 */ |
|
2122 SECStatus |
|
2123 RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, |
|
2124 unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, |
|
2125 const unsigned char *hash, unsigned int hashLen) |
|
2126 { |
|
2127 SECStatus rv = SECFailure; |
|
2128 SECItem digder; |
|
2129 PLArenaPool *arena = NULL; |
|
2130 SGNDigestInfo *di = NULL; |
|
2131 |
|
2132 digder.data = NULL; |
|
2133 |
|
2134 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
2135 if (!arena) { |
|
2136 goto loser; |
|
2137 } |
|
2138 |
|
2139 /* Construct digest info */ |
|
2140 di = SGN_CreateDigestInfo(hashOid, hash, hashLen); |
|
2141 if (!di) { |
|
2142 goto loser; |
|
2143 } |
|
2144 |
|
2145 /* Der encode the digest as a DigestInfo */ |
|
2146 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); |
|
2147 if (rv != SECSuccess) { |
|
2148 goto loser; |
|
2149 } |
|
2150 |
|
2151 /* |
|
2152 ** Encrypt signature after constructing appropriate PKCS#1 signature |
|
2153 ** block |
|
2154 */ |
|
2155 rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data, |
|
2156 digder.len); |
|
2157 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
2158 sftk_fatalError = PR_TRUE; |
|
2159 } |
|
2160 |
|
2161 loser: |
|
2162 SGN_DestroyDigestInfo(di); |
|
2163 if (arena != NULL) { |
|
2164 PORT_FreeArena(arena, PR_FALSE); |
|
2165 } |
|
2166 return rv; |
|
2167 } |
|
2168 |
|
2169 static SECStatus |
|
2170 sftk_RSASign(NSSLOWKEYPrivateKey *key, unsigned char *output, |
|
2171 unsigned int *outputLen, unsigned int maxOutputLen, |
|
2172 const unsigned char *input, unsigned int inputLen) |
|
2173 { |
|
2174 SECStatus rv = SECFailure; |
|
2175 |
|
2176 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
2177 if (key->keyType != NSSLOWKEYRSAKey) { |
|
2178 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
2179 return SECFailure; |
|
2180 } |
|
2181 |
|
2182 rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input, |
|
2183 inputLen); |
|
2184 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
2185 sftk_fatalError = PR_TRUE; |
|
2186 } |
|
2187 return rv; |
|
2188 } |
|
2189 |
|
2190 static SECStatus |
|
2191 sftk_RSASignRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, |
|
2192 unsigned int *outputLen, unsigned int maxOutputLen, |
|
2193 const unsigned char *input, unsigned int inputLen) |
|
2194 { |
|
2195 SECStatus rv = SECFailure; |
|
2196 |
|
2197 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
2198 if (key->keyType != NSSLOWKEYRSAKey) { |
|
2199 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
2200 return SECFailure; |
|
2201 } |
|
2202 |
|
2203 rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input, |
|
2204 inputLen); |
|
2205 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
2206 sftk_fatalError = PR_TRUE; |
|
2207 } |
|
2208 return rv; |
|
2209 |
|
2210 } |
|
2211 |
|
2212 static SECStatus |
|
2213 sftk_RSASignPSS(SFTKHashSignInfo *info, unsigned char *sig, |
|
2214 unsigned int *sigLen, unsigned int maxLen, |
|
2215 const unsigned char *hash, unsigned int hashLen) |
|
2216 { |
|
2217 SECStatus rv = SECFailure; |
|
2218 HASH_HashType hashAlg; |
|
2219 HASH_HashType maskHashAlg; |
|
2220 CK_RSA_PKCS_PSS_PARAMS *params = (CK_RSA_PKCS_PSS_PARAMS *)info->params; |
|
2221 |
|
2222 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
|
2223 if (info->key->keyType != NSSLOWKEYRSAKey) { |
|
2224 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
2225 return SECFailure; |
|
2226 } |
|
2227 |
|
2228 hashAlg = GetHashTypeFromMechanism(params->hashAlg); |
|
2229 maskHashAlg = GetHashTypeFromMechanism(params->mgf); |
|
2230 |
|
2231 rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL, |
|
2232 params->sLen, sig, sigLen, maxLen, hash, hashLen); |
|
2233 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
2234 sftk_fatalError = PR_TRUE; |
|
2235 } |
|
2236 return rv; |
|
2237 } |
|
2238 |
|
2239 static SECStatus |
|
2240 nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen, |
|
2241 void *dataBuf, unsigned int dataLen) |
|
2242 { |
|
2243 SECItem signature, digest; |
|
2244 NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; |
|
2245 |
|
2246 signature.data = (unsigned char *)sigBuf; |
|
2247 signature.len = sigLen; |
|
2248 digest.data = (unsigned char *)dataBuf; |
|
2249 digest.len = dataLen; |
|
2250 return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest); |
|
2251 } |
|
2252 |
|
2253 static SECStatus |
|
2254 nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, |
|
2255 unsigned int *sigLen, unsigned int maxSigLen, |
|
2256 void *dataBuf, unsigned int dataLen) |
|
2257 { |
|
2258 SECItem signature, digest; |
|
2259 SECStatus rv; |
|
2260 NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; |
|
2261 |
|
2262 signature.data = (unsigned char *)sigBuf; |
|
2263 signature.len = maxSigLen; |
|
2264 digest.data = (unsigned char *)dataBuf; |
|
2265 digest.len = dataLen; |
|
2266 rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); |
|
2267 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
2268 sftk_fatalError = PR_TRUE; |
|
2269 } |
|
2270 *sigLen = signature.len; |
|
2271 return rv; |
|
2272 } |
|
2273 |
|
2274 #ifndef NSS_DISABLE_ECC |
|
2275 static SECStatus |
|
2276 nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen, |
|
2277 void *dataBuf, unsigned int dataLen) |
|
2278 { |
|
2279 SECItem signature, digest; |
|
2280 NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; |
|
2281 |
|
2282 signature.data = (unsigned char *)sigBuf; |
|
2283 signature.len = sigLen; |
|
2284 digest.data = (unsigned char *)dataBuf; |
|
2285 digest.len = dataLen; |
|
2286 return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest); |
|
2287 } |
|
2288 |
|
2289 static SECStatus |
|
2290 nsc_ECDSASignStub(void *ctx, void *sigBuf, |
|
2291 unsigned int *sigLen, unsigned int maxSigLen, |
|
2292 void *dataBuf, unsigned int dataLen) |
|
2293 { |
|
2294 SECItem signature, digest; |
|
2295 SECStatus rv; |
|
2296 NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; |
|
2297 |
|
2298 signature.data = (unsigned char *)sigBuf; |
|
2299 signature.len = maxSigLen; |
|
2300 digest.data = (unsigned char *)dataBuf; |
|
2301 digest.len = dataLen; |
|
2302 rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); |
|
2303 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
2304 sftk_fatalError = PR_TRUE; |
|
2305 } |
|
2306 *sigLen = signature.len; |
|
2307 return rv; |
|
2308 } |
|
2309 #endif /* NSS_DISABLE_ECC */ |
|
2310 |
|
2311 /* NSC_SignInit setups up the signing operations. There are three basic |
|
2312 * types of signing: |
|
2313 * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied |
|
2314 * to data in a single Sign operation (which often looks a lot like an |
|
2315 * encrypt, with data coming in and data going out). |
|
2316 * (2) Hash based signing, where we continually hash the data, then apply |
|
2317 * some sort of signature to the end. |
|
2318 * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, |
|
2319 * and only the final block is part of the mac. |
|
2320 * |
|
2321 * For case number 3, we initialize a context much like the Encryption Context |
|
2322 * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and |
|
2323 * C_Final by the following method... if it's not multi-part, and it's doesn't |
|
2324 * have a hash context, it must be a block Encryption CBC MAC. |
|
2325 * |
|
2326 * For case number 2, we initialize a hash structure, as well as make it |
|
2327 * multi-part. Updates are simple calls to the hash update function. Final |
|
2328 * calls the hashend, then passes the result to the 'update' function (which |
|
2329 * operates as a final signature function). In some hash based MAC'ing (as |
|
2330 * opposed to hash base signatures), the update function is can be simply a |
|
2331 * copy (as is the case with HMAC). |
|
2332 */ |
|
2333 CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession, |
|
2334 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
|
2335 { |
|
2336 SFTKSession *session; |
|
2337 SFTKObject *key; |
|
2338 SFTKSessionContext *context; |
|
2339 CK_KEY_TYPE key_type; |
|
2340 CK_RV crv = CKR_OK; |
|
2341 NSSLOWKEYPrivateKey *privKey; |
|
2342 SFTKHashSignInfo *info = NULL; |
|
2343 |
|
2344 CHECK_FORK(); |
|
2345 |
|
2346 /* Block Cipher MACing Algorithms use a different Context init method..*/ |
|
2347 crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN); |
|
2348 if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv; |
|
2349 |
|
2350 /* we're not using a block cipher mac */ |
|
2351 session = sftk_SessionFromHandle(hSession); |
|
2352 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; |
|
2353 crv = sftk_InitGeneric(session,&context,SFTK_SIGN,&key,hKey,&key_type, |
|
2354 CKO_PRIVATE_KEY,CKA_SIGN); |
|
2355 if (crv != CKR_OK) { |
|
2356 sftk_FreeSession(session); |
|
2357 return crv; |
|
2358 } |
|
2359 |
|
2360 context->multi = PR_FALSE; |
|
2361 |
|
2362 #define INIT_RSA_SIGN_MECH(mmm) \ |
|
2363 case CKM_ ## mmm ## _RSA_PKCS: \ |
|
2364 context->multi = PR_TRUE; \ |
|
2365 crv = sftk_doSub ## mmm (context); \ |
|
2366 if (crv != CKR_OK) break; \ |
|
2367 context->update = (SFTKCipher) sftk_RSAHashSign; \ |
|
2368 info = PORT_New(SFTKHashSignInfo); \ |
|
2369 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \ |
|
2370 info->hashOid = SEC_OID_ ## mmm ; \ |
|
2371 goto finish_rsa; |
|
2372 |
|
2373 switch(pMechanism->mechanism) { |
|
2374 INIT_RSA_SIGN_MECH(MD5) |
|
2375 INIT_RSA_SIGN_MECH(MD2) |
|
2376 INIT_RSA_SIGN_MECH(SHA1) |
|
2377 INIT_RSA_SIGN_MECH(SHA224) |
|
2378 INIT_RSA_SIGN_MECH(SHA256) |
|
2379 INIT_RSA_SIGN_MECH(SHA384) |
|
2380 INIT_RSA_SIGN_MECH(SHA512) |
|
2381 |
|
2382 case CKM_RSA_PKCS: |
|
2383 context->update = (SFTKCipher) sftk_RSASign; |
|
2384 goto finish_rsa; |
|
2385 case CKM_RSA_X_509: |
|
2386 context->update = (SFTKCipher) sftk_RSASignRaw; |
|
2387 finish_rsa: |
|
2388 if (key_type != CKK_RSA) { |
|
2389 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
2390 break; |
|
2391 } |
|
2392 context->rsa = PR_TRUE; |
|
2393 privKey = sftk_GetPrivKey(key,CKK_RSA,&crv); |
|
2394 if (privKey == NULL) { |
|
2395 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
2396 break; |
|
2397 } |
|
2398 /* OK, info is allocated only if we're doing hash and sign mechanism. |
|
2399 * It's necessary to be able to set the correct OID in the final |
|
2400 * signature. |
|
2401 */ |
|
2402 if (info) { |
|
2403 info->key = privKey; |
|
2404 context->cipherInfo = info; |
|
2405 context->destroy = (SFTKDestroy)sftk_Space; |
|
2406 } else { |
|
2407 context->cipherInfo = privKey; |
|
2408 context->destroy = (SFTKDestroy)sftk_Null; |
|
2409 } |
|
2410 context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
|
2411 break; |
|
2412 case CKM_RSA_PKCS_PSS: |
|
2413 if (key_type != CKK_RSA) { |
|
2414 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
2415 break; |
|
2416 } |
|
2417 context->rsa = PR_TRUE; |
|
2418 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
|
2419 !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)) { |
|
2420 crv = CKR_MECHANISM_PARAM_INVALID; |
|
2421 break; |
|
2422 } |
|
2423 info = PORT_New(SFTKHashSignInfo); |
|
2424 if (info == NULL) { |
|
2425 crv = CKR_HOST_MEMORY; |
|
2426 break; |
|
2427 } |
|
2428 info->params = pMechanism->pParameter; |
|
2429 info->key = sftk_GetPrivKey(key,CKK_RSA,&crv); |
|
2430 if (info->key == NULL) { |
|
2431 PORT_Free(info); |
|
2432 break; |
|
2433 } |
|
2434 context->cipherInfo = info; |
|
2435 context->destroy = (SFTKDestroy) sftk_Space; |
|
2436 context->update = (SFTKCipher) sftk_RSASignPSS; |
|
2437 context->maxLen = nsslowkey_PrivateModulusLen(info->key); |
|
2438 break; |
|
2439 |
|
2440 case CKM_DSA_SHA1: |
|
2441 context->multi = PR_TRUE; |
|
2442 crv = sftk_doSubSHA1(context); |
|
2443 if (crv != CKR_OK) break; |
|
2444 /* fall through */ |
|
2445 case CKM_DSA: |
|
2446 if (key_type != CKK_DSA) { |
|
2447 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
2448 break; |
|
2449 } |
|
2450 privKey = sftk_GetPrivKey(key,CKK_DSA,&crv); |
|
2451 if (privKey == NULL) { |
|
2452 break; |
|
2453 } |
|
2454 context->cipherInfo = privKey; |
|
2455 context->update = (SFTKCipher) nsc_DSA_Sign_Stub; |
|
2456 context->destroy = (privKey == key->objectInfo) ? |
|
2457 (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey; |
|
2458 context->maxLen = DSA_MAX_SIGNATURE_LEN; |
|
2459 |
|
2460 break; |
|
2461 |
|
2462 #ifndef NSS_DISABLE_ECC |
|
2463 case CKM_ECDSA_SHA1: |
|
2464 context->multi = PR_TRUE; |
|
2465 crv = sftk_doSubSHA1(context); |
|
2466 if (crv != CKR_OK) break; |
|
2467 /* fall through */ |
|
2468 case CKM_ECDSA: |
|
2469 if (key_type != CKK_EC) { |
|
2470 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
2471 break; |
|
2472 } |
|
2473 privKey = sftk_GetPrivKey(key,CKK_EC,&crv); |
|
2474 if (privKey == NULL) { |
|
2475 crv = CKR_HOST_MEMORY; |
|
2476 break; |
|
2477 } |
|
2478 context->cipherInfo = privKey; |
|
2479 context->update = (SFTKCipher) nsc_ECDSASignStub; |
|
2480 context->destroy = (privKey == key->objectInfo) ? |
|
2481 (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey; |
|
2482 context->maxLen = MAX_ECKEY_LEN * 2; |
|
2483 |
|
2484 break; |
|
2485 #endif /* NSS_DISABLE_ECC */ |
|
2486 |
|
2487 #define INIT_HMAC_MECH(mmm) \ |
|
2488 case CKM_ ## mmm ## _HMAC_GENERAL: \ |
|
2489 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, \ |
|
2490 *(CK_ULONG *)pMechanism->pParameter); \ |
|
2491 break; \ |
|
2492 case CKM_ ## mmm ## _HMAC: \ |
|
2493 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, mmm ## _LENGTH); \ |
|
2494 break; |
|
2495 |
|
2496 INIT_HMAC_MECH(MD2) |
|
2497 INIT_HMAC_MECH(MD5) |
|
2498 INIT_HMAC_MECH(SHA224) |
|
2499 INIT_HMAC_MECH(SHA256) |
|
2500 INIT_HMAC_MECH(SHA384) |
|
2501 INIT_HMAC_MECH(SHA512) |
|
2502 |
|
2503 case CKM_SHA_1_HMAC_GENERAL: |
|
2504 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key, |
|
2505 *(CK_ULONG *)pMechanism->pParameter); |
|
2506 break; |
|
2507 case CKM_SHA_1_HMAC: |
|
2508 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); |
|
2509 break; |
|
2510 |
|
2511 case CKM_SSL3_MD5_MAC: |
|
2512 crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key, |
|
2513 *(CK_ULONG *)pMechanism->pParameter); |
|
2514 break; |
|
2515 case CKM_SSL3_SHA1_MAC: |
|
2516 crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key, |
|
2517 *(CK_ULONG *)pMechanism->pParameter); |
|
2518 break; |
|
2519 case CKM_TLS_PRF_GENERAL: |
|
2520 crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL); |
|
2521 break; |
|
2522 case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
|
2523 crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256); |
|
2524 break; |
|
2525 |
|
2526 case CKM_NSS_HMAC_CONSTANT_TIME: { |
|
2527 sftk_MACConstantTimeCtx *ctx = |
|
2528 sftk_HMACConstantTime_New(pMechanism,key); |
|
2529 CK_ULONG *intpointer; |
|
2530 |
|
2531 if (ctx == NULL) { |
|
2532 crv = CKR_ARGUMENTS_BAD; |
|
2533 break; |
|
2534 } |
|
2535 intpointer = PORT_New(CK_ULONG); |
|
2536 if (intpointer == NULL) { |
|
2537 crv = CKR_HOST_MEMORY; |
|
2538 break; |
|
2539 } |
|
2540 *intpointer = ctx->hash->length; |
|
2541 |
|
2542 context->cipherInfo = intpointer; |
|
2543 context->hashInfo = ctx; |
|
2544 context->currentMech = pMechanism->mechanism; |
|
2545 context->hashUpdate = sftk_HMACConstantTime_Update; |
|
2546 context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
|
2547 context->end = sftk_MACConstantTime_EndHash; |
|
2548 context->update = (SFTKCipher) sftk_SignCopy; |
|
2549 context->destroy = sftk_Space; |
|
2550 context->maxLen = 64; |
|
2551 context->multi = PR_TRUE; |
|
2552 break; |
|
2553 } |
|
2554 |
|
2555 case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { |
|
2556 sftk_MACConstantTimeCtx *ctx = |
|
2557 sftk_SSLv3MACConstantTime_New(pMechanism,key); |
|
2558 CK_ULONG *intpointer; |
|
2559 |
|
2560 if (ctx == NULL) { |
|
2561 crv = CKR_ARGUMENTS_BAD; |
|
2562 break; |
|
2563 } |
|
2564 intpointer = PORT_New(CK_ULONG); |
|
2565 if (intpointer == NULL) { |
|
2566 crv = CKR_HOST_MEMORY; |
|
2567 break; |
|
2568 } |
|
2569 *intpointer = ctx->hash->length; |
|
2570 |
|
2571 context->cipherInfo = intpointer; |
|
2572 context->hashInfo = ctx; |
|
2573 context->currentMech = pMechanism->mechanism; |
|
2574 context->hashUpdate = sftk_SSLv3MACConstantTime_Update; |
|
2575 context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
|
2576 context->end = sftk_MACConstantTime_EndHash; |
|
2577 context->update = (SFTKCipher) sftk_SignCopy; |
|
2578 context->destroy = sftk_Space; |
|
2579 context->maxLen = 64; |
|
2580 context->multi = PR_TRUE; |
|
2581 break; |
|
2582 } |
|
2583 |
|
2584 default: |
|
2585 crv = CKR_MECHANISM_INVALID; |
|
2586 break; |
|
2587 } |
|
2588 |
|
2589 if (crv != CKR_OK) { |
|
2590 if (info) PORT_Free(info); |
|
2591 sftk_FreeContext(context); |
|
2592 sftk_FreeSession(session); |
|
2593 return crv; |
|
2594 } |
|
2595 sftk_SetContextByType(session, SFTK_SIGN, context); |
|
2596 sftk_FreeSession(session); |
|
2597 return CKR_OK; |
|
2598 } |
|
2599 |
|
2600 /** MAC one block of data by block cipher |
|
2601 */ |
|
2602 static CK_RV |
|
2603 sftk_MACBlock( SFTKSessionContext *ctx, void *blk ) |
|
2604 { |
|
2605 unsigned int outlen; |
|
2606 return ( SECSuccess == (ctx->update)( ctx->cipherInfo, ctx->macBuf, &outlen, |
|
2607 SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize )) |
|
2608 ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
|
2609 } |
|
2610 |
|
2611 /** MAC last (incomplete) block of data by block cipher |
|
2612 * |
|
2613 * Call once, then terminate MACing operation. |
|
2614 */ |
|
2615 static CK_RV |
|
2616 sftk_MACFinal( SFTKSessionContext *ctx ) |
|
2617 { |
|
2618 unsigned int padLen = ctx->padDataLength; |
|
2619 /* pad and proceed the residual */ |
|
2620 if( padLen ) { |
|
2621 /* shd clr ctx->padLen to make sftk_MACFinal idempotent */ |
|
2622 PORT_Memset( ctx->padBuf + padLen, 0, ctx->blockSize - padLen ); |
|
2623 return sftk_MACBlock( ctx, ctx->padBuf ); |
|
2624 } else |
|
2625 return CKR_OK; |
|
2626 } |
|
2627 |
|
2628 /** The common implementation for {Sign,Verify}Update. (S/V only vary in their |
|
2629 * setup and final operations). |
|
2630 * |
|
2631 * A call which results in an error terminates the operation [PKCS#11,v2.11] |
|
2632 */ |
|
2633 static CK_RV |
|
2634 sftk_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, |
|
2635 CK_ULONG ulPartLen,SFTKContextType type) |
|
2636 { |
|
2637 SFTKSession *session; |
|
2638 SFTKSessionContext *context; |
|
2639 CK_RV crv; |
|
2640 |
|
2641 /* make sure we're legal */ |
|
2642 crv = sftk_GetContext(hSession,&context,type, PR_TRUE, &session ); |
|
2643 if (crv != CKR_OK) return crv; |
|
2644 |
|
2645 if (context->hashInfo) { |
|
2646 (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); |
|
2647 } else { |
|
2648 /* must be block cipher MACing */ |
|
2649 |
|
2650 unsigned int blkSize = context->blockSize; |
|
2651 unsigned char *residual = /* free room in context->padBuf */ |
|
2652 context->padBuf + context->padDataLength; |
|
2653 unsigned int minInput = /* min input for MACing at least one block */ |
|
2654 blkSize - context->padDataLength; |
|
2655 |
|
2656 /* not enough data even for one block */ |
|
2657 if( ulPartLen < minInput ) { |
|
2658 PORT_Memcpy( residual, pPart, ulPartLen ); |
|
2659 context->padDataLength += ulPartLen; |
|
2660 goto cleanup; |
|
2661 } |
|
2662 /* MACing residual */ |
|
2663 if( context->padDataLength ) { |
|
2664 PORT_Memcpy( residual, pPart, minInput ); |
|
2665 ulPartLen -= minInput; |
|
2666 pPart += minInput; |
|
2667 if( CKR_OK != (crv = sftk_MACBlock( context, context->padBuf )) ) |
|
2668 goto terminate; |
|
2669 } |
|
2670 /* MACing full blocks */ |
|
2671 while( ulPartLen >= blkSize ) |
|
2672 { |
|
2673 if( CKR_OK != (crv = sftk_MACBlock( context, pPart )) ) |
|
2674 goto terminate; |
|
2675 ulPartLen -= blkSize; |
|
2676 pPart += blkSize; |
|
2677 } |
|
2678 /* save the residual */ |
|
2679 if( (context->padDataLength = ulPartLen) ) |
|
2680 PORT_Memcpy( context->padBuf, pPart, ulPartLen ); |
|
2681 } /* blk cipher MACing */ |
|
2682 |
|
2683 goto cleanup; |
|
2684 |
|
2685 terminate: |
|
2686 sftk_TerminateOp( session, type, context ); |
|
2687 cleanup: |
|
2688 sftk_FreeSession(session); |
|
2689 return crv; |
|
2690 } |
|
2691 |
|
2692 /* NSC_SignUpdate continues a multiple-part signature operation, |
|
2693 * where the signature is (will be) an appendix to the data, |
|
2694 * and plaintext cannot be recovered from the signature |
|
2695 * |
|
2696 * A call which results in an error terminates the operation [PKCS#11,v2.11] |
|
2697 */ |
|
2698 CK_RV NSC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, |
|
2699 CK_ULONG ulPartLen) |
|
2700 { |
|
2701 CHECK_FORK(); |
|
2702 return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN); |
|
2703 } |
|
2704 |
|
2705 |
|
2706 /* NSC_SignFinal finishes a multiple-part signature operation, |
|
2707 * returning the signature. */ |
|
2708 CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature, |
|
2709 CK_ULONG_PTR pulSignatureLen) |
|
2710 { |
|
2711 SFTKSession *session; |
|
2712 SFTKSessionContext *context; |
|
2713 unsigned int outlen; |
|
2714 unsigned int maxoutlen = *pulSignatureLen; |
|
2715 CK_RV crv; |
|
2716 |
|
2717 CHECK_FORK(); |
|
2718 |
|
2719 /* make sure we're legal */ |
|
2720 crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_TRUE,&session); |
|
2721 if (crv != CKR_OK) return crv; |
|
2722 |
|
2723 if (context->hashInfo) { |
|
2724 unsigned int digestLen; |
|
2725 unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
|
2726 |
|
2727 if( !pSignature ) { |
|
2728 outlen = context->maxLen; goto finish; |
|
2729 } |
|
2730 (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
|
2731 if( SECSuccess != (context->update)(context->cipherInfo, pSignature, |
|
2732 &outlen, maxoutlen, tmpbuf, digestLen)) |
|
2733 crv = sftk_MapCryptError(PORT_GetError()); |
|
2734 /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate. |
|
2735 * Keeping "too small" CK_RV intact is a standard violation, but allows |
|
2736 * application read EXACT signature length */ |
|
2737 } else { |
|
2738 /* must be block cipher MACing */ |
|
2739 outlen = context->macSize; |
|
2740 /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/ |
|
2741 if( !pSignature || maxoutlen < outlen ) { |
|
2742 if( pSignature ) crv = CKR_BUFFER_TOO_SMALL; |
|
2743 goto finish; |
|
2744 } |
|
2745 if( CKR_OK == (crv = sftk_MACFinal( context )) ) |
|
2746 PORT_Memcpy(pSignature, context->macBuf, outlen ); |
|
2747 } |
|
2748 |
|
2749 sftk_TerminateOp( session, SFTK_SIGN, context ); |
|
2750 finish: |
|
2751 *pulSignatureLen = outlen; |
|
2752 sftk_FreeSession(session); |
|
2753 return crv; |
|
2754 } |
|
2755 |
|
2756 /* NSC_Sign signs (encrypts with private key) data in a single part, |
|
2757 * where the signature is (will be) an appendix to the data, |
|
2758 * and plaintext cannot be recovered from the signature */ |
|
2759 CK_RV NSC_Sign(CK_SESSION_HANDLE hSession, |
|
2760 CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature, |
|
2761 CK_ULONG_PTR pulSignatureLen) |
|
2762 { |
|
2763 SFTKSession *session; |
|
2764 SFTKSessionContext *context; |
|
2765 CK_RV crv; |
|
2766 |
|
2767 CHECK_FORK(); |
|
2768 |
|
2769 /* make sure we're legal */ |
|
2770 crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_FALSE,&session); |
|
2771 if (crv != CKR_OK) return crv; |
|
2772 |
|
2773 if (!pSignature) { |
|
2774 /* see also how C_SignUpdate implements this */ |
|
2775 *pulSignatureLen = (!context->multi || context->hashInfo) |
|
2776 ? context->maxLen |
|
2777 : context->macSize; /* must be block cipher MACing */ |
|
2778 goto finish; |
|
2779 } |
|
2780 |
|
2781 /* multi part Signing are completely implemented by SignUpdate and |
|
2782 * sign Final */ |
|
2783 if (context->multi) { |
|
2784 /* SignFinal can't follow failed SignUpdate */ |
|
2785 if( CKR_OK == (crv = NSC_SignUpdate(hSession,pData,ulDataLen) )) |
|
2786 crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen); |
|
2787 } else { |
|
2788 /* single-part PKC signature (e.g. CKM_ECDSA) */ |
|
2789 unsigned int outlen; |
|
2790 unsigned int maxoutlen = *pulSignatureLen; |
|
2791 if( SECSuccess != (*context->update)(context->cipherInfo, pSignature, |
|
2792 &outlen, maxoutlen, pData, ulDataLen)) |
|
2793 crv = sftk_MapCryptError(PORT_GetError()); |
|
2794 *pulSignatureLen = (CK_ULONG) outlen; |
|
2795 /* "too small" here is certainly continuable */ |
|
2796 if( crv != CKR_BUFFER_TOO_SMALL ) |
|
2797 sftk_TerminateOp(session, SFTK_SIGN, context); |
|
2798 } /* single-part */ |
|
2799 |
|
2800 finish: |
|
2801 sftk_FreeSession(session); |
|
2802 return crv; |
|
2803 } |
|
2804 |
|
2805 |
|
2806 /* |
|
2807 ************** Crypto Functions: Sign Recover ************************ |
|
2808 */ |
|
2809 /* NSC_SignRecoverInit initializes a signature operation, |
|
2810 * where the (digest) data can be recovered from the signature. |
|
2811 * E.g. encryption with the user's private key */ |
|
2812 CK_RV NSC_SignRecoverInit(CK_SESSION_HANDLE hSession, |
|
2813 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) |
|
2814 { |
|
2815 CHECK_FORK(); |
|
2816 |
|
2817 switch (pMechanism->mechanism) { |
|
2818 case CKM_RSA_PKCS: |
|
2819 case CKM_RSA_X_509: |
|
2820 return NSC_SignInit(hSession,pMechanism,hKey); |
|
2821 default: |
|
2822 break; |
|
2823 } |
|
2824 return CKR_MECHANISM_INVALID; |
|
2825 } |
|
2826 |
|
2827 |
|
2828 /* NSC_SignRecover signs data in a single operation |
|
2829 * where the (digest) data can be recovered from the signature. |
|
2830 * E.g. encryption with the user's private key */ |
|
2831 CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
|
2832 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) |
|
2833 { |
|
2834 CHECK_FORK(); |
|
2835 |
|
2836 return NSC_Sign(hSession,pData,ulDataLen,pSignature,pulSignatureLen); |
|
2837 } |
|
2838 |
|
2839 /* |
|
2840 ************** Crypto Functions: verify ************************ |
|
2841 */ |
|
2842 |
|
2843 /* Handle RSA Signature formatting */ |
|
2844 static SECStatus |
|
2845 sftk_hashCheckSign(SFTKHashVerifyInfo *info, const unsigned char *sig, |
|
2846 unsigned int sigLen, const unsigned char *digest, |
|
2847 unsigned int digestLen) |
|
2848 { |
|
2849 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
|
2850 if (info->key->keyType != NSSLOWKEYRSAKey) { |
|
2851 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
2852 return SECFailure; |
|
2853 } |
|
2854 |
|
2855 return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest, |
|
2856 digestLen); |
|
2857 } |
|
2858 |
|
2859 SECStatus |
|
2860 RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key, |
|
2861 const unsigned char *sig, unsigned int sigLen, |
|
2862 const unsigned char *digestData, unsigned int digestLen) |
|
2863 { |
|
2864 unsigned char *pkcs1DigestInfoData; |
|
2865 SECItem pkcs1DigestInfo; |
|
2866 SECItem digest; |
|
2867 unsigned int bufferSize; |
|
2868 SECStatus rv; |
|
2869 |
|
2870 /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */ |
|
2871 bufferSize = key->u.rsa.modulus.len; |
|
2872 pkcs1DigestInfoData = PORT_ZAlloc(bufferSize); |
|
2873 if (!pkcs1DigestInfoData) { |
|
2874 PORT_SetError(SEC_ERROR_NO_MEMORY); |
|
2875 return SECFailure; |
|
2876 } |
|
2877 |
|
2878 pkcs1DigestInfo.data = pkcs1DigestInfoData; |
|
2879 pkcs1DigestInfo.len = bufferSize; |
|
2880 |
|
2881 /* decrypt the block */ |
|
2882 rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data, |
|
2883 &pkcs1DigestInfo.len, pkcs1DigestInfo.len, |
|
2884 sig, sigLen); |
|
2885 if (rv != SECSuccess) { |
|
2886 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
|
2887 } else { |
|
2888 digest.data = (PRUint8*) digestData; |
|
2889 digest.len = digestLen; |
|
2890 rv = _SGN_VerifyPKCS1DigestInfo( |
|
2891 digestOid, &digest, &pkcs1DigestInfo, |
|
2892 PR_TRUE /*XXX: unsafeAllowMissingParameters*/); |
|
2893 } |
|
2894 |
|
2895 PORT_Free(pkcs1DigestInfoData); |
|
2896 return rv; |
|
2897 } |
|
2898 |
|
2899 static SECStatus |
|
2900 sftk_RSACheckSign(NSSLOWKEYPublicKey *key, const unsigned char *sig, |
|
2901 unsigned int sigLen, const unsigned char *digest, |
|
2902 unsigned int digestLen) |
|
2903 { |
|
2904 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
2905 if (key->keyType != NSSLOWKEYRSAKey) { |
|
2906 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
2907 return SECFailure; |
|
2908 } |
|
2909 |
|
2910 return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen); |
|
2911 } |
|
2912 |
|
2913 static SECStatus |
|
2914 sftk_RSACheckSignRaw(NSSLOWKEYPublicKey *key, const unsigned char *sig, |
|
2915 unsigned int sigLen, const unsigned char *digest, |
|
2916 unsigned int digestLen) |
|
2917 { |
|
2918 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
2919 if (key->keyType != NSSLOWKEYRSAKey) { |
|
2920 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
2921 return SECFailure; |
|
2922 } |
|
2923 |
|
2924 return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen); |
|
2925 } |
|
2926 |
|
2927 static SECStatus |
|
2928 sftk_RSACheckSignPSS(SFTKHashVerifyInfo *info, const unsigned char *sig, |
|
2929 unsigned int sigLen, const unsigned char *digest, |
|
2930 unsigned int digestLen) |
|
2931 { |
|
2932 HASH_HashType hashAlg; |
|
2933 HASH_HashType maskHashAlg; |
|
2934 CK_RSA_PKCS_PSS_PARAMS *params = (CK_RSA_PKCS_PSS_PARAMS *)info->params; |
|
2935 |
|
2936 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
|
2937 if (info->key->keyType != NSSLOWKEYRSAKey) { |
|
2938 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
2939 return SECFailure; |
|
2940 } |
|
2941 |
|
2942 hashAlg = GetHashTypeFromMechanism(params->hashAlg); |
|
2943 maskHashAlg = GetHashTypeFromMechanism(params->mgf); |
|
2944 |
|
2945 return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, |
|
2946 params->sLen, sig, sigLen, digest, digestLen); |
|
2947 } |
|
2948 |
|
2949 /* NSC_VerifyInit initializes a verification operation, |
|
2950 * where the signature is an appendix to the data, |
|
2951 * and plaintext cannot be recovered from the signature (e.g. DSA) */ |
|
2952 CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession, |
|
2953 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) |
|
2954 { |
|
2955 SFTKSession *session; |
|
2956 SFTKObject *key; |
|
2957 SFTKSessionContext *context; |
|
2958 CK_KEY_TYPE key_type; |
|
2959 CK_RV crv = CKR_OK; |
|
2960 NSSLOWKEYPublicKey *pubKey; |
|
2961 SFTKHashVerifyInfo *info = NULL; |
|
2962 |
|
2963 CHECK_FORK(); |
|
2964 |
|
2965 /* Block Cipher MACing Algorithms use a different Context init method..*/ |
|
2966 crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY); |
|
2967 if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv; |
|
2968 |
|
2969 session = sftk_SessionFromHandle(hSession); |
|
2970 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; |
|
2971 crv = sftk_InitGeneric(session,&context,SFTK_VERIFY,&key,hKey,&key_type, |
|
2972 CKO_PUBLIC_KEY,CKA_VERIFY); |
|
2973 if (crv != CKR_OK) { |
|
2974 sftk_FreeSession(session); |
|
2975 return crv; |
|
2976 } |
|
2977 |
|
2978 context->multi = PR_FALSE; |
|
2979 |
|
2980 #define INIT_RSA_VFY_MECH(mmm) \ |
|
2981 case CKM_ ## mmm ## _RSA_PKCS: \ |
|
2982 context->multi = PR_TRUE; \ |
|
2983 crv = sftk_doSub ## mmm (context); \ |
|
2984 if (crv != CKR_OK) break; \ |
|
2985 context->verify = (SFTKVerify) sftk_hashCheckSign; \ |
|
2986 info = PORT_New(SFTKHashVerifyInfo); \ |
|
2987 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \ |
|
2988 info->hashOid = SEC_OID_ ## mmm ; \ |
|
2989 goto finish_rsa; |
|
2990 |
|
2991 switch(pMechanism->mechanism) { |
|
2992 INIT_RSA_VFY_MECH(MD5) |
|
2993 INIT_RSA_VFY_MECH(MD2) |
|
2994 INIT_RSA_VFY_MECH(SHA1) |
|
2995 INIT_RSA_VFY_MECH(SHA224) |
|
2996 INIT_RSA_VFY_MECH(SHA256) |
|
2997 INIT_RSA_VFY_MECH(SHA384) |
|
2998 INIT_RSA_VFY_MECH(SHA512) |
|
2999 |
|
3000 case CKM_RSA_PKCS: |
|
3001 context->verify = (SFTKVerify) sftk_RSACheckSign; |
|
3002 goto finish_rsa; |
|
3003 case CKM_RSA_X_509: |
|
3004 context->verify = (SFTKVerify) sftk_RSACheckSignRaw; |
|
3005 finish_rsa: |
|
3006 if (key_type != CKK_RSA) { |
|
3007 if (info) PORT_Free(info); |
|
3008 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
3009 break; |
|
3010 } |
|
3011 context->rsa = PR_TRUE; |
|
3012 pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); |
|
3013 if (pubKey == NULL) { |
|
3014 if (info) PORT_Free(info); |
|
3015 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
3016 break; |
|
3017 } |
|
3018 if (info) { |
|
3019 info->key = pubKey; |
|
3020 context->cipherInfo = info; |
|
3021 context->destroy = sftk_Space; |
|
3022 } else { |
|
3023 context->cipherInfo = pubKey; |
|
3024 context->destroy = sftk_Null; |
|
3025 } |
|
3026 break; |
|
3027 case CKM_RSA_PKCS_PSS: |
|
3028 if (key_type != CKK_RSA) { |
|
3029 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
3030 break; |
|
3031 } |
|
3032 context->rsa = PR_TRUE; |
|
3033 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
|
3034 !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)) { |
|
3035 crv = CKR_MECHANISM_PARAM_INVALID; |
|
3036 break; |
|
3037 } |
|
3038 info = PORT_New(SFTKHashVerifyInfo); |
|
3039 if (info == NULL) { |
|
3040 crv = CKR_HOST_MEMORY; |
|
3041 break; |
|
3042 } |
|
3043 info->params = pMechanism->pParameter; |
|
3044 info->key = sftk_GetPubKey(key,CKK_RSA,&crv); |
|
3045 if (info->key == NULL) { |
|
3046 PORT_Free(info); |
|
3047 break; |
|
3048 } |
|
3049 context->cipherInfo = info; |
|
3050 context->destroy = (SFTKDestroy) sftk_Space; |
|
3051 context->verify = (SFTKVerify) sftk_RSACheckSignPSS; |
|
3052 break; |
|
3053 case CKM_DSA_SHA1: |
|
3054 context->multi = PR_TRUE; |
|
3055 crv = sftk_doSubSHA1(context); |
|
3056 if (crv != CKR_OK) break; |
|
3057 /* fall through */ |
|
3058 case CKM_DSA: |
|
3059 if (key_type != CKK_DSA) { |
|
3060 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
3061 break; |
|
3062 } |
|
3063 pubKey = sftk_GetPubKey(key,CKK_DSA,&crv); |
|
3064 if (pubKey == NULL) { |
|
3065 break; |
|
3066 } |
|
3067 context->cipherInfo = pubKey; |
|
3068 context->verify = (SFTKVerify) nsc_DSA_Verify_Stub; |
|
3069 context->destroy = sftk_Null; |
|
3070 break; |
|
3071 #ifndef NSS_DISABLE_ECC |
|
3072 case CKM_ECDSA_SHA1: |
|
3073 context->multi = PR_TRUE; |
|
3074 crv = sftk_doSubSHA1(context); |
|
3075 if (crv != CKR_OK) break; |
|
3076 /* fall through */ |
|
3077 case CKM_ECDSA: |
|
3078 if (key_type != CKK_EC) { |
|
3079 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
3080 break; |
|
3081 } |
|
3082 pubKey = sftk_GetPubKey(key,CKK_EC,&crv); |
|
3083 if (pubKey == NULL) { |
|
3084 crv = CKR_HOST_MEMORY; |
|
3085 break; |
|
3086 } |
|
3087 context->cipherInfo = pubKey; |
|
3088 context->verify = (SFTKVerify) nsc_ECDSAVerifyStub; |
|
3089 context->destroy = sftk_Null; |
|
3090 break; |
|
3091 #endif /* NSS_DISABLE_ECC */ |
|
3092 |
|
3093 INIT_HMAC_MECH(MD2) |
|
3094 INIT_HMAC_MECH(MD5) |
|
3095 INIT_HMAC_MECH(SHA224) |
|
3096 INIT_HMAC_MECH(SHA256) |
|
3097 INIT_HMAC_MECH(SHA384) |
|
3098 INIT_HMAC_MECH(SHA512) |
|
3099 |
|
3100 case CKM_SHA_1_HMAC_GENERAL: |
|
3101 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key, |
|
3102 *(CK_ULONG *)pMechanism->pParameter); |
|
3103 break; |
|
3104 case CKM_SHA_1_HMAC: |
|
3105 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); |
|
3106 break; |
|
3107 |
|
3108 case CKM_SSL3_MD5_MAC: |
|
3109 crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key, |
|
3110 *(CK_ULONG *)pMechanism->pParameter); |
|
3111 break; |
|
3112 case CKM_SSL3_SHA1_MAC: |
|
3113 crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key, |
|
3114 *(CK_ULONG *)pMechanism->pParameter); |
|
3115 break; |
|
3116 case CKM_TLS_PRF_GENERAL: |
|
3117 crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL); |
|
3118 break; |
|
3119 case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
|
3120 crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256); |
|
3121 break; |
|
3122 |
|
3123 default: |
|
3124 crv = CKR_MECHANISM_INVALID; |
|
3125 break; |
|
3126 } |
|
3127 |
|
3128 if (crv != CKR_OK) { |
|
3129 if (info) PORT_Free(info); |
|
3130 sftk_FreeContext(context); |
|
3131 sftk_FreeSession(session); |
|
3132 return crv; |
|
3133 } |
|
3134 sftk_SetContextByType(session, SFTK_VERIFY, context); |
|
3135 sftk_FreeSession(session); |
|
3136 return CKR_OK; |
|
3137 } |
|
3138 |
|
3139 /* NSC_Verify verifies a signature in a single-part operation, |
|
3140 * where the signature is an appendix to the data, |
|
3141 * and plaintext cannot be recovered from the signature */ |
|
3142 CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
|
3143 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
|
3144 { |
|
3145 SFTKSession *session; |
|
3146 SFTKSessionContext *context; |
|
3147 CK_RV crv; |
|
3148 |
|
3149 CHECK_FORK(); |
|
3150 |
|
3151 /* make sure we're legal */ |
|
3152 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_FALSE,&session); |
|
3153 if (crv != CKR_OK) return crv; |
|
3154 |
|
3155 /* multi part Verifying are completely implemented by VerifyUpdate and |
|
3156 * VerifyFinal */ |
|
3157 if (context->multi) { |
|
3158 /* VerifyFinal can't follow failed VerifyUpdate */ |
|
3159 if( CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen))) |
|
3160 crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen); |
|
3161 } else { |
|
3162 if (SECSuccess != (*context->verify)(context->cipherInfo,pSignature, |
|
3163 ulSignatureLen, pData, ulDataLen)) |
|
3164 crv = sftk_MapCryptError(PORT_GetError()); |
|
3165 |
|
3166 sftk_TerminateOp( session, SFTK_VERIFY, context ); |
|
3167 } |
|
3168 sftk_FreeSession(session); |
|
3169 return crv; |
|
3170 } |
|
3171 |
|
3172 |
|
3173 /* NSC_VerifyUpdate continues a multiple-part verification operation, |
|
3174 * where the signature is an appendix to the data, |
|
3175 * and plaintext cannot be recovered from the signature |
|
3176 * |
|
3177 * A call which results in an error terminates the operation [PKCS#11,v2.11] |
|
3178 */ |
|
3179 CK_RV NSC_VerifyUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
|
3180 CK_ULONG ulPartLen) |
|
3181 { |
|
3182 CHECK_FORK(); |
|
3183 return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY); |
|
3184 } |
|
3185 |
|
3186 |
|
3187 /* NSC_VerifyFinal finishes a multiple-part verification operation, |
|
3188 * checking the signature. */ |
|
3189 CK_RV NSC_VerifyFinal(CK_SESSION_HANDLE hSession, |
|
3190 CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen) |
|
3191 { |
|
3192 SFTKSession *session; |
|
3193 SFTKSessionContext *context; |
|
3194 CK_RV crv; |
|
3195 |
|
3196 CHECK_FORK(); |
|
3197 |
|
3198 if (!pSignature) |
|
3199 return CKR_ARGUMENTS_BAD; |
|
3200 |
|
3201 /* make sure we're legal */ |
|
3202 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_TRUE,&session); |
|
3203 if (crv != CKR_OK) |
|
3204 return crv; |
|
3205 |
|
3206 if (context->hashInfo) { |
|
3207 unsigned int digestLen; |
|
3208 unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
|
3209 |
|
3210 (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
|
3211 if( SECSuccess != (context->verify)(context->cipherInfo, pSignature, |
|
3212 ulSignatureLen, tmpbuf, digestLen)) |
|
3213 crv = sftk_MapCryptError(PORT_GetError()); |
|
3214 } else if (ulSignatureLen != context->macSize) { |
|
3215 /* must be block cipher MACing */ |
|
3216 crv = CKR_SIGNATURE_LEN_RANGE; |
|
3217 } else if (CKR_OK == (crv = sftk_MACFinal(context))) { |
|
3218 if (PORT_Memcmp(pSignature, context->macBuf, ulSignatureLen)) |
|
3219 crv = CKR_SIGNATURE_INVALID; |
|
3220 } |
|
3221 |
|
3222 sftk_TerminateOp( session, SFTK_VERIFY, context ); |
|
3223 sftk_FreeSession(session); |
|
3224 return crv; |
|
3225 |
|
3226 } |
|
3227 |
|
3228 /* |
|
3229 ************** Crypto Functions: Verify Recover ************************ |
|
3230 */ |
|
3231 static SECStatus |
|
3232 sftk_RSACheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data, |
|
3233 unsigned int *dataLen, unsigned int maxDataLen, |
|
3234 const unsigned char *sig, unsigned int sigLen) |
|
3235 { |
|
3236 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
3237 if (key->keyType != NSSLOWKEYRSAKey) { |
|
3238 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
3239 return SECFailure; |
|
3240 } |
|
3241 |
|
3242 return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen, |
|
3243 sig, sigLen); |
|
3244 } |
|
3245 |
|
3246 static SECStatus |
|
3247 sftk_RSACheckSignRecoverRaw(NSSLOWKEYPublicKey *key, unsigned char *data, |
|
3248 unsigned int *dataLen, unsigned int maxDataLen, |
|
3249 const unsigned char *sig, unsigned int sigLen) |
|
3250 { |
|
3251 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
|
3252 if (key->keyType != NSSLOWKEYRSAKey) { |
|
3253 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
3254 return SECFailure; |
|
3255 } |
|
3256 |
|
3257 return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen, |
|
3258 sig, sigLen); |
|
3259 } |
|
3260 |
|
3261 /* NSC_VerifyRecoverInit initializes a signature verification operation, |
|
3262 * where the data is recovered from the signature. |
|
3263 * E.g. Decryption with the user's public key */ |
|
3264 CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, |
|
3265 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) |
|
3266 { |
|
3267 SFTKSession *session; |
|
3268 SFTKObject *key; |
|
3269 SFTKSessionContext *context; |
|
3270 CK_KEY_TYPE key_type; |
|
3271 CK_RV crv = CKR_OK; |
|
3272 NSSLOWKEYPublicKey *pubKey; |
|
3273 |
|
3274 CHECK_FORK(); |
|
3275 |
|
3276 session = sftk_SessionFromHandle(hSession); |
|
3277 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; |
|
3278 crv = sftk_InitGeneric(session,&context,SFTK_VERIFY_RECOVER, |
|
3279 &key,hKey,&key_type,CKO_PUBLIC_KEY,CKA_VERIFY_RECOVER); |
|
3280 if (crv != CKR_OK) { |
|
3281 sftk_FreeSession(session); |
|
3282 return crv; |
|
3283 } |
|
3284 |
|
3285 context->multi = PR_TRUE; |
|
3286 |
|
3287 switch(pMechanism->mechanism) { |
|
3288 case CKM_RSA_PKCS: |
|
3289 case CKM_RSA_X_509: |
|
3290 if (key_type != CKK_RSA) { |
|
3291 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
3292 break; |
|
3293 } |
|
3294 context->multi = PR_FALSE; |
|
3295 context->rsa = PR_TRUE; |
|
3296 pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); |
|
3297 if (pubKey == NULL) { |
|
3298 break; |
|
3299 } |
|
3300 context->cipherInfo = pubKey; |
|
3301 context->update = (SFTKCipher) (pMechanism->mechanism == CKM_RSA_X_509 |
|
3302 ? sftk_RSACheckSignRecoverRaw : sftk_RSACheckSignRecover); |
|
3303 context->destroy = sftk_Null; |
|
3304 break; |
|
3305 default: |
|
3306 crv = CKR_MECHANISM_INVALID; |
|
3307 break; |
|
3308 } |
|
3309 |
|
3310 if (crv != CKR_OK) { |
|
3311 PORT_Free(context); |
|
3312 sftk_FreeSession(session); |
|
3313 return crv; |
|
3314 } |
|
3315 sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context); |
|
3316 sftk_FreeSession(session); |
|
3317 return CKR_OK; |
|
3318 } |
|
3319 |
|
3320 |
|
3321 /* NSC_VerifyRecover verifies a signature in a single-part operation, |
|
3322 * where the data is recovered from the signature. |
|
3323 * E.g. Decryption with the user's public key */ |
|
3324 CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession, |
|
3325 CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen, |
|
3326 CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen) |
|
3327 { |
|
3328 SFTKSession *session; |
|
3329 SFTKSessionContext *context; |
|
3330 unsigned int outlen; |
|
3331 unsigned int maxoutlen = *pulDataLen; |
|
3332 CK_RV crv; |
|
3333 SECStatus rv; |
|
3334 |
|
3335 CHECK_FORK(); |
|
3336 |
|
3337 /* make sure we're legal */ |
|
3338 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY_RECOVER, |
|
3339 PR_FALSE,&session); |
|
3340 if (crv != CKR_OK) return crv; |
|
3341 if (pData == NULL) { |
|
3342 /* to return the actual size, we need to do the decrypt, just return |
|
3343 * the max size, which is the size of the input signature. */ |
|
3344 *pulDataLen = ulSignatureLen; |
|
3345 rv = SECSuccess; |
|
3346 goto finish; |
|
3347 } |
|
3348 |
|
3349 rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
|
3350 pSignature, ulSignatureLen); |
|
3351 *pulDataLen = (CK_ULONG) outlen; |
|
3352 |
|
3353 sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context); |
|
3354 finish: |
|
3355 sftk_FreeSession(session); |
|
3356 return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError()); |
|
3357 } |
|
3358 |
|
3359 /* |
|
3360 **************************** Random Functions: ************************ |
|
3361 */ |
|
3362 |
|
3363 /* NSC_SeedRandom mixes additional seed material into the token's random number |
|
3364 * generator. */ |
|
3365 CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, |
|
3366 CK_ULONG ulSeedLen) |
|
3367 { |
|
3368 SECStatus rv; |
|
3369 |
|
3370 CHECK_FORK(); |
|
3371 |
|
3372 rv = RNG_RandomUpdate(pSeed, ulSeedLen); |
|
3373 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
|
3374 } |
|
3375 |
|
3376 /* NSC_GenerateRandom generates random data. */ |
|
3377 CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession, |
|
3378 CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) |
|
3379 { |
|
3380 SECStatus rv; |
|
3381 |
|
3382 CHECK_FORK(); |
|
3383 |
|
3384 rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen); |
|
3385 /* |
|
3386 * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't |
|
3387 * seeded with enough entropy. |
|
3388 */ |
|
3389 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
|
3390 } |
|
3391 |
|
3392 /* |
|
3393 **************************** Key Functions: ************************ |
|
3394 */ |
|
3395 |
|
3396 |
|
3397 /* |
|
3398 * generate a password based encryption key. This code uses |
|
3399 * PKCS5 to do the work. |
|
3400 */ |
|
3401 static CK_RV |
|
3402 nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, |
|
3403 void *buf, CK_ULONG *key_length, PRBool faulty3DES) |
|
3404 { |
|
3405 SECItem *pbe_key = NULL, iv, pwitem; |
|
3406 CK_PBE_PARAMS *pbe_params = NULL; |
|
3407 CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; |
|
3408 |
|
3409 *key_length = 0; |
|
3410 iv.data = NULL; iv.len = 0; |
|
3411 |
|
3412 if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
|
3413 pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; |
|
3414 pwitem.data = (unsigned char *)pbkd2_params->pPassword; |
|
3415 /* was this a typo in the PKCS #11 spec? */ |
|
3416 pwitem.len = *pbkd2_params->ulPasswordLen; |
|
3417 } else { |
|
3418 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
|
3419 pwitem.data = (unsigned char *)pbe_params->pPassword; |
|
3420 pwitem.len = pbe_params->ulPasswordLen; |
|
3421 } |
|
3422 pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); |
|
3423 if (pbe_key == NULL) { |
|
3424 return CKR_HOST_MEMORY; |
|
3425 } |
|
3426 |
|
3427 PORT_Memcpy(buf, pbe_key->data, pbe_key->len); |
|
3428 *key_length = pbe_key->len; |
|
3429 SECITEM_ZfreeItem(pbe_key, PR_TRUE); |
|
3430 pbe_key = NULL; |
|
3431 |
|
3432 if (iv.data) { |
|
3433 if (pbe_params && pbe_params->pInitVector != NULL) { |
|
3434 PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); |
|
3435 } |
|
3436 PORT_Free(iv.data); |
|
3437 } |
|
3438 |
|
3439 return CKR_OK; |
|
3440 } |
|
3441 |
|
3442 /* |
|
3443 * this is coded for "full" support. These selections will be limitted to |
|
3444 * the official subset by freebl. |
|
3445 */ |
|
3446 static unsigned int |
|
3447 sftk_GetSubPrimeFromPrime(unsigned int primeBits) |
|
3448 { |
|
3449 if (primeBits <= 1024) { |
|
3450 return 160; |
|
3451 } else if (primeBits <= 2048) { |
|
3452 return 224; |
|
3453 } else if (primeBits <= 3072) { |
|
3454 return 256; |
|
3455 } else if (primeBits <= 7680) { |
|
3456 return 384; |
|
3457 } else { |
|
3458 return 512; |
|
3459 } |
|
3460 } |
|
3461 |
|
3462 static CK_RV |
|
3463 nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) |
|
3464 { |
|
3465 SFTKAttribute *attribute; |
|
3466 CK_ULONG counter; |
|
3467 unsigned int seedBits = 0; |
|
3468 unsigned int subprimeBits = 0; |
|
3469 unsigned int primeBits; |
|
3470 unsigned int j = 8; /* default to 1024 bits */ |
|
3471 CK_RV crv = CKR_OK; |
|
3472 PQGParams *params = NULL; |
|
3473 PQGVerify *vfy = NULL; |
|
3474 SECStatus rv; |
|
3475 |
|
3476 attribute = sftk_FindAttribute(key, CKA_PRIME_BITS); |
|
3477 if (attribute == NULL) { |
|
3478 return CKR_TEMPLATE_INCOMPLETE; |
|
3479 } |
|
3480 primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; |
|
3481 sftk_FreeAttribute(attribute); |
|
3482 if (primeBits < 1024) { |
|
3483 j = PQG_PBITS_TO_INDEX(primeBits); |
|
3484 if (j == (unsigned int)-1) { |
|
3485 return CKR_ATTRIBUTE_VALUE_INVALID; |
|
3486 } |
|
3487 } |
|
3488 |
|
3489 attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS); |
|
3490 if (attribute != NULL) { |
|
3491 seedBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; |
|
3492 sftk_FreeAttribute(attribute); |
|
3493 } |
|
3494 |
|
3495 attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS); |
|
3496 if (attribute != NULL) { |
|
3497 subprimeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; |
|
3498 sftk_FreeAttribute(attribute); |
|
3499 } |
|
3500 |
|
3501 sftk_DeleteAttributeType(key,CKA_PRIME_BITS); |
|
3502 sftk_DeleteAttributeType(key,CKA_SUBPRIME_BITS); |
|
3503 sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS); |
|
3504 |
|
3505 /* use the old PQG interface if we have old input data */ |
|
3506 if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) { |
|
3507 if (seedBits == 0) { |
|
3508 rv = PQG_ParamGen(j, ¶ms, &vfy); |
|
3509 } else { |
|
3510 rv = PQG_ParamGenSeedLen(j,seedBits/8, ¶ms, &vfy); |
|
3511 } |
|
3512 } else { |
|
3513 if (subprimeBits == 0) { |
|
3514 subprimeBits = sftk_GetSubPrimeFromPrime(primeBits); |
|
3515 } |
|
3516 if (seedBits == 0) { |
|
3517 seedBits = primeBits; |
|
3518 } |
|
3519 rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits/8, ¶ms, &vfy); |
|
3520 } |
|
3521 |
|
3522 |
|
3523 |
|
3524 if (rv != SECSuccess) { |
|
3525 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
3526 sftk_fatalError = PR_TRUE; |
|
3527 } |
|
3528 return sftk_MapCryptError(PORT_GetError()); |
|
3529 } |
|
3530 crv = sftk_AddAttributeType(key,CKA_PRIME, |
|
3531 params->prime.data, params->prime.len); |
|
3532 if (crv != CKR_OK) goto loser; |
|
3533 crv = sftk_AddAttributeType(key,CKA_SUBPRIME, |
|
3534 params->subPrime.data, params->subPrime.len); |
|
3535 if (crv != CKR_OK) goto loser; |
|
3536 crv = sftk_AddAttributeType(key,CKA_BASE, |
|
3537 params->base.data, params->base.len); |
|
3538 if (crv != CKR_OK) goto loser; |
|
3539 counter = vfy->counter; |
|
3540 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_COUNTER, |
|
3541 &counter, sizeof(counter)); |
|
3542 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_SEED, |
|
3543 vfy->seed.data, vfy->seed.len); |
|
3544 if (crv != CKR_OK) goto loser; |
|
3545 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_H, |
|
3546 vfy->h.data, vfy->h.len); |
|
3547 if (crv != CKR_OK) goto loser; |
|
3548 |
|
3549 loser: |
|
3550 PQG_DestroyParams(params); |
|
3551 |
|
3552 if (vfy) { |
|
3553 PQG_DestroyVerify(vfy); |
|
3554 } |
|
3555 return crv; |
|
3556 } |
|
3557 |
|
3558 |
|
3559 static CK_RV |
|
3560 nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, |
|
3561 CK_ULONG *key_length) |
|
3562 { |
|
3563 CK_RV crv = CKR_OK; |
|
3564 |
|
3565 switch (mechanism) { |
|
3566 case CKM_RC2_KEY_GEN: |
|
3567 *key_type = CKK_RC2; |
|
3568 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; |
|
3569 break; |
|
3570 #if NSS_SOFTOKEN_DOES_RC5 |
|
3571 case CKM_RC5_KEY_GEN: |
|
3572 *key_type = CKK_RC5; |
|
3573 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; |
|
3574 break; |
|
3575 #endif |
|
3576 case CKM_RC4_KEY_GEN: |
|
3577 *key_type = CKK_RC4; |
|
3578 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; |
|
3579 break; |
|
3580 case CKM_GENERIC_SECRET_KEY_GEN: |
|
3581 *key_type = CKK_GENERIC_SECRET; |
|
3582 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; |
|
3583 break; |
|
3584 case CKM_CDMF_KEY_GEN: |
|
3585 *key_type = CKK_CDMF; |
|
3586 *key_length = 8; |
|
3587 break; |
|
3588 case CKM_DES_KEY_GEN: |
|
3589 *key_type = CKK_DES; |
|
3590 *key_length = 8; |
|
3591 break; |
|
3592 case CKM_DES2_KEY_GEN: |
|
3593 *key_type = CKK_DES2; |
|
3594 *key_length = 16; |
|
3595 break; |
|
3596 case CKM_DES3_KEY_GEN: |
|
3597 *key_type = CKK_DES3; |
|
3598 *key_length = 24; |
|
3599 break; |
|
3600 case CKM_SEED_KEY_GEN: |
|
3601 *key_type = CKK_SEED; |
|
3602 *key_length = 16; |
|
3603 break; |
|
3604 case CKM_CAMELLIA_KEY_GEN: |
|
3605 *key_type = CKK_CAMELLIA; |
|
3606 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; |
|
3607 break; |
|
3608 case CKM_AES_KEY_GEN: |
|
3609 *key_type = CKK_AES; |
|
3610 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; |
|
3611 break; |
|
3612 default: |
|
3613 PORT_Assert(0); |
|
3614 crv = CKR_MECHANISM_INVALID; |
|
3615 break; |
|
3616 } |
|
3617 |
|
3618 return crv; |
|
3619 } |
|
3620 |
|
3621 CK_RV |
|
3622 nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) |
|
3623 { |
|
3624 SECItem salt; |
|
3625 CK_PBE_PARAMS *pbe_params = NULL; |
|
3626 NSSPKCS5PBEParameter *params; |
|
3627 PLArenaPool *arena = NULL; |
|
3628 SECStatus rv; |
|
3629 |
|
3630 *pbe = NULL; |
|
3631 |
|
3632 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); |
|
3633 if (arena == NULL) { |
|
3634 return CKR_HOST_MEMORY; |
|
3635 } |
|
3636 |
|
3637 params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena, |
|
3638 sizeof(NSSPKCS5PBEParameter)); |
|
3639 if (params == NULL) { |
|
3640 PORT_FreeArena(arena,PR_TRUE); |
|
3641 return CKR_HOST_MEMORY; |
|
3642 } |
|
3643 |
|
3644 params->poolp = arena; |
|
3645 params->ivLen = 0; |
|
3646 params->pbeType = NSSPKCS5_PKCS12_V2; |
|
3647 params->hashType = HASH_AlgSHA1; |
|
3648 params->encAlg = SEC_OID_SHA1; /* any invalid value */ |
|
3649 params->is2KeyDES = PR_FALSE; |
|
3650 params->keyID = pbeBitGenIntegrityKey; |
|
3651 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
|
3652 params->iter = pbe_params->ulIteration; |
|
3653 |
|
3654 salt.data = (unsigned char *)pbe_params->pSalt; |
|
3655 salt.len = (unsigned int)pbe_params->ulSaltLen; |
|
3656 rv = SECITEM_CopyItem(arena,¶ms->salt,&salt); |
|
3657 if (rv != SECSuccess) { |
|
3658 PORT_FreeArena(arena,PR_TRUE); |
|
3659 return CKR_HOST_MEMORY; |
|
3660 } |
|
3661 switch (pMechanism->mechanism) { |
|
3662 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: |
|
3663 case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
|
3664 params->hashType = HASH_AlgSHA1; |
|
3665 params->keyLen = 20; |
|
3666 break; |
|
3667 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: |
|
3668 params->hashType = HASH_AlgMD5; |
|
3669 params->keyLen = 16; |
|
3670 break; |
|
3671 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: |
|
3672 params->hashType = HASH_AlgMD2; |
|
3673 params->keyLen = 16; |
|
3674 break; |
|
3675 default: |
|
3676 PORT_FreeArena(arena,PR_TRUE); |
|
3677 return CKR_MECHANISM_INVALID; |
|
3678 } |
|
3679 *pbe = params; |
|
3680 return CKR_OK; |
|
3681 } |
|
3682 |
|
3683 /* maybe this should be table driven? */ |
|
3684 static CK_RV |
|
3685 nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, |
|
3686 CK_KEY_TYPE *key_type, CK_ULONG *key_length) |
|
3687 { |
|
3688 CK_RV crv = CKR_OK; |
|
3689 SECOidData *oid; |
|
3690 CK_PBE_PARAMS *pbe_params = NULL; |
|
3691 NSSPKCS5PBEParameter *params = NULL; |
|
3692 CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; |
|
3693 SECItem salt; |
|
3694 CK_ULONG iteration = 0; |
|
3695 |
|
3696 *pbe = NULL; |
|
3697 |
|
3698 oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); |
|
3699 if (oid == NULL) { |
|
3700 return CKR_MECHANISM_INVALID; |
|
3701 } |
|
3702 |
|
3703 if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
|
3704 pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; |
|
3705 if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) { |
|
3706 return CKR_MECHANISM_PARAM_INVALID; |
|
3707 } |
|
3708 salt.data = (unsigned char *)pbkd2_params->pSaltSourceData; |
|
3709 salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen; |
|
3710 iteration = pbkd2_params->iterations; |
|
3711 } else { |
|
3712 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
|
3713 salt.data = (unsigned char *)pbe_params->pSalt; |
|
3714 salt.len = (unsigned int)pbe_params->ulSaltLen; |
|
3715 iteration = pbe_params->ulIteration; |
|
3716 } |
|
3717 params=nsspkcs5_NewParam(oid->offset, &salt, iteration); |
|
3718 if (params == NULL) { |
|
3719 return CKR_MECHANISM_INVALID; |
|
3720 } |
|
3721 |
|
3722 switch (params->encAlg) { |
|
3723 case SEC_OID_DES_CBC: |
|
3724 *key_type = CKK_DES; |
|
3725 *key_length = params->keyLen; |
|
3726 break; |
|
3727 case SEC_OID_DES_EDE3_CBC: |
|
3728 *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; |
|
3729 *key_length = params->keyLen; |
|
3730 break; |
|
3731 case SEC_OID_RC2_CBC: |
|
3732 *key_type = CKK_RC2; |
|
3733 *key_length = params->keyLen; |
|
3734 break; |
|
3735 case SEC_OID_RC4: |
|
3736 *key_type = CKK_RC4; |
|
3737 *key_length = params->keyLen; |
|
3738 break; |
|
3739 case SEC_OID_PKCS5_PBKDF2: |
|
3740 /* sigh, PKCS #11 currently only defines SHA1 for the KDF hash type. |
|
3741 * we do the check here because this where we would handle multiple |
|
3742 * hash types in the future */ |
|
3743 if (pbkd2_params == NULL || |
|
3744 pbkd2_params->prf != CKP_PKCS5_PBKD2_HMAC_SHA1) { |
|
3745 crv = CKR_MECHANISM_PARAM_INVALID; |
|
3746 break; |
|
3747 } |
|
3748 /* key type must already be set */ |
|
3749 if (*key_type == CKK_INVALID_KEY_TYPE) { |
|
3750 crv = CKR_TEMPLATE_INCOMPLETE; |
|
3751 break; |
|
3752 } |
|
3753 /* PBKDF2 needs to calculate the key length from the other parameters |
|
3754 */ |
|
3755 if (*key_length == 0) { |
|
3756 *key_length = sftk_MapKeySize(*key_type); |
|
3757 } |
|
3758 if (*key_length == 0) { |
|
3759 crv = CKR_TEMPLATE_INCOMPLETE; |
|
3760 break; |
|
3761 } |
|
3762 params->keyLen = *key_length; |
|
3763 break; |
|
3764 default: |
|
3765 crv = CKR_MECHANISM_INVALID; |
|
3766 nsspkcs5_DestroyPBEParameter(params); |
|
3767 break; |
|
3768 } |
|
3769 if (crv == CKR_OK) { |
|
3770 *pbe = params; |
|
3771 } |
|
3772 return crv; |
|
3773 } |
|
3774 |
|
3775 /* NSC_GenerateKey generates a secret key, creating a new key object. */ |
|
3776 CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, |
|
3777 CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, |
|
3778 CK_OBJECT_HANDLE_PTR phKey) |
|
3779 { |
|
3780 SFTKObject *key; |
|
3781 SFTKSession *session; |
|
3782 PRBool checkWeak = PR_FALSE; |
|
3783 CK_ULONG key_length = 0; |
|
3784 CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE; |
|
3785 CK_OBJECT_CLASS objclass = CKO_SECRET_KEY; |
|
3786 CK_RV crv = CKR_OK; |
|
3787 CK_BBOOL cktrue = CK_TRUE; |
|
3788 int i; |
|
3789 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
|
3790 unsigned char buf[MAX_KEY_LEN]; |
|
3791 enum {nsc_pbe, nsc_ssl, nsc_bulk, nsc_param, nsc_jpake} key_gen_type; |
|
3792 NSSPKCS5PBEParameter *pbe_param; |
|
3793 SSL3RSAPreMasterSecret *rsa_pms; |
|
3794 CK_VERSION *version; |
|
3795 /* in very old versions of NSS, there were implementation errors with key |
|
3796 * generation methods. We want to beable to read these, but not |
|
3797 * produce them any more. The affected algorithm was 3DES. |
|
3798 */ |
|
3799 PRBool faultyPBE3DES = PR_FALSE; |
|
3800 HASH_HashType hashType; |
|
3801 |
|
3802 CHECK_FORK(); |
|
3803 |
|
3804 if (!slot) { |
|
3805 return CKR_SESSION_HANDLE_INVALID; |
|
3806 } |
|
3807 /* |
|
3808 * now lets create an object to hang the attributes off of |
|
3809 */ |
|
3810 key = sftk_NewObject(slot); /* fill in the handle later */ |
|
3811 if (key == NULL) { |
|
3812 return CKR_HOST_MEMORY; |
|
3813 } |
|
3814 |
|
3815 /* |
|
3816 * load the template values into the object |
|
3817 */ |
|
3818 for (i=0; i < (int) ulCount; i++) { |
|
3819 if (pTemplate[i].type == CKA_VALUE_LEN) { |
|
3820 key_length = *(CK_ULONG *)pTemplate[i].pValue; |
|
3821 continue; |
|
3822 } |
|
3823 /* some algorithms need keytype specified */ |
|
3824 if (pTemplate[i].type == CKA_KEY_TYPE) { |
|
3825 key_type = *(CK_ULONG *)pTemplate[i].pValue; |
|
3826 continue; |
|
3827 } |
|
3828 |
|
3829 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); |
|
3830 if (crv != CKR_OK) break; |
|
3831 } |
|
3832 if (crv != CKR_OK) { |
|
3833 sftk_FreeObject(key); |
|
3834 return crv; |
|
3835 } |
|
3836 |
|
3837 /* make sure we don't have any class, key_type, or value fields */ |
|
3838 sftk_DeleteAttributeType(key,CKA_CLASS); |
|
3839 sftk_DeleteAttributeType(key,CKA_KEY_TYPE); |
|
3840 sftk_DeleteAttributeType(key,CKA_VALUE); |
|
3841 |
|
3842 /* Now Set up the parameters to generate the key (based on mechanism) */ |
|
3843 key_gen_type = nsc_bulk; /* bulk key by default */ |
|
3844 switch (pMechanism->mechanism) { |
|
3845 case CKM_CDMF_KEY_GEN: |
|
3846 case CKM_DES_KEY_GEN: |
|
3847 case CKM_DES2_KEY_GEN: |
|
3848 case CKM_DES3_KEY_GEN: |
|
3849 checkWeak = PR_TRUE; |
|
3850 /* fall through */ |
|
3851 case CKM_RC2_KEY_GEN: |
|
3852 case CKM_RC4_KEY_GEN: |
|
3853 case CKM_GENERIC_SECRET_KEY_GEN: |
|
3854 case CKM_SEED_KEY_GEN: |
|
3855 case CKM_CAMELLIA_KEY_GEN: |
|
3856 case CKM_AES_KEY_GEN: |
|
3857 #if NSS_SOFTOKEN_DOES_RC5 |
|
3858 case CKM_RC5_KEY_GEN: |
|
3859 #endif |
|
3860 crv = nsc_SetupBulkKeyGen(pMechanism->mechanism,&key_type,&key_length); |
|
3861 break; |
|
3862 case CKM_SSL3_PRE_MASTER_KEY_GEN: |
|
3863 key_type = CKK_GENERIC_SECRET; |
|
3864 key_length = 48; |
|
3865 key_gen_type = nsc_ssl; |
|
3866 break; |
|
3867 case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
|
3868 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: |
|
3869 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: |
|
3870 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: |
|
3871 key_gen_type = nsc_pbe; |
|
3872 key_type = CKK_GENERIC_SECRET; |
|
3873 crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); |
|
3874 break; |
|
3875 case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: |
|
3876 faultyPBE3DES = PR_TRUE; |
|
3877 /* fall through */ |
|
3878 case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: |
|
3879 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: |
|
3880 case CKM_NETSCAPE_PBE_SHA1_DES_CBC: |
|
3881 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: |
|
3882 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: |
|
3883 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: |
|
3884 case CKM_PBE_SHA1_DES3_EDE_CBC: |
|
3885 case CKM_PBE_SHA1_DES2_EDE_CBC: |
|
3886 case CKM_PBE_SHA1_RC2_128_CBC: |
|
3887 case CKM_PBE_SHA1_RC2_40_CBC: |
|
3888 case CKM_PBE_SHA1_RC4_128: |
|
3889 case CKM_PBE_SHA1_RC4_40: |
|
3890 case CKM_PBE_MD5_DES_CBC: |
|
3891 case CKM_PBE_MD2_DES_CBC: |
|
3892 case CKM_PKCS5_PBKD2: |
|
3893 key_gen_type = nsc_pbe; |
|
3894 crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type, &key_length); |
|
3895 break; |
|
3896 case CKM_DSA_PARAMETER_GEN: |
|
3897 key_gen_type = nsc_param; |
|
3898 key_type = CKK_DSA; |
|
3899 objclass = CKO_KG_PARAMETERS; |
|
3900 crv = CKR_OK; |
|
3901 break; |
|
3902 case CKM_NSS_JPAKE_ROUND1_SHA1: hashType = HASH_AlgSHA1; goto jpake1; |
|
3903 case CKM_NSS_JPAKE_ROUND1_SHA256: hashType = HASH_AlgSHA256; goto jpake1; |
|
3904 case CKM_NSS_JPAKE_ROUND1_SHA384: hashType = HASH_AlgSHA384; goto jpake1; |
|
3905 case CKM_NSS_JPAKE_ROUND1_SHA512: hashType = HASH_AlgSHA512; goto jpake1; |
|
3906 jpake1: |
|
3907 key_gen_type = nsc_jpake; |
|
3908 key_type = CKK_NSS_JPAKE_ROUND1; |
|
3909 objclass = CKO_PRIVATE_KEY; |
|
3910 if (pMechanism->pParameter == NULL || |
|
3911 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) { |
|
3912 crv = CKR_MECHANISM_PARAM_INVALID; |
|
3913 break; |
|
3914 } |
|
3915 if (sftk_isTrue(key, CKA_TOKEN)) { |
|
3916 crv = CKR_TEMPLATE_INCONSISTENT; |
|
3917 break; |
|
3918 } |
|
3919 crv = CKR_OK; |
|
3920 break; |
|
3921 default: |
|
3922 crv = CKR_MECHANISM_INVALID; |
|
3923 break; |
|
3924 } |
|
3925 |
|
3926 /* make sure we aren't going to overflow the buffer */ |
|
3927 if (sizeof(buf) < key_length) { |
|
3928 /* someone is getting pretty optimistic about how big their key can |
|
3929 * be... */ |
|
3930 crv = CKR_TEMPLATE_INCONSISTENT; |
|
3931 } |
|
3932 |
|
3933 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } |
|
3934 |
|
3935 /* if there was no error, |
|
3936 * key_type *MUST* be set in the switch statement above */ |
|
3937 PORT_Assert( key_type != CKK_INVALID_KEY_TYPE ); |
|
3938 |
|
3939 /* |
|
3940 * now to the actual key gen. |
|
3941 */ |
|
3942 switch (key_gen_type) { |
|
3943 case nsc_pbe: |
|
3944 crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, |
|
3945 faultyPBE3DES); |
|
3946 nsspkcs5_DestroyPBEParameter(pbe_param); |
|
3947 break; |
|
3948 case nsc_ssl: |
|
3949 rsa_pms = (SSL3RSAPreMasterSecret *)buf; |
|
3950 version = (CK_VERSION *)pMechanism->pParameter; |
|
3951 rsa_pms->client_version[0] = version->major; |
|
3952 rsa_pms->client_version[1] = version->minor; |
|
3953 crv = |
|
3954 NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random)); |
|
3955 break; |
|
3956 case nsc_bulk: |
|
3957 /* get the key, check for weak keys and repeat if found */ |
|
3958 do { |
|
3959 crv = NSC_GenerateRandom(0, buf, key_length); |
|
3960 } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf,key_type)); |
|
3961 break; |
|
3962 case nsc_param: |
|
3963 /* generate parameters */ |
|
3964 *buf = 0; |
|
3965 crv = nsc_parameter_gen(key_type,key); |
|
3966 break; |
|
3967 case nsc_jpake: |
|
3968 crv = jpake_Round1(hashType, |
|
3969 (CK_NSS_JPAKERound1Params *) pMechanism->pParameter, |
|
3970 key); |
|
3971 break; |
|
3972 } |
|
3973 |
|
3974 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } |
|
3975 |
|
3976 /* Add the class, key_type, and value */ |
|
3977 crv = sftk_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS)); |
|
3978 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } |
|
3979 crv = sftk_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE)); |
|
3980 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } |
|
3981 if (key_length != 0) { |
|
3982 crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length); |
|
3983 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } |
|
3984 } |
|
3985 |
|
3986 /* get the session */ |
|
3987 session = sftk_SessionFromHandle(hSession); |
|
3988 if (session == NULL) { |
|
3989 sftk_FreeObject(key); |
|
3990 return CKR_SESSION_HANDLE_INVALID; |
|
3991 } |
|
3992 |
|
3993 /* |
|
3994 * handle the base object stuff |
|
3995 */ |
|
3996 crv = sftk_handleObject(key,session); |
|
3997 sftk_FreeSession(session); |
|
3998 if (sftk_isTrue(key,CKA_SENSITIVE)) { |
|
3999 sftk_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL)); |
|
4000 } |
|
4001 if (!sftk_isTrue(key,CKA_EXTRACTABLE)) { |
|
4002 sftk_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL)); |
|
4003 } |
|
4004 |
|
4005 *phKey = key->handle; |
|
4006 sftk_FreeObject(key); |
|
4007 return crv; |
|
4008 } |
|
4009 |
|
4010 #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ |
|
4011 #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ |
|
4012 |
|
4013 /* |
|
4014 * FIPS 140-2 pairwise consistency check utilized to validate key pair. |
|
4015 * |
|
4016 * This function returns |
|
4017 * CKR_OK if pairwise consistency check passed |
|
4018 * CKR_GENERAL_ERROR if pairwise consistency check failed |
|
4019 * other error codes if paiswise consistency check could not be |
|
4020 * performed, for example, CKR_HOST_MEMORY. |
|
4021 */ |
|
4022 static CK_RV |
|
4023 sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, |
|
4024 SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) |
|
4025 { |
|
4026 /* |
|
4027 * Key type Mechanism type |
|
4028 * -------------------------------- |
|
4029 * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS |
|
4030 * others => CKM_INVALID_MECHANISM |
|
4031 * |
|
4032 * For sign/verify: CKK_RSA => CKM_RSA_PKCS |
|
4033 * CKK_DSA => CKM_DSA |
|
4034 * CKK_EC => CKM_ECDSA |
|
4035 * others => CKM_INVALID_MECHANISM |
|
4036 * |
|
4037 * None of these mechanisms has a parameter. |
|
4038 */ |
|
4039 CK_MECHANISM mech = {0, NULL, 0}; |
|
4040 |
|
4041 CK_ULONG modulusLen; |
|
4042 CK_ULONG subPrimeLen; |
|
4043 PRBool isEncryptable = PR_FALSE; |
|
4044 PRBool canSignVerify = PR_FALSE; |
|
4045 PRBool isDerivable = PR_FALSE; |
|
4046 CK_RV crv; |
|
4047 |
|
4048 /* Variables used for Encrypt/Decrypt functions. */ |
|
4049 unsigned char *known_message = (unsigned char *)"Known Crypto Message"; |
|
4050 unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; |
|
4051 CK_ULONG bytes_decrypted; |
|
4052 unsigned char *ciphertext; |
|
4053 unsigned char *text_compared; |
|
4054 CK_ULONG bytes_encrypted; |
|
4055 CK_ULONG bytes_compared; |
|
4056 CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH; |
|
4057 |
|
4058 /* Variables used for Signature/Verification functions. */ |
|
4059 /* Must be at least 256 bits for DSA2 digest */ |
|
4060 unsigned char *known_digest = (unsigned char *) |
|
4061 "Mozilla Rules the World through NSS!"; |
|
4062 unsigned char *signature; |
|
4063 CK_ULONG signature_length; |
|
4064 |
|
4065 if (keyType == CKK_RSA) { |
|
4066 SFTKAttribute *attribute; |
|
4067 |
|
4068 /* Get modulus length of private key. */ |
|
4069 attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); |
|
4070 if (attribute == NULL) { |
|
4071 return CKR_DEVICE_ERROR; |
|
4072 } |
|
4073 modulusLen = attribute->attrib.ulValueLen; |
|
4074 if (*(unsigned char *)attribute->attrib.pValue == 0) { |
|
4075 modulusLen--; |
|
4076 } |
|
4077 sftk_FreeAttribute(attribute); |
|
4078 } else if (keyType == CKK_DSA) { |
|
4079 SFTKAttribute *attribute; |
|
4080 |
|
4081 /* Get subprime length of private key. */ |
|
4082 attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME); |
|
4083 if (attribute == NULL) { |
|
4084 return CKR_DEVICE_ERROR; |
|
4085 } |
|
4086 subPrimeLen = attribute->attrib.ulValueLen; |
|
4087 if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) { |
|
4088 subPrimeLen--; |
|
4089 } |
|
4090 sftk_FreeAttribute(attribute); |
|
4091 } |
|
4092 |
|
4093 /**************************************************/ |
|
4094 /* Pairwise Consistency Check of Encrypt/Decrypt. */ |
|
4095 /**************************************************/ |
|
4096 |
|
4097 isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); |
|
4098 |
|
4099 /* |
|
4100 * If the decryption attribute is set, attempt to encrypt |
|
4101 * with the public key and decrypt with the private key. |
|
4102 */ |
|
4103 if (isEncryptable) { |
|
4104 if (keyType != CKK_RSA) { |
|
4105 return CKR_DEVICE_ERROR; |
|
4106 } |
|
4107 bytes_encrypted = modulusLen; |
|
4108 mech.mechanism = CKM_RSA_PKCS; |
|
4109 |
|
4110 /* Allocate space for ciphertext. */ |
|
4111 ciphertext = (unsigned char *) PORT_ZAlloc(bytes_encrypted); |
|
4112 if (ciphertext == NULL) { |
|
4113 return CKR_HOST_MEMORY; |
|
4114 } |
|
4115 |
|
4116 /* Prepare for encryption using the public key. */ |
|
4117 crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); |
|
4118 if (crv != CKR_OK) { |
|
4119 PORT_Free(ciphertext); |
|
4120 return crv; |
|
4121 } |
|
4122 |
|
4123 /* Encrypt using the public key. */ |
|
4124 crv = NSC_Encrypt(hSession, |
|
4125 known_message, |
|
4126 PAIRWISE_MESSAGE_LENGTH, |
|
4127 ciphertext, |
|
4128 &bytes_encrypted); |
|
4129 if (crv != CKR_OK) { |
|
4130 PORT_Free(ciphertext); |
|
4131 return crv; |
|
4132 } |
|
4133 |
|
4134 /* Always use the smaller of these two values . . . */ |
|
4135 bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); |
|
4136 |
|
4137 /* |
|
4138 * If there was a failure, the plaintext |
|
4139 * goes at the end, therefore . . . |
|
4140 */ |
|
4141 text_compared = ciphertext + bytes_encrypted - bytes_compared; |
|
4142 |
|
4143 /* |
|
4144 * Check to ensure that ciphertext does |
|
4145 * NOT EQUAL known input message text |
|
4146 * per FIPS PUB 140-2 directive. |
|
4147 */ |
|
4148 if (PORT_Memcmp(text_compared, known_message, |
|
4149 bytes_compared) == 0) { |
|
4150 /* Set error to Invalid PRIVATE Key. */ |
|
4151 PORT_SetError(SEC_ERROR_INVALID_KEY); |
|
4152 PORT_Free(ciphertext); |
|
4153 return CKR_GENERAL_ERROR; |
|
4154 } |
|
4155 |
|
4156 /* Prepare for decryption using the private key. */ |
|
4157 crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); |
|
4158 if (crv != CKR_OK) { |
|
4159 PORT_Free(ciphertext); |
|
4160 return crv; |
|
4161 } |
|
4162 |
|
4163 memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); |
|
4164 |
|
4165 /* |
|
4166 * Initialize bytes decrypted to be the |
|
4167 * expected PAIRWISE_MESSAGE_LENGTH. |
|
4168 */ |
|
4169 bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; |
|
4170 |
|
4171 /* |
|
4172 * Decrypt using the private key. |
|
4173 * NOTE: No need to reset the |
|
4174 * value of bytes_encrypted. |
|
4175 */ |
|
4176 crv = NSC_Decrypt(hSession, |
|
4177 ciphertext, |
|
4178 bytes_encrypted, |
|
4179 plaintext, |
|
4180 &bytes_decrypted); |
|
4181 |
|
4182 /* Finished with ciphertext; free it. */ |
|
4183 PORT_Free(ciphertext); |
|
4184 |
|
4185 if (crv != CKR_OK) { |
|
4186 return crv; |
|
4187 } |
|
4188 |
|
4189 /* |
|
4190 * Check to ensure that the output plaintext |
|
4191 * does EQUAL known input message text. |
|
4192 */ |
|
4193 if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || |
|
4194 (PORT_Memcmp(plaintext, known_message, |
|
4195 PAIRWISE_MESSAGE_LENGTH) != 0)) { |
|
4196 /* Set error to Bad PUBLIC Key. */ |
|
4197 PORT_SetError(SEC_ERROR_BAD_KEY); |
|
4198 return CKR_GENERAL_ERROR; |
|
4199 } |
|
4200 } |
|
4201 |
|
4202 /**********************************************/ |
|
4203 /* Pairwise Consistency Check of Sign/Verify. */ |
|
4204 /**********************************************/ |
|
4205 |
|
4206 canSignVerify = sftk_isTrue(privateKey, CKA_SIGN); |
|
4207 |
|
4208 if (canSignVerify) { |
|
4209 /* Determine length of signature. */ |
|
4210 switch (keyType) { |
|
4211 case CKK_RSA: |
|
4212 signature_length = modulusLen; |
|
4213 mech.mechanism = CKM_RSA_PKCS; |
|
4214 break; |
|
4215 case CKK_DSA: |
|
4216 signature_length = DSA_MAX_SIGNATURE_LEN; |
|
4217 pairwise_digest_length = subPrimeLen; |
|
4218 mech.mechanism = CKM_DSA; |
|
4219 break; |
|
4220 #ifndef NSS_DISABLE_ECC |
|
4221 case CKK_EC: |
|
4222 signature_length = MAX_ECKEY_LEN * 2; |
|
4223 mech.mechanism = CKM_ECDSA; |
|
4224 break; |
|
4225 #endif |
|
4226 default: |
|
4227 return CKR_DEVICE_ERROR; |
|
4228 } |
|
4229 |
|
4230 /* Allocate space for signature data. */ |
|
4231 signature = (unsigned char *) PORT_ZAlloc(signature_length); |
|
4232 if (signature == NULL) { |
|
4233 return CKR_HOST_MEMORY; |
|
4234 } |
|
4235 |
|
4236 /* Sign the known hash using the private key. */ |
|
4237 crv = NSC_SignInit(hSession, &mech, privateKey->handle); |
|
4238 if (crv != CKR_OK) { |
|
4239 PORT_Free(signature); |
|
4240 return crv; |
|
4241 } |
|
4242 |
|
4243 crv = NSC_Sign(hSession, |
|
4244 known_digest, |
|
4245 pairwise_digest_length, |
|
4246 signature, |
|
4247 &signature_length); |
|
4248 if (crv != CKR_OK) { |
|
4249 PORT_Free(signature); |
|
4250 return crv; |
|
4251 } |
|
4252 |
|
4253 /* Verify the known hash using the public key. */ |
|
4254 crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); |
|
4255 if (crv != CKR_OK) { |
|
4256 PORT_Free(signature); |
|
4257 return crv; |
|
4258 } |
|
4259 |
|
4260 crv = NSC_Verify(hSession, |
|
4261 known_digest, |
|
4262 pairwise_digest_length, |
|
4263 signature, |
|
4264 signature_length); |
|
4265 |
|
4266 /* Free signature data. */ |
|
4267 PORT_Free(signature); |
|
4268 |
|
4269 if ((crv == CKR_SIGNATURE_LEN_RANGE) || |
|
4270 (crv == CKR_SIGNATURE_INVALID)) { |
|
4271 return CKR_GENERAL_ERROR; |
|
4272 } |
|
4273 if (crv != CKR_OK) { |
|
4274 return crv; |
|
4275 } |
|
4276 } |
|
4277 |
|
4278 /**********************************************/ |
|
4279 /* Pairwise Consistency Check for Derivation */ |
|
4280 /**********************************************/ |
|
4281 |
|
4282 isDerivable = sftk_isTrue(privateKey, CKA_DERIVE); |
|
4283 |
|
4284 if (isDerivable) { |
|
4285 /* |
|
4286 * We are not doing consistency check for Diffie-Hellman Key - |
|
4287 * otherwise it would be here |
|
4288 * This is also true for Elliptic Curve Diffie-Hellman keys |
|
4289 * NOTE: EC keys are currently subjected to pairwise |
|
4290 * consistency check for signing/verification. |
|
4291 */ |
|
4292 /* |
|
4293 * FIPS 140-2 had the following pairwise consistency test for |
|
4294 * public and private keys used for key agreement: |
|
4295 * If the keys are used to perform key agreement, then the |
|
4296 * cryptographic module shall create a second, compatible |
|
4297 * key pair. The cryptographic module shall perform both |
|
4298 * sides of the key agreement algorithm and shall compare |
|
4299 * the resulting shared values. If the shared values are |
|
4300 * not equal, the test shall fail. |
|
4301 * This test was removed in Change Notice 3. |
|
4302 */ |
|
4303 |
|
4304 } |
|
4305 |
|
4306 return CKR_OK; |
|
4307 } |
|
4308 |
|
4309 /* NSC_GenerateKeyPair generates a public-key/private-key pair, |
|
4310 * creating new key objects. */ |
|
4311 CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession, |
|
4312 CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, |
|
4313 CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, |
|
4314 CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, |
|
4315 CK_OBJECT_HANDLE_PTR phPrivateKey) |
|
4316 { |
|
4317 SFTKObject * publicKey,*privateKey; |
|
4318 SFTKSession * session; |
|
4319 CK_KEY_TYPE key_type; |
|
4320 CK_RV crv = CKR_OK; |
|
4321 CK_BBOOL cktrue = CK_TRUE; |
|
4322 SECStatus rv; |
|
4323 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; |
|
4324 CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; |
|
4325 int i; |
|
4326 SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession); |
|
4327 unsigned int bitSize; |
|
4328 |
|
4329 /* RSA */ |
|
4330 int public_modulus_bits = 0; |
|
4331 SECItem pubExp; |
|
4332 RSAPrivateKey * rsaPriv; |
|
4333 |
|
4334 /* DSA */ |
|
4335 PQGParams pqgParam; |
|
4336 DHParams dhParam; |
|
4337 DSAPrivateKey * dsaPriv; |
|
4338 |
|
4339 /* Diffie Hellman */ |
|
4340 int private_value_bits = 0; |
|
4341 DHPrivateKey * dhPriv; |
|
4342 |
|
4343 #ifndef NSS_DISABLE_ECC |
|
4344 /* Elliptic Curve Cryptography */ |
|
4345 SECItem ecEncodedParams; /* DER Encoded parameters */ |
|
4346 ECPrivateKey * ecPriv; |
|
4347 ECParams * ecParams; |
|
4348 #endif /* NSS_DISABLE_ECC */ |
|
4349 |
|
4350 CHECK_FORK(); |
|
4351 |
|
4352 if (!slot) { |
|
4353 return CKR_SESSION_HANDLE_INVALID; |
|
4354 } |
|
4355 /* |
|
4356 * now lets create an object to hang the attributes off of |
|
4357 */ |
|
4358 publicKey = sftk_NewObject(slot); /* fill in the handle later */ |
|
4359 if (publicKey == NULL) { |
|
4360 return CKR_HOST_MEMORY; |
|
4361 } |
|
4362 |
|
4363 /* |
|
4364 * load the template values into the publicKey |
|
4365 */ |
|
4366 for (i=0; i < (int) ulPublicKeyAttributeCount; i++) { |
|
4367 if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) { |
|
4368 public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; |
|
4369 continue; |
|
4370 } |
|
4371 |
|
4372 crv = sftk_AddAttributeType(publicKey, |
|
4373 sftk_attr_expand(&pPublicKeyTemplate[i])); |
|
4374 if (crv != CKR_OK) break; |
|
4375 } |
|
4376 |
|
4377 if (crv != CKR_OK) { |
|
4378 sftk_FreeObject(publicKey); |
|
4379 return CKR_HOST_MEMORY; |
|
4380 } |
|
4381 |
|
4382 privateKey = sftk_NewObject(slot); /* fill in the handle later */ |
|
4383 if (privateKey == NULL) { |
|
4384 sftk_FreeObject(publicKey); |
|
4385 return CKR_HOST_MEMORY; |
|
4386 } |
|
4387 /* |
|
4388 * now load the private key template |
|
4389 */ |
|
4390 for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) { |
|
4391 if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) { |
|
4392 private_value_bits = *(CK_ULONG *)pPrivateKeyTemplate[i].pValue; |
|
4393 continue; |
|
4394 } |
|
4395 |
|
4396 crv = sftk_AddAttributeType(privateKey, |
|
4397 sftk_attr_expand(&pPrivateKeyTemplate[i])); |
|
4398 if (crv != CKR_OK) break; |
|
4399 } |
|
4400 |
|
4401 if (crv != CKR_OK) { |
|
4402 sftk_FreeObject(publicKey); |
|
4403 sftk_FreeObject(privateKey); |
|
4404 return CKR_HOST_MEMORY; |
|
4405 } |
|
4406 sftk_DeleteAttributeType(privateKey,CKA_CLASS); |
|
4407 sftk_DeleteAttributeType(privateKey,CKA_KEY_TYPE); |
|
4408 sftk_DeleteAttributeType(privateKey,CKA_VALUE); |
|
4409 sftk_DeleteAttributeType(publicKey,CKA_CLASS); |
|
4410 sftk_DeleteAttributeType(publicKey,CKA_KEY_TYPE); |
|
4411 sftk_DeleteAttributeType(publicKey,CKA_VALUE); |
|
4412 |
|
4413 /* Now Set up the parameters to generate the key (based on mechanism) */ |
|
4414 switch (pMechanism->mechanism) { |
|
4415 case CKM_RSA_PKCS_KEY_PAIR_GEN: |
|
4416 /* format the keys */ |
|
4417 sftk_DeleteAttributeType(publicKey,CKA_MODULUS); |
|
4418 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); |
|
4419 sftk_DeleteAttributeType(privateKey,CKA_MODULUS); |
|
4420 sftk_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT); |
|
4421 sftk_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT); |
|
4422 sftk_DeleteAttributeType(privateKey,CKA_PRIME_1); |
|
4423 sftk_DeleteAttributeType(privateKey,CKA_PRIME_2); |
|
4424 sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_1); |
|
4425 sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_2); |
|
4426 sftk_DeleteAttributeType(privateKey,CKA_COEFFICIENT); |
|
4427 key_type = CKK_RSA; |
|
4428 if (public_modulus_bits == 0) { |
|
4429 crv = CKR_TEMPLATE_INCOMPLETE; |
|
4430 break; |
|
4431 } |
|
4432 if (public_modulus_bits < RSA_MIN_MODULUS_BITS) { |
|
4433 crv = CKR_ATTRIBUTE_VALUE_INVALID; |
|
4434 break; |
|
4435 } |
|
4436 if (public_modulus_bits % 2 != 0) { |
|
4437 crv = CKR_ATTRIBUTE_VALUE_INVALID; |
|
4438 break; |
|
4439 } |
|
4440 |
|
4441 /* extract the exponent */ |
|
4442 crv=sftk_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT); |
|
4443 if (crv != CKR_OK) break; |
|
4444 bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len); |
|
4445 if (bitSize < 2) { |
|
4446 crv = CKR_ATTRIBUTE_VALUE_INVALID; |
|
4447 break; |
|
4448 } |
|
4449 crv = sftk_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT, |
|
4450 sftk_item_expand(&pubExp)); |
|
4451 if (crv != CKR_OK) { |
|
4452 PORT_Free(pubExp.data); |
|
4453 break; |
|
4454 } |
|
4455 |
|
4456 rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); |
|
4457 PORT_Free(pubExp.data); |
|
4458 if (rsaPriv == NULL) { |
|
4459 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
4460 sftk_fatalError = PR_TRUE; |
|
4461 } |
|
4462 crv = sftk_MapCryptError(PORT_GetError()); |
|
4463 break; |
|
4464 } |
|
4465 /* now fill in the RSA dependent paramenters in the public key */ |
|
4466 crv = sftk_AddAttributeType(publicKey,CKA_MODULUS, |
|
4467 sftk_item_expand(&rsaPriv->modulus)); |
|
4468 if (crv != CKR_OK) goto kpg_done; |
|
4469 /* now fill in the RSA dependent paramenters in the private key */ |
|
4470 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, |
|
4471 sftk_item_expand(&rsaPriv->modulus)); |
|
4472 if (crv != CKR_OK) goto kpg_done; |
|
4473 crv = sftk_AddAttributeType(privateKey,CKA_MODULUS, |
|
4474 sftk_item_expand(&rsaPriv->modulus)); |
|
4475 if (crv != CKR_OK) goto kpg_done; |
|
4476 crv = sftk_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT, |
|
4477 sftk_item_expand(&rsaPriv->privateExponent)); |
|
4478 if (crv != CKR_OK) goto kpg_done; |
|
4479 crv = sftk_AddAttributeType(privateKey,CKA_PRIME_1, |
|
4480 sftk_item_expand(&rsaPriv->prime1)); |
|
4481 if (crv != CKR_OK) goto kpg_done; |
|
4482 crv = sftk_AddAttributeType(privateKey,CKA_PRIME_2, |
|
4483 sftk_item_expand(&rsaPriv->prime2)); |
|
4484 if (crv != CKR_OK) goto kpg_done; |
|
4485 crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_1, |
|
4486 sftk_item_expand(&rsaPriv->exponent1)); |
|
4487 if (crv != CKR_OK) goto kpg_done; |
|
4488 crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_2, |
|
4489 sftk_item_expand(&rsaPriv->exponent2)); |
|
4490 if (crv != CKR_OK) goto kpg_done; |
|
4491 crv = sftk_AddAttributeType(privateKey,CKA_COEFFICIENT, |
|
4492 sftk_item_expand(&rsaPriv->coefficient)); |
|
4493 kpg_done: |
|
4494 /* Should zeroize the contents first, since this func doesn't. */ |
|
4495 PORT_FreeArena(rsaPriv->arena, PR_TRUE); |
|
4496 break; |
|
4497 case CKM_DSA_KEY_PAIR_GEN: |
|
4498 sftk_DeleteAttributeType(publicKey,CKA_VALUE); |
|
4499 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); |
|
4500 sftk_DeleteAttributeType(privateKey,CKA_PRIME); |
|
4501 sftk_DeleteAttributeType(privateKey,CKA_SUBPRIME); |
|
4502 sftk_DeleteAttributeType(privateKey,CKA_BASE); |
|
4503 key_type = CKK_DSA; |
|
4504 |
|
4505 /* extract the necessary parameters and copy them to the private key */ |
|
4506 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME); |
|
4507 if (crv != CKR_OK) break; |
|
4508 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey, |
|
4509 CKA_SUBPRIME); |
|
4510 if (crv != CKR_OK) { |
|
4511 PORT_Free(pqgParam.prime.data); |
|
4512 break; |
|
4513 } |
|
4514 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE); |
|
4515 if (crv != CKR_OK) { |
|
4516 PORT_Free(pqgParam.prime.data); |
|
4517 PORT_Free(pqgParam.subPrime.data); |
|
4518 break; |
|
4519 } |
|
4520 crv = sftk_AddAttributeType(privateKey,CKA_PRIME, |
|
4521 sftk_item_expand(&pqgParam.prime)); |
|
4522 if (crv != CKR_OK) { |
|
4523 PORT_Free(pqgParam.prime.data); |
|
4524 PORT_Free(pqgParam.subPrime.data); |
|
4525 PORT_Free(pqgParam.base.data); |
|
4526 break; |
|
4527 } |
|
4528 crv = sftk_AddAttributeType(privateKey,CKA_SUBPRIME, |
|
4529 sftk_item_expand(&pqgParam.subPrime)); |
|
4530 if (crv != CKR_OK) { |
|
4531 PORT_Free(pqgParam.prime.data); |
|
4532 PORT_Free(pqgParam.subPrime.data); |
|
4533 PORT_Free(pqgParam.base.data); |
|
4534 break; |
|
4535 } |
|
4536 crv = sftk_AddAttributeType(privateKey,CKA_BASE, |
|
4537 sftk_item_expand(&pqgParam.base)); |
|
4538 if (crv != CKR_OK) { |
|
4539 PORT_Free(pqgParam.prime.data); |
|
4540 PORT_Free(pqgParam.subPrime.data); |
|
4541 PORT_Free(pqgParam.base.data); |
|
4542 break; |
|
4543 } |
|
4544 |
|
4545 /* |
|
4546 * these are checked by DSA_NewKey |
|
4547 */ |
|
4548 bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data, |
|
4549 pqgParam.subPrime.len); |
|
4550 if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) { |
|
4551 crv = CKR_TEMPLATE_INCOMPLETE; |
|
4552 PORT_Free(pqgParam.prime.data); |
|
4553 PORT_Free(pqgParam.subPrime.data); |
|
4554 PORT_Free(pqgParam.base.data); |
|
4555 break; |
|
4556 } |
|
4557 bitSize = sftk_GetLengthInBits(pqgParam.prime.data,pqgParam.prime.len); |
|
4558 if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) { |
|
4559 crv = CKR_TEMPLATE_INCOMPLETE; |
|
4560 PORT_Free(pqgParam.prime.data); |
|
4561 PORT_Free(pqgParam.subPrime.data); |
|
4562 PORT_Free(pqgParam.base.data); |
|
4563 break; |
|
4564 } |
|
4565 bitSize = sftk_GetLengthInBits(pqgParam.base.data,pqgParam.base.len); |
|
4566 if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) { |
|
4567 crv = CKR_TEMPLATE_INCOMPLETE; |
|
4568 PORT_Free(pqgParam.prime.data); |
|
4569 PORT_Free(pqgParam.subPrime.data); |
|
4570 PORT_Free(pqgParam.base.data); |
|
4571 break; |
|
4572 } |
|
4573 |
|
4574 /* Generate the key */ |
|
4575 rv = DSA_NewKey(&pqgParam, &dsaPriv); |
|
4576 |
|
4577 PORT_Free(pqgParam.prime.data); |
|
4578 PORT_Free(pqgParam.subPrime.data); |
|
4579 PORT_Free(pqgParam.base.data); |
|
4580 |
|
4581 if (rv != SECSuccess) { |
|
4582 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
4583 sftk_fatalError = PR_TRUE; |
|
4584 } |
|
4585 crv = sftk_MapCryptError(PORT_GetError()); |
|
4586 break; |
|
4587 } |
|
4588 |
|
4589 /* store the generated key into the attributes */ |
|
4590 crv = sftk_AddAttributeType(publicKey,CKA_VALUE, |
|
4591 sftk_item_expand(&dsaPriv->publicValue)); |
|
4592 if (crv != CKR_OK) goto dsagn_done; |
|
4593 |
|
4594 /* now fill in the RSA dependent paramenters in the private key */ |
|
4595 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, |
|
4596 sftk_item_expand(&dsaPriv->publicValue)); |
|
4597 if (crv != CKR_OK) goto dsagn_done; |
|
4598 crv = sftk_AddAttributeType(privateKey,CKA_VALUE, |
|
4599 sftk_item_expand(&dsaPriv->privateValue)); |
|
4600 |
|
4601 dsagn_done: |
|
4602 /* should zeroize, since this function doesn't. */ |
|
4603 PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); |
|
4604 break; |
|
4605 |
|
4606 case CKM_DH_PKCS_KEY_PAIR_GEN: |
|
4607 sftk_DeleteAttributeType(privateKey,CKA_PRIME); |
|
4608 sftk_DeleteAttributeType(privateKey,CKA_BASE); |
|
4609 sftk_DeleteAttributeType(privateKey,CKA_VALUE); |
|
4610 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); |
|
4611 key_type = CKK_DH; |
|
4612 |
|
4613 /* extract the necessary parameters and copy them to private keys */ |
|
4614 crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, |
|
4615 CKA_PRIME); |
|
4616 if (crv != CKR_OK) break; |
|
4617 crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE); |
|
4618 if (crv != CKR_OK) { |
|
4619 PORT_Free(dhParam.prime.data); |
|
4620 break; |
|
4621 } |
|
4622 crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
|
4623 sftk_item_expand(&dhParam.prime)); |
|
4624 if (crv != CKR_OK) { |
|
4625 PORT_Free(dhParam.prime.data); |
|
4626 PORT_Free(dhParam.base.data); |
|
4627 break; |
|
4628 } |
|
4629 crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
|
4630 sftk_item_expand(&dhParam.base)); |
|
4631 if (crv != CKR_OK) { |
|
4632 PORT_Free(dhParam.prime.data); |
|
4633 PORT_Free(dhParam.base.data); |
|
4634 break; |
|
4635 } |
|
4636 bitSize = sftk_GetLengthInBits(dhParam.prime.data,dhParam.prime.len); |
|
4637 if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) { |
|
4638 crv = CKR_TEMPLATE_INCOMPLETE; |
|
4639 PORT_Free(dhParam.prime.data); |
|
4640 PORT_Free(dhParam.base.data); |
|
4641 break; |
|
4642 } |
|
4643 bitSize = sftk_GetLengthInBits(dhParam.base.data,dhParam.base.len); |
|
4644 if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) { |
|
4645 crv = CKR_TEMPLATE_INCOMPLETE; |
|
4646 PORT_Free(dhParam.prime.data); |
|
4647 PORT_Free(dhParam.base.data); |
|
4648 break; |
|
4649 } |
|
4650 |
|
4651 rv = DH_NewKey(&dhParam, &dhPriv); |
|
4652 PORT_Free(dhParam.prime.data); |
|
4653 PORT_Free(dhParam.base.data); |
|
4654 if (rv != SECSuccess) { |
|
4655 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
4656 sftk_fatalError = PR_TRUE; |
|
4657 } |
|
4658 crv = sftk_MapCryptError(PORT_GetError()); |
|
4659 break; |
|
4660 } |
|
4661 |
|
4662 crv=sftk_AddAttributeType(publicKey, CKA_VALUE, |
|
4663 sftk_item_expand(&dhPriv->publicValue)); |
|
4664 if (crv != CKR_OK) goto dhgn_done; |
|
4665 |
|
4666 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, |
|
4667 sftk_item_expand(&dhPriv->publicValue)); |
|
4668 if (crv != CKR_OK) goto dhgn_done; |
|
4669 |
|
4670 crv=sftk_AddAttributeType(privateKey, CKA_VALUE, |
|
4671 sftk_item_expand(&dhPriv->privateValue)); |
|
4672 |
|
4673 dhgn_done: |
|
4674 /* should zeroize, since this function doesn't. */ |
|
4675 PORT_FreeArena(dhPriv->arena, PR_TRUE); |
|
4676 break; |
|
4677 |
|
4678 #ifndef NSS_DISABLE_ECC |
|
4679 case CKM_EC_KEY_PAIR_GEN: |
|
4680 sftk_DeleteAttributeType(privateKey,CKA_EC_PARAMS); |
|
4681 sftk_DeleteAttributeType(privateKey,CKA_VALUE); |
|
4682 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); |
|
4683 key_type = CKK_EC; |
|
4684 |
|
4685 /* extract the necessary parameters and copy them to private keys */ |
|
4686 crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
|
4687 CKA_EC_PARAMS); |
|
4688 if (crv != CKR_OK) break; |
|
4689 |
|
4690 crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
|
4691 sftk_item_expand(&ecEncodedParams)); |
|
4692 if (crv != CKR_OK) { |
|
4693 PORT_Free(ecEncodedParams.data); |
|
4694 break; |
|
4695 } |
|
4696 |
|
4697 /* Decode ec params before calling EC_NewKey */ |
|
4698 rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
|
4699 PORT_Free(ecEncodedParams.data); |
|
4700 if (rv != SECSuccess) { |
|
4701 crv = sftk_MapCryptError(PORT_GetError()); |
|
4702 break; |
|
4703 } |
|
4704 rv = EC_NewKey(ecParams, &ecPriv); |
|
4705 PORT_FreeArena(ecParams->arena, PR_TRUE); |
|
4706 if (rv != SECSuccess) { |
|
4707 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
|
4708 sftk_fatalError = PR_TRUE; |
|
4709 } |
|
4710 crv = sftk_MapCryptError(PORT_GetError()); |
|
4711 break; |
|
4712 } |
|
4713 |
|
4714 if (getenv("NSS_USE_DECODED_CKA_EC_POINT")) { |
|
4715 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
|
4716 sftk_item_expand(&ecPriv->publicValue)); |
|
4717 } else { |
|
4718 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, |
|
4719 &ecPriv->publicValue, |
|
4720 SEC_ASN1_GET(SEC_OctetStringTemplate)); |
|
4721 if (!pubValue) { |
|
4722 crv = CKR_ARGUMENTS_BAD; |
|
4723 goto ecgn_done; |
|
4724 } |
|
4725 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
|
4726 sftk_item_expand(pubValue)); |
|
4727 SECITEM_FreeItem(pubValue, PR_TRUE); |
|
4728 } |
|
4729 if (crv != CKR_OK) goto ecgn_done; |
|
4730 |
|
4731 crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
|
4732 sftk_item_expand(&ecPriv->privateValue)); |
|
4733 if (crv != CKR_OK) goto ecgn_done; |
|
4734 |
|
4735 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, |
|
4736 sftk_item_expand(&ecPriv->publicValue)); |
|
4737 ecgn_done: |
|
4738 /* should zeroize, since this function doesn't. */ |
|
4739 PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
|
4740 break; |
|
4741 #endif /* NSS_DISABLE_ECC */ |
|
4742 |
|
4743 default: |
|
4744 crv = CKR_MECHANISM_INVALID; |
|
4745 } |
|
4746 |
|
4747 if (crv != CKR_OK) { |
|
4748 sftk_FreeObject(privateKey); |
|
4749 sftk_FreeObject(publicKey); |
|
4750 return crv; |
|
4751 } |
|
4752 |
|
4753 |
|
4754 /* Add the class, key_type The loop lets us check errors blow out |
|
4755 * on errors and clean up at the bottom */ |
|
4756 session = NULL; /* make pedtantic happy... session cannot leave the*/ |
|
4757 /* loop below NULL unless an error is set... */ |
|
4758 do { |
|
4759 crv = sftk_AddAttributeType(privateKey,CKA_CLASS,&privClass, |
|
4760 sizeof(CK_OBJECT_CLASS)); |
|
4761 if (crv != CKR_OK) break; |
|
4762 crv = sftk_AddAttributeType(publicKey,CKA_CLASS,&pubClass, |
|
4763 sizeof(CK_OBJECT_CLASS)); |
|
4764 if (crv != CKR_OK) break; |
|
4765 crv = sftk_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type, |
|
4766 sizeof(CK_KEY_TYPE)); |
|
4767 if (crv != CKR_OK) break; |
|
4768 crv = sftk_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type, |
|
4769 sizeof(CK_KEY_TYPE)); |
|
4770 if (crv != CKR_OK) break; |
|
4771 session = sftk_SessionFromHandle(hSession); |
|
4772 if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID; |
|
4773 } while (0); |
|
4774 |
|
4775 if (crv != CKR_OK) { |
|
4776 sftk_FreeObject(privateKey); |
|
4777 sftk_FreeObject(publicKey); |
|
4778 return crv; |
|
4779 } |
|
4780 |
|
4781 /* |
|
4782 * handle the base object cleanup for the public Key |
|
4783 */ |
|
4784 crv = sftk_handleObject(privateKey,session); |
|
4785 if (crv != CKR_OK) { |
|
4786 sftk_FreeSession(session); |
|
4787 sftk_FreeObject(privateKey); |
|
4788 sftk_FreeObject(publicKey); |
|
4789 return crv; |
|
4790 } |
|
4791 |
|
4792 /* |
|
4793 * handle the base object cleanup for the private Key |
|
4794 * If we have any problems, we destroy the public Key we've |
|
4795 * created and linked. |
|
4796 */ |
|
4797 crv = sftk_handleObject(publicKey,session); |
|
4798 sftk_FreeSession(session); |
|
4799 if (crv != CKR_OK) { |
|
4800 sftk_FreeObject(publicKey); |
|
4801 NSC_DestroyObject(hSession,privateKey->handle); |
|
4802 sftk_FreeObject(privateKey); |
|
4803 return crv; |
|
4804 } |
|
4805 if (sftk_isTrue(privateKey,CKA_SENSITIVE)) { |
|
4806 sftk_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE, |
|
4807 &cktrue,sizeof(CK_BBOOL)); |
|
4808 } |
|
4809 if (sftk_isTrue(publicKey,CKA_SENSITIVE)) { |
|
4810 sftk_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE, |
|
4811 &cktrue,sizeof(CK_BBOOL)); |
|
4812 } |
|
4813 if (!sftk_isTrue(privateKey,CKA_EXTRACTABLE)) { |
|
4814 sftk_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE, |
|
4815 &cktrue,sizeof(CK_BBOOL)); |
|
4816 } |
|
4817 if (!sftk_isTrue(publicKey,CKA_EXTRACTABLE)) { |
|
4818 sftk_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE, |
|
4819 &cktrue,sizeof(CK_BBOOL)); |
|
4820 } |
|
4821 |
|
4822 /* Perform FIPS 140-2 pairwise consistency check. */ |
|
4823 crv = sftk_PairwiseConsistencyCheck(hSession, |
|
4824 publicKey, privateKey, key_type); |
|
4825 if (crv != CKR_OK) { |
|
4826 NSC_DestroyObject(hSession,publicKey->handle); |
|
4827 sftk_FreeObject(publicKey); |
|
4828 NSC_DestroyObject(hSession,privateKey->handle); |
|
4829 sftk_FreeObject(privateKey); |
|
4830 if (sftk_audit_enabled) { |
|
4831 char msg[128]; |
|
4832 PR_snprintf(msg,sizeof msg, |
|
4833 "C_GenerateKeyPair(hSession=0x%08lX, " |
|
4834 "pMechanism->mechanism=0x%08lX)=0x%08lX " |
|
4835 "self-test: pair-wise consistency test failed", |
|
4836 (PRUint32)hSession,(PRUint32)pMechanism->mechanism, |
|
4837 (PRUint32)crv); |
|
4838 sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); |
|
4839 } |
|
4840 return crv; |
|
4841 } |
|
4842 |
|
4843 *phPrivateKey = privateKey->handle; |
|
4844 *phPublicKey = publicKey->handle; |
|
4845 sftk_FreeObject(publicKey); |
|
4846 sftk_FreeObject(privateKey); |
|
4847 |
|
4848 return CKR_OK; |
|
4849 } |
|
4850 |
|
4851 static SECItem *sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) |
|
4852 { |
|
4853 NSSLOWKEYPrivateKey *lk = NULL; |
|
4854 NSSLOWKEYPrivateKeyInfo *pki = NULL; |
|
4855 SFTKAttribute *attribute = NULL; |
|
4856 PLArenaPool *arena = NULL; |
|
4857 SECOidTag algorithm = SEC_OID_UNKNOWN; |
|
4858 void *dummy, *param = NULL; |
|
4859 SECStatus rv = SECSuccess; |
|
4860 SECItem *encodedKey = NULL; |
|
4861 #ifndef NSS_DISABLE_ECC |
|
4862 SECItem *fordebug; |
|
4863 int savelen; |
|
4864 #endif |
|
4865 |
|
4866 if(!key) { |
|
4867 *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ |
|
4868 return NULL; |
|
4869 } |
|
4870 |
|
4871 attribute = sftk_FindAttribute(key, CKA_KEY_TYPE); |
|
4872 if(!attribute) { |
|
4873 *crvp = CKR_KEY_TYPE_INCONSISTENT; |
|
4874 return NULL; |
|
4875 } |
|
4876 |
|
4877 lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp); |
|
4878 sftk_FreeAttribute(attribute); |
|
4879 if(!lk) { |
|
4880 return NULL; |
|
4881 } |
|
4882 |
|
4883 arena = PORT_NewArena(2048); /* XXX different size? */ |
|
4884 if(!arena) { |
|
4885 *crvp = CKR_HOST_MEMORY; |
|
4886 rv = SECFailure; |
|
4887 goto loser; |
|
4888 } |
|
4889 |
|
4890 pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, |
|
4891 sizeof(NSSLOWKEYPrivateKeyInfo)); |
|
4892 if(!pki) { |
|
4893 *crvp = CKR_HOST_MEMORY; |
|
4894 rv = SECFailure; |
|
4895 goto loser; |
|
4896 } |
|
4897 pki->arena = arena; |
|
4898 |
|
4899 param = NULL; |
|
4900 switch(lk->keyType) { |
|
4901 case NSSLOWKEYRSAKey: |
|
4902 prepare_low_rsa_priv_key_for_asn1(lk); |
|
4903 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
|
4904 nsslowkey_RSAPrivateKeyTemplate); |
|
4905 algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
|
4906 break; |
|
4907 case NSSLOWKEYDSAKey: |
|
4908 prepare_low_dsa_priv_key_export_for_asn1(lk); |
|
4909 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
|
4910 nsslowkey_DSAPrivateKeyExportTemplate); |
|
4911 prepare_low_pqg_params_for_asn1(&lk->u.dsa.params); |
|
4912 param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), |
|
4913 nsslowkey_PQGParamsTemplate); |
|
4914 algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; |
|
4915 break; |
|
4916 #ifndef NSS_DISABLE_ECC |
|
4917 case NSSLOWKEYECKey: |
|
4918 prepare_low_ec_priv_key_for_asn1(lk); |
|
4919 /* Public value is encoded as a bit string so adjust length |
|
4920 * to be in bits before ASN encoding and readjust |
|
4921 * immediately after. |
|
4922 * |
|
4923 * Since the SECG specification recommends not including the |
|
4924 * parameters as part of ECPrivateKey, we zero out the curveOID |
|
4925 * length before encoding and restore it later. |
|
4926 */ |
|
4927 lk->u.ec.publicValue.len <<= 3; |
|
4928 savelen = lk->u.ec.ecParams.curveOID.len; |
|
4929 lk->u.ec.ecParams.curveOID.len = 0; |
|
4930 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
|
4931 nsslowkey_ECPrivateKeyTemplate); |
|
4932 lk->u.ec.ecParams.curveOID.len = savelen; |
|
4933 lk->u.ec.publicValue.len >>= 3; |
|
4934 |
|
4935 fordebug = &pki->privateKey; |
|
4936 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType, |
|
4937 fordebug); |
|
4938 |
|
4939 param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); |
|
4940 |
|
4941 algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; |
|
4942 break; |
|
4943 #endif /* NSS_DISABLE_ECC */ |
|
4944 case NSSLOWKEYDHKey: |
|
4945 default: |
|
4946 dummy = NULL; |
|
4947 break; |
|
4948 } |
|
4949 |
|
4950 if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { |
|
4951 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
|
4952 rv = SECFailure; |
|
4953 goto loser; |
|
4954 } |
|
4955 |
|
4956 rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, |
|
4957 (SECItem*)param); |
|
4958 if(rv != SECSuccess) { |
|
4959 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
|
4960 rv = SECFailure; |
|
4961 goto loser; |
|
4962 } |
|
4963 |
|
4964 dummy = SEC_ASN1EncodeInteger(arena, &pki->version, |
|
4965 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); |
|
4966 if(!dummy) { |
|
4967 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
|
4968 rv = SECFailure; |
|
4969 goto loser; |
|
4970 } |
|
4971 |
|
4972 encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, |
|
4973 nsslowkey_PrivateKeyInfoTemplate); |
|
4974 *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR; |
|
4975 |
|
4976 #ifndef NSS_DISABLE_ECC |
|
4977 fordebug = encodedKey; |
|
4978 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType, |
|
4979 fordebug); |
|
4980 #endif |
|
4981 loser: |
|
4982 if(arena) { |
|
4983 PORT_FreeArena(arena, PR_TRUE); |
|
4984 } |
|
4985 |
|
4986 if(lk && (lk != key->objectInfo)) { |
|
4987 nsslowkey_DestroyPrivateKey(lk); |
|
4988 } |
|
4989 |
|
4990 if(param) { |
|
4991 SECITEM_ZfreeItem((SECItem*)param, PR_TRUE); |
|
4992 } |
|
4993 |
|
4994 if(rv != SECSuccess) { |
|
4995 return NULL; |
|
4996 } |
|
4997 |
|
4998 return encodedKey; |
|
4999 } |
|
5000 |
|
5001 /* it doesn't matter yet, since we colapse error conditions in the |
|
5002 * level above, but we really should map those few key error differences */ |
|
5003 static CK_RV |
|
5004 sftk_mapWrap(CK_RV crv) |
|
5005 { |
|
5006 switch (crv) { |
|
5007 case CKR_ENCRYPTED_DATA_INVALID: crv = CKR_WRAPPED_KEY_INVALID; break; |
|
5008 } |
|
5009 return crv; |
|
5010 } |
|
5011 |
|
5012 /* NSC_WrapKey wraps (i.e., encrypts) a key. */ |
|
5013 CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, |
|
5014 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, |
|
5015 CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, |
|
5016 CK_ULONG_PTR pulWrappedKeyLen) |
|
5017 { |
|
5018 SFTKSession *session; |
|
5019 SFTKAttribute *attribute; |
|
5020 SFTKObject *key; |
|
5021 CK_RV crv; |
|
5022 |
|
5023 CHECK_FORK(); |
|
5024 |
|
5025 session = sftk_SessionFromHandle(hSession); |
|
5026 if (session == NULL) { |
|
5027 return CKR_SESSION_HANDLE_INVALID; |
|
5028 } |
|
5029 |
|
5030 key = sftk_ObjectFromHandle(hKey,session); |
|
5031 sftk_FreeSession(session); |
|
5032 if (key == NULL) { |
|
5033 return CKR_KEY_HANDLE_INVALID; |
|
5034 } |
|
5035 |
|
5036 switch(key->objclass) { |
|
5037 case CKO_SECRET_KEY: |
|
5038 { |
|
5039 SFTKSessionContext *context = NULL; |
|
5040 SECItem pText; |
|
5041 |
|
5042 attribute = sftk_FindAttribute(key,CKA_VALUE); |
|
5043 |
|
5044 if (attribute == NULL) { |
|
5045 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
5046 break; |
|
5047 } |
|
5048 crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
|
5049 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
|
5050 if (crv != CKR_OK) { |
|
5051 sftk_FreeAttribute(attribute); |
|
5052 break; |
|
5053 } |
|
5054 |
|
5055 pText.type = siBuffer; |
|
5056 pText.data = (unsigned char *)attribute->attrib.pValue; |
|
5057 pText.len = attribute->attrib.ulValueLen; |
|
5058 |
|
5059 /* Find out if this is a block cipher. */ |
|
5060 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,NULL); |
|
5061 if (crv != CKR_OK || !context) |
|
5062 break; |
|
5063 if (context->blockSize > 1) { |
|
5064 unsigned int remainder = pText.len % context->blockSize; |
|
5065 if (!context->doPad && remainder) { |
|
5066 /* When wrapping secret keys with unpadded block ciphers, |
|
5067 ** the keys are zero padded, if necessary, to fill out |
|
5068 ** a full block. |
|
5069 */ |
|
5070 pText.len += context->blockSize - remainder; |
|
5071 pText.data = PORT_ZAlloc(pText.len); |
|
5072 if (pText.data) |
|
5073 memcpy(pText.data, attribute->attrib.pValue, |
|
5074 attribute->attrib.ulValueLen); |
|
5075 else { |
|
5076 crv = CKR_HOST_MEMORY; |
|
5077 break; |
|
5078 } |
|
5079 } |
|
5080 } |
|
5081 |
|
5082 crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, |
|
5083 pText.len, pWrappedKey, pulWrappedKeyLen); |
|
5084 /* always force a finalize, both on errors and when |
|
5085 * we are just getting the size */ |
|
5086 if (crv != CKR_OK || pWrappedKey == NULL) { |
|
5087 CK_RV lcrv ; |
|
5088 lcrv = sftk_GetContext(hSession,&context, |
|
5089 SFTK_ENCRYPT,PR_FALSE,NULL); |
|
5090 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); |
|
5091 if (lcrv == CKR_OK && context) { |
|
5092 sftk_FreeContext(context); |
|
5093 } |
|
5094 } |
|
5095 |
|
5096 if (pText.data != (unsigned char *)attribute->attrib.pValue) |
|
5097 PORT_ZFree(pText.data, pText.len); |
|
5098 sftk_FreeAttribute(attribute); |
|
5099 break; |
|
5100 } |
|
5101 |
|
5102 case CKO_PRIVATE_KEY: |
|
5103 { |
|
5104 SECItem *bpki = sftk_PackagePrivateKey(key, &crv); |
|
5105 SFTKSessionContext *context = NULL; |
|
5106 |
|
5107 if(!bpki) { |
|
5108 break; |
|
5109 } |
|
5110 |
|
5111 crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
|
5112 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
|
5113 if(crv != CKR_OK) { |
|
5114 SECITEM_ZfreeItem(bpki, PR_TRUE); |
|
5115 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
5116 break; |
|
5117 } |
|
5118 |
|
5119 crv = NSC_Encrypt(hSession, bpki->data, bpki->len, |
|
5120 pWrappedKey, pulWrappedKeyLen); |
|
5121 /* always force a finalize */ |
|
5122 if (crv != CKR_OK || pWrappedKey == NULL) { |
|
5123 CK_RV lcrv ; |
|
5124 lcrv = sftk_GetContext(hSession,&context, |
|
5125 SFTK_ENCRYPT,PR_FALSE,NULL); |
|
5126 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); |
|
5127 if (lcrv == CKR_OK && context) { |
|
5128 sftk_FreeContext(context); |
|
5129 } |
|
5130 } |
|
5131 SECITEM_ZfreeItem(bpki, PR_TRUE); |
|
5132 break; |
|
5133 } |
|
5134 |
|
5135 default: |
|
5136 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
5137 break; |
|
5138 } |
|
5139 sftk_FreeObject(key); |
|
5140 |
|
5141 return sftk_mapWrap(crv); |
|
5142 } |
|
5143 |
|
5144 /* |
|
5145 * import a pprivate key info into the desired slot |
|
5146 */ |
|
5147 static SECStatus |
|
5148 sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) |
|
5149 { |
|
5150 CK_BBOOL cktrue = CK_TRUE; |
|
5151 CK_KEY_TYPE keyType = CKK_RSA; |
|
5152 SECStatus rv = SECFailure; |
|
5153 const SEC_ASN1Template *keyTemplate, *paramTemplate; |
|
5154 void *paramDest = NULL; |
|
5155 PLArenaPool *arena; |
|
5156 NSSLOWKEYPrivateKey *lpk = NULL; |
|
5157 NSSLOWKEYPrivateKeyInfo *pki = NULL; |
|
5158 CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; |
|
5159 |
|
5160 arena = PORT_NewArena(2048); |
|
5161 if(!arena) { |
|
5162 return SECFailure; |
|
5163 } |
|
5164 |
|
5165 pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, |
|
5166 sizeof(NSSLOWKEYPrivateKeyInfo)); |
|
5167 if(!pki) { |
|
5168 PORT_FreeArena(arena, PR_FALSE); |
|
5169 return SECFailure; |
|
5170 } |
|
5171 |
|
5172 if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) |
|
5173 != SECSuccess) { |
|
5174 PORT_FreeArena(arena, PR_TRUE); |
|
5175 return SECFailure; |
|
5176 } |
|
5177 |
|
5178 lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena, |
|
5179 sizeof(NSSLOWKEYPrivateKey)); |
|
5180 if(lpk == NULL) { |
|
5181 goto loser; |
|
5182 } |
|
5183 lpk->arena = arena; |
|
5184 |
|
5185 switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { |
|
5186 case SEC_OID_PKCS1_RSA_ENCRYPTION: |
|
5187 keyTemplate = nsslowkey_RSAPrivateKeyTemplate; |
|
5188 paramTemplate = NULL; |
|
5189 paramDest = NULL; |
|
5190 lpk->keyType = NSSLOWKEYRSAKey; |
|
5191 prepare_low_rsa_priv_key_for_asn1(lpk); |
|
5192 break; |
|
5193 case SEC_OID_ANSIX9_DSA_SIGNATURE: |
|
5194 keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; |
|
5195 paramTemplate = nsslowkey_PQGParamsTemplate; |
|
5196 paramDest = &(lpk->u.dsa.params); |
|
5197 lpk->keyType = NSSLOWKEYDSAKey; |
|
5198 prepare_low_dsa_priv_key_export_for_asn1(lpk); |
|
5199 prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); |
|
5200 break; |
|
5201 /* case NSSLOWKEYDHKey: */ |
|
5202 #ifndef NSS_DISABLE_ECC |
|
5203 case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
|
5204 keyTemplate = nsslowkey_ECPrivateKeyTemplate; |
|
5205 paramTemplate = NULL; |
|
5206 paramDest = &(lpk->u.ec.ecParams.DEREncoding); |
|
5207 lpk->keyType = NSSLOWKEYECKey; |
|
5208 prepare_low_ec_priv_key_for_asn1(lpk); |
|
5209 prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); |
|
5210 break; |
|
5211 #endif /* NSS_DISABLE_ECC */ |
|
5212 default: |
|
5213 keyTemplate = NULL; |
|
5214 paramTemplate = NULL; |
|
5215 paramDest = NULL; |
|
5216 break; |
|
5217 } |
|
5218 |
|
5219 if(!keyTemplate) { |
|
5220 goto loser; |
|
5221 } |
|
5222 |
|
5223 /* decode the private key and any algorithm parameters */ |
|
5224 rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); |
|
5225 |
|
5226 #ifndef NSS_DISABLE_ECC |
|
5227 if (lpk->keyType == NSSLOWKEYECKey) { |
|
5228 /* convert length in bits to length in bytes */ |
|
5229 lpk->u.ec.publicValue.len >>= 3; |
|
5230 rv = SECITEM_CopyItem(arena, |
|
5231 &(lpk->u.ec.ecParams.DEREncoding), |
|
5232 &(pki->algorithm.parameters)); |
|
5233 if(rv != SECSuccess) { |
|
5234 goto loser; |
|
5235 } |
|
5236 } |
|
5237 #endif /* NSS_DISABLE_ECC */ |
|
5238 |
|
5239 if(rv != SECSuccess) { |
|
5240 goto loser; |
|
5241 } |
|
5242 if(paramDest && paramTemplate) { |
|
5243 rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate, |
|
5244 &(pki->algorithm.parameters)); |
|
5245 if(rv != SECSuccess) { |
|
5246 goto loser; |
|
5247 } |
|
5248 } |
|
5249 |
|
5250 rv = SECFailure; |
|
5251 |
|
5252 switch (lpk->keyType) { |
|
5253 case NSSLOWKEYRSAKey: |
|
5254 keyType = CKK_RSA; |
|
5255 if(sftk_hasAttribute(key, CKA_NETSCAPE_DB)) { |
|
5256 sftk_DeleteAttributeType(key, CKA_NETSCAPE_DB); |
|
5257 } |
|
5258 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
|
5259 sizeof(keyType)); |
|
5260 if(crv != CKR_OK) break; |
|
5261 crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue, |
|
5262 sizeof(CK_BBOOL)); |
|
5263 if(crv != CKR_OK) break; |
|
5264 crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue, |
|
5265 sizeof(CK_BBOOL)); |
|
5266 if(crv != CKR_OK) break; |
|
5267 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
|
5268 sizeof(CK_BBOOL)); |
|
5269 if(crv != CKR_OK) break; |
|
5270 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
|
5271 sizeof(CK_BBOOL)); |
|
5272 if(crv != CKR_OK) break; |
|
5273 crv = sftk_AddAttributeType(key, CKA_MODULUS, |
|
5274 sftk_item_expand(&lpk->u.rsa.modulus)); |
|
5275 if(crv != CKR_OK) break; |
|
5276 crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT, |
|
5277 sftk_item_expand(&lpk->u.rsa.publicExponent)); |
|
5278 if(crv != CKR_OK) break; |
|
5279 crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT, |
|
5280 sftk_item_expand(&lpk->u.rsa.privateExponent)); |
|
5281 if(crv != CKR_OK) break; |
|
5282 crv = sftk_AddAttributeType(key, CKA_PRIME_1, |
|
5283 sftk_item_expand(&lpk->u.rsa.prime1)); |
|
5284 if(crv != CKR_OK) break; |
|
5285 crv = sftk_AddAttributeType(key, CKA_PRIME_2, |
|
5286 sftk_item_expand(&lpk->u.rsa.prime2)); |
|
5287 if(crv != CKR_OK) break; |
|
5288 crv = sftk_AddAttributeType(key, CKA_EXPONENT_1, |
|
5289 sftk_item_expand(&lpk->u.rsa.exponent1)); |
|
5290 if(crv != CKR_OK) break; |
|
5291 crv = sftk_AddAttributeType(key, CKA_EXPONENT_2, |
|
5292 sftk_item_expand(&lpk->u.rsa.exponent2)); |
|
5293 if(crv != CKR_OK) break; |
|
5294 crv = sftk_AddAttributeType(key, CKA_COEFFICIENT, |
|
5295 sftk_item_expand(&lpk->u.rsa.coefficient)); |
|
5296 break; |
|
5297 case NSSLOWKEYDSAKey: |
|
5298 keyType = CKK_DSA; |
|
5299 crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : |
|
5300 CKR_KEY_TYPE_INCONSISTENT; |
|
5301 if(crv != CKR_OK) break; |
|
5302 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
|
5303 sizeof(keyType)); |
|
5304 if(crv != CKR_OK) break; |
|
5305 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
|
5306 sizeof(CK_BBOOL)); |
|
5307 if(crv != CKR_OK) break; |
|
5308 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
|
5309 sizeof(CK_BBOOL)); |
|
5310 if(crv != CKR_OK) break; |
|
5311 crv = sftk_AddAttributeType(key, CKA_PRIME, |
|
5312 sftk_item_expand(&lpk->u.dsa.params.prime)); |
|
5313 if(crv != CKR_OK) break; |
|
5314 crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
|
5315 sftk_item_expand(&lpk->u.dsa.params.subPrime)); |
|
5316 if(crv != CKR_OK) break; |
|
5317 crv = sftk_AddAttributeType(key, CKA_BASE, |
|
5318 sftk_item_expand(&lpk->u.dsa.params.base)); |
|
5319 if(crv != CKR_OK) break; |
|
5320 crv = sftk_AddAttributeType(key, CKA_VALUE, |
|
5321 sftk_item_expand(&lpk->u.dsa.privateValue)); |
|
5322 if(crv != CKR_OK) break; |
|
5323 break; |
|
5324 #ifdef notdef |
|
5325 case NSSLOWKEYDHKey: |
|
5326 template = dhTemplate; |
|
5327 templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE); |
|
5328 keyType = CKK_DH; |
|
5329 break; |
|
5330 #endif |
|
5331 /* what about fortezza??? */ |
|
5332 #ifndef NSS_DISABLE_ECC |
|
5333 case NSSLOWKEYECKey: |
|
5334 keyType = CKK_EC; |
|
5335 crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : |
|
5336 CKR_KEY_TYPE_INCONSISTENT; |
|
5337 if(crv != CKR_OK) break; |
|
5338 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
|
5339 sizeof(keyType)); |
|
5340 if(crv != CKR_OK) break; |
|
5341 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
|
5342 sizeof(CK_BBOOL)); |
|
5343 if(crv != CKR_OK) break; |
|
5344 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
|
5345 sizeof(CK_BBOOL)); |
|
5346 if(crv != CKR_OK) break; |
|
5347 crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue, |
|
5348 sizeof(CK_BBOOL)); |
|
5349 if(crv != CKR_OK) break; |
|
5350 crv = sftk_AddAttributeType(key, CKA_EC_PARAMS, |
|
5351 sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding)); |
|
5352 if(crv != CKR_OK) break; |
|
5353 crv = sftk_AddAttributeType(key, CKA_VALUE, |
|
5354 sftk_item_expand(&lpk->u.ec.privateValue)); |
|
5355 if(crv != CKR_OK) break; |
|
5356 /* XXX Do we need to decode the EC Params here ?? */ |
|
5357 break; |
|
5358 #endif /* NSS_DISABLE_ECC */ |
|
5359 default: |
|
5360 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
5361 break; |
|
5362 } |
|
5363 |
|
5364 loser: |
|
5365 if(lpk) { |
|
5366 nsslowkey_DestroyPrivateKey(lpk); |
|
5367 } |
|
5368 |
|
5369 if(crv != CKR_OK) { |
|
5370 return SECFailure; |
|
5371 } |
|
5372 |
|
5373 return SECSuccess; |
|
5374 } |
|
5375 |
|
5376 |
|
5377 /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */ |
|
5378 CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, |
|
5379 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, |
|
5380 CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, |
|
5381 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
|
5382 CK_OBJECT_HANDLE_PTR phKey) |
|
5383 { |
|
5384 SFTKObject *key = NULL; |
|
5385 SFTKSession *session; |
|
5386 CK_ULONG key_length = 0; |
|
5387 unsigned char * buf = NULL; |
|
5388 CK_RV crv = CKR_OK; |
|
5389 int i; |
|
5390 CK_ULONG bsize = ulWrappedKeyLen; |
|
5391 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
|
5392 SECItem bpki; |
|
5393 CK_OBJECT_CLASS target_type = CKO_SECRET_KEY; |
|
5394 |
|
5395 CHECK_FORK(); |
|
5396 |
|
5397 if (!slot) { |
|
5398 return CKR_SESSION_HANDLE_INVALID; |
|
5399 } |
|
5400 /* |
|
5401 * now lets create an object to hang the attributes off of |
|
5402 */ |
|
5403 key = sftk_NewObject(slot); /* fill in the handle later */ |
|
5404 if (key == NULL) { |
|
5405 return CKR_HOST_MEMORY; |
|
5406 } |
|
5407 |
|
5408 /* |
|
5409 * load the template values into the object |
|
5410 */ |
|
5411 for (i=0; i < (int) ulAttributeCount; i++) { |
|
5412 if (pTemplate[i].type == CKA_VALUE_LEN) { |
|
5413 key_length = *(CK_ULONG *)pTemplate[i].pValue; |
|
5414 continue; |
|
5415 } |
|
5416 if (pTemplate[i].type == CKA_CLASS) { |
|
5417 target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; |
|
5418 } |
|
5419 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); |
|
5420 if (crv != CKR_OK) break; |
|
5421 } |
|
5422 if (crv != CKR_OK) { |
|
5423 sftk_FreeObject(key); |
|
5424 return crv; |
|
5425 } |
|
5426 |
|
5427 crv = sftk_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP, |
|
5428 CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE); |
|
5429 if (crv != CKR_OK) { |
|
5430 sftk_FreeObject(key); |
|
5431 return sftk_mapWrap(crv); |
|
5432 } |
|
5433 |
|
5434 /* allocate the buffer to decrypt into |
|
5435 * this assumes the unwrapped key is never larger than the |
|
5436 * wrapped key. For all the mechanisms we support this is true */ |
|
5437 buf = (unsigned char *)PORT_Alloc( ulWrappedKeyLen); |
|
5438 bsize = ulWrappedKeyLen; |
|
5439 |
|
5440 crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize); |
|
5441 if (crv != CKR_OK) { |
|
5442 sftk_FreeObject(key); |
|
5443 PORT_Free(buf); |
|
5444 return sftk_mapWrap(crv); |
|
5445 } |
|
5446 |
|
5447 switch(target_type) { |
|
5448 case CKO_SECRET_KEY: |
|
5449 if (!sftk_hasAttribute(key,CKA_KEY_TYPE)) { |
|
5450 crv = CKR_TEMPLATE_INCOMPLETE; |
|
5451 break; |
|
5452 } |
|
5453 |
|
5454 if (key_length == 0 || key_length > bsize) { |
|
5455 key_length = bsize; |
|
5456 } |
|
5457 if (key_length > MAX_KEY_LEN) { |
|
5458 crv = CKR_TEMPLATE_INCONSISTENT; |
|
5459 break; |
|
5460 } |
|
5461 |
|
5462 /* add the value */ |
|
5463 crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length); |
|
5464 break; |
|
5465 case CKO_PRIVATE_KEY: |
|
5466 bpki.data = (unsigned char *)buf; |
|
5467 bpki.len = bsize; |
|
5468 crv = CKR_OK; |
|
5469 if(sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) { |
|
5470 crv = CKR_TEMPLATE_INCOMPLETE; |
|
5471 } |
|
5472 break; |
|
5473 default: |
|
5474 crv = CKR_TEMPLATE_INCONSISTENT; |
|
5475 break; |
|
5476 } |
|
5477 |
|
5478 PORT_ZFree(buf, bsize); |
|
5479 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } |
|
5480 |
|
5481 /* get the session */ |
|
5482 session = sftk_SessionFromHandle(hSession); |
|
5483 if (session == NULL) { |
|
5484 sftk_FreeObject(key); |
|
5485 return CKR_SESSION_HANDLE_INVALID; |
|
5486 } |
|
5487 |
|
5488 /* |
|
5489 * handle the base object stuff |
|
5490 */ |
|
5491 crv = sftk_handleObject(key,session); |
|
5492 *phKey = key->handle; |
|
5493 sftk_FreeSession(session); |
|
5494 sftk_FreeObject(key); |
|
5495 |
|
5496 return crv; |
|
5497 |
|
5498 } |
|
5499 |
|
5500 /* |
|
5501 * The SSL key gen mechanism create's lots of keys. This function handles the |
|
5502 * details of each of these key creation. |
|
5503 */ |
|
5504 static CK_RV |
|
5505 sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, |
|
5506 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize, |
|
5507 CK_OBJECT_HANDLE *keyHandle) |
|
5508 { |
|
5509 SFTKObject *key; |
|
5510 SFTKSession *session; |
|
5511 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
|
5512 CK_BBOOL cktrue = CK_TRUE; |
|
5513 CK_BBOOL ckfalse = CK_FALSE; |
|
5514 CK_RV crv = CKR_HOST_MEMORY; |
|
5515 |
|
5516 /* |
|
5517 * now lets create an object to hang the attributes off of |
|
5518 */ |
|
5519 *keyHandle = CK_INVALID_HANDLE; |
|
5520 key = sftk_NewObject(baseKey->slot); |
|
5521 if (key == NULL) return CKR_HOST_MEMORY; |
|
5522 sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE; |
|
5523 |
|
5524 crv = sftk_CopyObject(key,baseKey); |
|
5525 if (crv != CKR_OK) goto loser; |
|
5526 if (isMacKey) { |
|
5527 crv = sftk_forceAttribute(key,CKA_KEY_TYPE,&keyType,sizeof(keyType)); |
|
5528 if (crv != CKR_OK) goto loser; |
|
5529 crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL)); |
|
5530 if (crv != CKR_OK) goto loser; |
|
5531 crv = sftk_forceAttribute(key,CKA_ENCRYPT,&ckfalse,sizeof(CK_BBOOL)); |
|
5532 if (crv != CKR_OK) goto loser; |
|
5533 crv = sftk_forceAttribute(key,CKA_DECRYPT,&ckfalse,sizeof(CK_BBOOL)); |
|
5534 if (crv != CKR_OK) goto loser; |
|
5535 crv = sftk_forceAttribute(key,CKA_SIGN,&cktrue,sizeof(CK_BBOOL)); |
|
5536 if (crv != CKR_OK) goto loser; |
|
5537 crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL)); |
|
5538 if (crv != CKR_OK) goto loser; |
|
5539 crv = sftk_forceAttribute(key,CKA_WRAP,&ckfalse,sizeof(CK_BBOOL)); |
|
5540 if (crv != CKR_OK) goto loser; |
|
5541 crv = sftk_forceAttribute(key,CKA_UNWRAP,&ckfalse,sizeof(CK_BBOOL)); |
|
5542 if (crv != CKR_OK) goto loser; |
|
5543 } |
|
5544 crv = sftk_forceAttribute(key,CKA_VALUE,keyBlock,keySize); |
|
5545 if (crv != CKR_OK) goto loser; |
|
5546 |
|
5547 /* get the session */ |
|
5548 crv = CKR_HOST_MEMORY; |
|
5549 session = sftk_SessionFromHandle(hSession); |
|
5550 if (session == NULL) { goto loser; } |
|
5551 |
|
5552 crv = sftk_handleObject(key,session); |
|
5553 sftk_FreeSession(session); |
|
5554 *keyHandle = key->handle; |
|
5555 loser: |
|
5556 if (key) sftk_FreeObject(key); |
|
5557 return crv; |
|
5558 } |
|
5559 |
|
5560 /* |
|
5561 * if there is an error, we need to free the keys we already created in SSL |
|
5562 * This is the routine that will do it.. |
|
5563 */ |
|
5564 static void |
|
5565 sftk_freeSSLKeys(CK_SESSION_HANDLE session, |
|
5566 CK_SSL3_KEY_MAT_OUT *returnedMaterial ) |
|
5567 { |
|
5568 if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { |
|
5569 NSC_DestroyObject(session,returnedMaterial->hClientMacSecret); |
|
5570 } |
|
5571 if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { |
|
5572 NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); |
|
5573 } |
|
5574 if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { |
|
5575 NSC_DestroyObject(session, returnedMaterial->hClientKey); |
|
5576 } |
|
5577 if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { |
|
5578 NSC_DestroyObject(session, returnedMaterial->hServerKey); |
|
5579 } |
|
5580 } |
|
5581 |
|
5582 /* |
|
5583 * when deriving from sensitive and extractable keys, we need to preserve some |
|
5584 * of the semantics in the derived key. This helper routine maintains these |
|
5585 * semantics. |
|
5586 */ |
|
5587 static CK_RV |
|
5588 sftk_DeriveSensitiveCheck(SFTKObject *baseKey,SFTKObject *destKey) |
|
5589 { |
|
5590 PRBool hasSensitive; |
|
5591 PRBool sensitive = PR_FALSE; |
|
5592 PRBool hasExtractable; |
|
5593 PRBool extractable = PR_TRUE; |
|
5594 CK_RV crv = CKR_OK; |
|
5595 SFTKAttribute *att; |
|
5596 |
|
5597 hasSensitive = PR_FALSE; |
|
5598 att = sftk_FindAttribute(destKey,CKA_SENSITIVE); |
|
5599 if (att) { |
|
5600 hasSensitive = PR_TRUE; |
|
5601 sensitive = (PRBool) *(CK_BBOOL *)att->attrib.pValue; |
|
5602 sftk_FreeAttribute(att); |
|
5603 } |
|
5604 |
|
5605 hasExtractable = PR_FALSE; |
|
5606 att = sftk_FindAttribute(destKey,CKA_EXTRACTABLE); |
|
5607 if (att) { |
|
5608 hasExtractable = PR_TRUE; |
|
5609 extractable = (PRBool) *(CK_BBOOL *)att->attrib.pValue; |
|
5610 sftk_FreeAttribute(att); |
|
5611 } |
|
5612 |
|
5613 |
|
5614 /* don't make a key more accessible */ |
|
5615 if (sftk_isTrue(baseKey,CKA_SENSITIVE) && hasSensitive && |
|
5616 (sensitive == PR_FALSE)) { |
|
5617 return CKR_KEY_FUNCTION_NOT_PERMITTED; |
|
5618 } |
|
5619 if (!sftk_isTrue(baseKey,CKA_EXTRACTABLE) && hasExtractable && |
|
5620 (extractable == PR_TRUE)) { |
|
5621 return CKR_KEY_FUNCTION_NOT_PERMITTED; |
|
5622 } |
|
5623 |
|
5624 /* inherit parent's sensitivity */ |
|
5625 if (!hasSensitive) { |
|
5626 att = sftk_FindAttribute(baseKey,CKA_SENSITIVE); |
|
5627 if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT; |
|
5628 crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib)); |
|
5629 sftk_FreeAttribute(att); |
|
5630 if (crv != CKR_OK) return crv; |
|
5631 } |
|
5632 if (!hasExtractable) { |
|
5633 att = sftk_FindAttribute(baseKey,CKA_EXTRACTABLE); |
|
5634 if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT; |
|
5635 crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib)); |
|
5636 sftk_FreeAttribute(att); |
|
5637 if (crv != CKR_OK) return crv; |
|
5638 } |
|
5639 |
|
5640 /* we should inherit the parent's always extractable/ never sensitive info, |
|
5641 * but handleObject always forces this attributes, so we would need to do |
|
5642 * something special. */ |
|
5643 return CKR_OK; |
|
5644 } |
|
5645 |
|
5646 /* |
|
5647 * make known fixed PKCS #11 key types to their sizes in bytes |
|
5648 */ |
|
5649 unsigned long |
|
5650 sftk_MapKeySize(CK_KEY_TYPE keyType) |
|
5651 { |
|
5652 switch (keyType) { |
|
5653 case CKK_CDMF: |
|
5654 return 8; |
|
5655 case CKK_DES: |
|
5656 return 8; |
|
5657 case CKK_DES2: |
|
5658 return 16; |
|
5659 case CKK_DES3: |
|
5660 return 24; |
|
5661 /* IDEA and CAST need to be added */ |
|
5662 default: |
|
5663 break; |
|
5664 } |
|
5665 return 0; |
|
5666 } |
|
5667 |
|
5668 #ifndef NSS_DISABLE_ECC |
|
5669 /* Inputs: |
|
5670 * key_len: Length of derived key to be generated. |
|
5671 * SharedSecret: a shared secret that is the output of a key agreement primitive. |
|
5672 * SharedInfo: (Optional) some data shared by the entities computing the secret key. |
|
5673 * SharedInfoLen: the length in octets of SharedInfo |
|
5674 * Hash: The hash function to be used in the KDF |
|
5675 * HashLen: the length in octets of the output of Hash |
|
5676 * Output: |
|
5677 * key: Pointer to a buffer containing derived key, if return value is SECSuccess. |
|
5678 */ |
|
5679 static CK_RV sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret, |
|
5680 CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
|
5681 SECStatus Hash(unsigned char *, const unsigned char *, PRUint32), |
|
5682 CK_ULONG HashLen) |
|
5683 { |
|
5684 unsigned char *buffer = NULL, *output_buffer = NULL; |
|
5685 PRUint32 buffer_len, max_counter, i; |
|
5686 SECStatus rv; |
|
5687 CK_RV crv; |
|
5688 |
|
5689 /* Check that key_len isn't too long. The maximum key length could be |
|
5690 * greatly increased if the code below did not limit the 4-byte counter |
|
5691 * to a maximum value of 255. */ |
|
5692 if (key_len > 254 * HashLen) |
|
5693 return CKR_ARGUMENTS_BAD; |
|
5694 |
|
5695 if (SharedInfo == NULL) |
|
5696 SharedInfoLen = 0; |
|
5697 |
|
5698 buffer_len = SharedSecret->len + 4 + SharedInfoLen; |
|
5699 buffer = (CK_BYTE *)PORT_Alloc(buffer_len); |
|
5700 if (buffer == NULL) { |
|
5701 crv = CKR_HOST_MEMORY; |
|
5702 goto loser; |
|
5703 } |
|
5704 |
|
5705 max_counter = key_len/HashLen; |
|
5706 if (key_len > max_counter * HashLen) |
|
5707 max_counter++; |
|
5708 |
|
5709 output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen); |
|
5710 if (output_buffer == NULL) { |
|
5711 crv = CKR_HOST_MEMORY; |
|
5712 goto loser; |
|
5713 } |
|
5714 |
|
5715 /* Populate buffer with SharedSecret || Counter || [SharedInfo] |
|
5716 * where Counter is 0x00000001 */ |
|
5717 PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len); |
|
5718 buffer[SharedSecret->len] = 0; |
|
5719 buffer[SharedSecret->len + 1] = 0; |
|
5720 buffer[SharedSecret->len + 2] = 0; |
|
5721 buffer[SharedSecret->len + 3] = 1; |
|
5722 if (SharedInfo) { |
|
5723 PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen); |
|
5724 } |
|
5725 |
|
5726 for(i=0; i < max_counter; i++) { |
|
5727 rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len); |
|
5728 if (rv != SECSuccess) { |
|
5729 /* 'Hash' should not fail. */ |
|
5730 crv = CKR_FUNCTION_FAILED; |
|
5731 goto loser; |
|
5732 } |
|
5733 |
|
5734 /* Increment counter (assumes max_counter < 255) */ |
|
5735 buffer[SharedSecret->len + 3]++; |
|
5736 } |
|
5737 |
|
5738 PORT_ZFree(buffer, buffer_len); |
|
5739 if (key_len < max_counter * HashLen) { |
|
5740 PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len); |
|
5741 } |
|
5742 *key = output_buffer; |
|
5743 |
|
5744 return CKR_OK; |
|
5745 |
|
5746 loser: |
|
5747 if (buffer) { |
|
5748 PORT_ZFree(buffer, buffer_len); |
|
5749 } |
|
5750 if (output_buffer) { |
|
5751 PORT_ZFree(output_buffer, max_counter * HashLen); |
|
5752 } |
|
5753 return crv; |
|
5754 } |
|
5755 |
|
5756 static CK_RV sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, |
|
5757 SECItem *SharedSecret, |
|
5758 CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
|
5759 CK_EC_KDF_TYPE kdf) |
|
5760 { |
|
5761 if (kdf == CKD_SHA1_KDF) |
|
5762 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
|
5763 SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH); |
|
5764 else if (kdf == CKD_SHA224_KDF) |
|
5765 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
|
5766 SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH); |
|
5767 else if (kdf == CKD_SHA256_KDF) |
|
5768 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
|
5769 SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH); |
|
5770 else if (kdf == CKD_SHA384_KDF) |
|
5771 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
|
5772 SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH); |
|
5773 else if (kdf == CKD_SHA512_KDF) |
|
5774 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
|
5775 SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH); |
|
5776 else |
|
5777 return CKR_MECHANISM_INVALID; |
|
5778 } |
|
5779 #endif /* NSS_DISABLE_ECC */ |
|
5780 |
|
5781 /* |
|
5782 * SSL Key generation given pre master secret |
|
5783 */ |
|
5784 #define NUM_MIXERS 9 |
|
5785 static const char * const mixers[NUM_MIXERS] = { |
|
5786 "A", |
|
5787 "BB", |
|
5788 "CCC", |
|
5789 "DDDD", |
|
5790 "EEEEE", |
|
5791 "FFFFFF", |
|
5792 "GGGGGGG", |
|
5793 "HHHHHHHH", |
|
5794 "IIIIIIIII" }; |
|
5795 #define SSL3_PMS_LENGTH 48 |
|
5796 #define SSL3_MASTER_SECRET_LENGTH 48 |
|
5797 #define SSL3_RANDOM_LENGTH 32 |
|
5798 |
|
5799 |
|
5800 /* NSC_DeriveKey derives a key from a base key, creating a new key object. */ |
|
5801 CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, |
|
5802 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, |
|
5803 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
|
5804 CK_OBJECT_HANDLE_PTR phKey) |
|
5805 { |
|
5806 SFTKSession * session; |
|
5807 SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession); |
|
5808 SFTKObject * key; |
|
5809 SFTKObject * sourceKey; |
|
5810 SFTKAttribute * att = NULL; |
|
5811 SFTKAttribute * att2 = NULL; |
|
5812 unsigned char * buf; |
|
5813 SHA1Context * sha; |
|
5814 MD5Context * md5; |
|
5815 MD2Context * md2; |
|
5816 CK_ULONG macSize; |
|
5817 CK_ULONG tmpKeySize; |
|
5818 CK_ULONG IVSize; |
|
5819 CK_ULONG keySize = 0; |
|
5820 CK_RV crv = CKR_OK; |
|
5821 CK_BBOOL cktrue = CK_TRUE; |
|
5822 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
|
5823 CK_OBJECT_CLASS classType = CKO_SECRET_KEY; |
|
5824 CK_KEY_DERIVATION_STRING_DATA *stringPtr; |
|
5825 PRBool isTLS = PR_FALSE; |
|
5826 PRBool isSHA256 = PR_FALSE; |
|
5827 PRBool isDH = PR_FALSE; |
|
5828 SECStatus rv; |
|
5829 int i; |
|
5830 unsigned int outLen; |
|
5831 unsigned char sha_out[SHA1_LENGTH]; |
|
5832 unsigned char key_block[NUM_MIXERS * MD5_LENGTH]; |
|
5833 unsigned char key_block2[MD5_LENGTH]; |
|
5834 PRBool isFIPS; |
|
5835 HASH_HashType hashType; |
|
5836 PRBool extractValue = PR_TRUE; |
|
5837 |
|
5838 CHECK_FORK(); |
|
5839 |
|
5840 if (!slot) { |
|
5841 return CKR_SESSION_HANDLE_INVALID; |
|
5842 } |
|
5843 /* |
|
5844 * now lets create an object to hang the attributes off of |
|
5845 */ |
|
5846 if (phKey) *phKey = CK_INVALID_HANDLE; |
|
5847 |
|
5848 key = sftk_NewObject(slot); /* fill in the handle later */ |
|
5849 if (key == NULL) { |
|
5850 return CKR_HOST_MEMORY; |
|
5851 } |
|
5852 isFIPS = (slot->slotID == FIPS_SLOT_ID); |
|
5853 |
|
5854 /* |
|
5855 * load the template values into the object |
|
5856 */ |
|
5857 for (i=0; i < (int) ulAttributeCount; i++) { |
|
5858 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); |
|
5859 if (crv != CKR_OK) break; |
|
5860 |
|
5861 if (pTemplate[i].type == CKA_KEY_TYPE) { |
|
5862 keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue; |
|
5863 } |
|
5864 if (pTemplate[i].type == CKA_VALUE_LEN) { |
|
5865 keySize = *(CK_ULONG *)pTemplate[i].pValue; |
|
5866 } |
|
5867 } |
|
5868 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } |
|
5869 |
|
5870 if (keySize == 0) { |
|
5871 keySize = sftk_MapKeySize(keyType); |
|
5872 } |
|
5873 |
|
5874 switch (pMechanism->mechanism) { |
|
5875 case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ |
|
5876 case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ |
|
5877 case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ |
|
5878 case CKM_NSS_JPAKE_ROUND2_SHA512: |
|
5879 extractValue = PR_FALSE; |
|
5880 classType = CKO_PRIVATE_KEY; |
|
5881 break; |
|
5882 case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ |
|
5883 case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ |
|
5884 case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ |
|
5885 case CKM_NSS_JPAKE_FINAL_SHA512: |
|
5886 extractValue = PR_FALSE; |
|
5887 /* fall through */ |
|
5888 default: |
|
5889 classType = CKO_SECRET_KEY; |
|
5890 } |
|
5891 |
|
5892 crv = sftk_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType)); |
|
5893 if (crv != CKR_OK) { |
|
5894 sftk_FreeObject(key); |
|
5895 return crv; |
|
5896 } |
|
5897 |
|
5898 /* look up the base key we're deriving with */ |
|
5899 session = sftk_SessionFromHandle(hSession); |
|
5900 if (session == NULL) { |
|
5901 sftk_FreeObject(key); |
|
5902 return CKR_SESSION_HANDLE_INVALID; |
|
5903 } |
|
5904 |
|
5905 sourceKey = sftk_ObjectFromHandle(hBaseKey,session); |
|
5906 sftk_FreeSession(session); |
|
5907 if (sourceKey == NULL) { |
|
5908 sftk_FreeObject(key); |
|
5909 return CKR_KEY_HANDLE_INVALID; |
|
5910 } |
|
5911 |
|
5912 if (extractValue) { |
|
5913 /* get the value of the base key */ |
|
5914 att = sftk_FindAttribute(sourceKey,CKA_VALUE); |
|
5915 if (att == NULL) { |
|
5916 sftk_FreeObject(key); |
|
5917 sftk_FreeObject(sourceKey); |
|
5918 return CKR_KEY_HANDLE_INVALID; |
|
5919 } |
|
5920 } |
|
5921 |
|
5922 switch (pMechanism->mechanism) { |
|
5923 /* |
|
5924 * generate the master secret |
|
5925 */ |
|
5926 case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: |
|
5927 case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: |
|
5928 isSHA256 = PR_TRUE; |
|
5929 /* fall thru */ |
|
5930 case CKM_TLS_MASTER_KEY_DERIVE: |
|
5931 case CKM_TLS_MASTER_KEY_DERIVE_DH: |
|
5932 isTLS = PR_TRUE; |
|
5933 /* fall thru */ |
|
5934 case CKM_SSL3_MASTER_KEY_DERIVE: |
|
5935 case CKM_SSL3_MASTER_KEY_DERIVE_DH: |
|
5936 { |
|
5937 CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; |
|
5938 SSL3RSAPreMasterSecret * rsa_pms; |
|
5939 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; |
|
5940 |
|
5941 if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || |
|
5942 (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || |
|
5943 (pMechanism->mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) |
|
5944 isDH = PR_TRUE; |
|
5945 |
|
5946 /* first do the consistancy checks */ |
|
5947 if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
|
5948 crv = CKR_KEY_TYPE_INCONSISTENT; |
|
5949 break; |
|
5950 } |
|
5951 att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); |
|
5952 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
|
5953 CKK_GENERIC_SECRET)) { |
|
5954 if (att2) sftk_FreeAttribute(att2); |
|
5955 crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
|
5956 break; |
|
5957 } |
|
5958 sftk_FreeAttribute(att2); |
|
5959 if (keyType != CKK_GENERIC_SECRET) { |
|
5960 crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
|
5961 break; |
|
5962 } |
|
5963 if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
|
5964 crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
|
5965 break; |
|
5966 } |
|
5967 |
|
5968 /* finally do the key gen */ |
|
5969 ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) |
|
5970 pMechanism->pParameter; |
|
5971 |
|
5972 PORT_Memcpy(crsrdata, |
|
5973 ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
|
5974 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, |
|
5975 ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
|
5976 |
|
5977 if (ssl3_master->pVersion) { |
|
5978 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
|
5979 rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue; |
|
5980 /* don't leak more key material then necessary for SSL to work */ |
|
5981 if ((sessKey == NULL) || sessKey->wasDerived) { |
|
5982 ssl3_master->pVersion->major = 0xff; |
|
5983 ssl3_master->pVersion->minor = 0xff; |
|
5984 } else { |
|
5985 ssl3_master->pVersion->major = rsa_pms->client_version[0]; |
|
5986 ssl3_master->pVersion->minor = rsa_pms->client_version[1]; |
|
5987 } |
|
5988 } |
|
5989 if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) { |
|
5990 crv = CKR_MECHANISM_PARAM_INVALID; |
|
5991 break; |
|
5992 } |
|
5993 if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) { |
|
5994 crv = CKR_MECHANISM_PARAM_INVALID; |
|
5995 break; |
|
5996 } |
|
5997 |
|
5998 if (isTLS) { |
|
5999 SECStatus status; |
|
6000 SECItem crsr = { siBuffer, NULL, 0 }; |
|
6001 SECItem master = { siBuffer, NULL, 0 }; |
|
6002 SECItem pms = { siBuffer, NULL, 0 }; |
|
6003 |
|
6004 crsr.data = crsrdata; |
|
6005 crsr.len = sizeof crsrdata; |
|
6006 master.data = key_block; |
|
6007 master.len = SSL3_MASTER_SECRET_LENGTH; |
|
6008 pms.data = (unsigned char*)att->attrib.pValue; |
|
6009 pms.len = att->attrib.ulValueLen; |
|
6010 |
|
6011 if (isSHA256) { |
|
6012 status = TLS_P_hash(HASH_AlgSHA256, &pms, "master secret", |
|
6013 &crsr, &master, isFIPS); |
|
6014 } else { |
|
6015 status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); |
|
6016 } |
|
6017 if (status != SECSuccess) { |
|
6018 crv = CKR_FUNCTION_FAILED; |
|
6019 break; |
|
6020 } |
|
6021 } else { |
|
6022 /* now allocate the hash contexts */ |
|
6023 md5 = MD5_NewContext(); |
|
6024 if (md5 == NULL) { |
|
6025 crv = CKR_HOST_MEMORY; |
|
6026 break; |
|
6027 } |
|
6028 sha = SHA1_NewContext(); |
|
6029 if (sha == NULL) { |
|
6030 PORT_Free(md5); |
|
6031 crv = CKR_HOST_MEMORY; |
|
6032 break; |
|
6033 } |
|
6034 for (i = 0; i < 3; i++) { |
|
6035 SHA1_Begin(sha); |
|
6036 SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i])); |
|
6037 SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, |
|
6038 att->attrib.ulValueLen); |
|
6039 SHA1_Update(sha, crsrdata, sizeof crsrdata); |
|
6040 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
|
6041 PORT_Assert(outLen == SHA1_LENGTH); |
|
6042 |
|
6043 MD5_Begin(md5); |
|
6044 MD5_Update(md5, (const unsigned char*)att->attrib.pValue, |
|
6045 att->attrib.ulValueLen); |
|
6046 MD5_Update(md5, sha_out, outLen); |
|
6047 MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH); |
|
6048 PORT_Assert(outLen == MD5_LENGTH); |
|
6049 } |
|
6050 PORT_Free(md5); |
|
6051 PORT_Free(sha); |
|
6052 } |
|
6053 |
|
6054 /* store the results */ |
|
6055 crv = sftk_forceAttribute |
|
6056 (key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH); |
|
6057 if (crv != CKR_OK) break; |
|
6058 keyType = CKK_GENERIC_SECRET; |
|
6059 crv = sftk_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType)); |
|
6060 if (isTLS) { |
|
6061 /* TLS's master secret is used to "sign" finished msgs with PRF. */ |
|
6062 /* XXX This seems like a hack. But SFTK_Derive only accepts |
|
6063 * one "operation" argument. */ |
|
6064 crv = sftk_forceAttribute(key,CKA_SIGN, &cktrue,sizeof(CK_BBOOL)); |
|
6065 if (crv != CKR_OK) break; |
|
6066 crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL)); |
|
6067 if (crv != CKR_OK) break; |
|
6068 /* While we're here, we might as well force this, too. */ |
|
6069 crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL)); |
|
6070 if (crv != CKR_OK) break; |
|
6071 } |
|
6072 break; |
|
6073 } |
|
6074 |
|
6075 case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: |
|
6076 isSHA256 = PR_TRUE; |
|
6077 /* fall thru */ |
|
6078 case CKM_TLS_KEY_AND_MAC_DERIVE: |
|
6079 isTLS = PR_TRUE; |
|
6080 /* fall thru */ |
|
6081 case CKM_SSL3_KEY_AND_MAC_DERIVE: |
|
6082 { |
|
6083 CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; |
|
6084 CK_SSL3_KEY_MAT_OUT * ssl3_keys_out; |
|
6085 CK_ULONG effKeySize; |
|
6086 unsigned int block_needed; |
|
6087 unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; |
|
6088 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; |
|
6089 |
|
6090 crv = sftk_DeriveSensitiveCheck(sourceKey,key); |
|
6091 if (crv != CKR_OK) break; |
|
6092 |
|
6093 if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { |
|
6094 crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
|
6095 break; |
|
6096 } |
|
6097 att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); |
|
6098 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
|
6099 CKK_GENERIC_SECRET)) { |
|
6100 if (att2) sftk_FreeAttribute(att2); |
|
6101 crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
|
6102 break; |
|
6103 } |
|
6104 sftk_FreeAttribute(att2); |
|
6105 md5 = MD5_NewContext(); |
|
6106 if (md5 == NULL) { |
|
6107 crv = CKR_HOST_MEMORY; |
|
6108 break; |
|
6109 } |
|
6110 sha = SHA1_NewContext(); |
|
6111 if (sha == NULL) { |
|
6112 PORT_Free(md5); |
|
6113 crv = CKR_HOST_MEMORY; |
|
6114 break; |
|
6115 } |
|
6116 ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter; |
|
6117 |
|
6118 PORT_Memcpy(srcrdata, |
|
6119 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
|
6120 PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, |
|
6121 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
|
6122 |
|
6123 PORT_Memcpy(crsrdata, |
|
6124 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
|
6125 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, |
|
6126 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
|
6127 |
|
6128 /* |
|
6129 * clear out our returned keys so we can recover on failure |
|
6130 */ |
|
6131 ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; |
|
6132 ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; |
|
6133 ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; |
|
6134 ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; |
|
6135 ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; |
|
6136 |
|
6137 /* |
|
6138 * How much key material do we need? |
|
6139 */ |
|
6140 macSize = ssl3_keys->ulMacSizeInBits/8; |
|
6141 effKeySize = ssl3_keys->ulKeySizeInBits/8; |
|
6142 IVSize = ssl3_keys->ulIVSizeInBits/8; |
|
6143 if (keySize == 0) { |
|
6144 effKeySize = keySize; |
|
6145 } |
|
6146 block_needed = 2 * (macSize + effKeySize + |
|
6147 ((!ssl3_keys->bIsExport) * IVSize)); |
|
6148 PORT_Assert(block_needed <= sizeof key_block); |
|
6149 if (block_needed > sizeof key_block) |
|
6150 block_needed = sizeof key_block; |
|
6151 |
|
6152 /* |
|
6153 * generate the key material: This looks amazingly similar to the |
|
6154 * PMS code, and is clearly crying out for a function to provide it. |
|
6155 */ |
|
6156 if (isTLS) { |
|
6157 SECStatus status; |
|
6158 SECItem srcr = { siBuffer, NULL, 0 }; |
|
6159 SECItem keyblk = { siBuffer, NULL, 0 }; |
|
6160 SECItem master = { siBuffer, NULL, 0 }; |
|
6161 |
|
6162 srcr.data = srcrdata; |
|
6163 srcr.len = sizeof srcrdata; |
|
6164 keyblk.data = key_block; |
|
6165 keyblk.len = block_needed; |
|
6166 master.data = (unsigned char*)att->attrib.pValue; |
|
6167 master.len = att->attrib.ulValueLen; |
|
6168 |
|
6169 if (isSHA256) { |
|
6170 status = TLS_P_hash(HASH_AlgSHA256, &master, "key expansion", |
|
6171 &srcr, &keyblk, isFIPS); |
|
6172 } else { |
|
6173 status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, |
|
6174 isFIPS); |
|
6175 } |
|
6176 if (status != SECSuccess) { |
|
6177 goto key_and_mac_derive_fail; |
|
6178 } |
|
6179 } else { |
|
6180 unsigned int block_bytes = 0; |
|
6181 /* key_block = |
|
6182 * MD5(master_secret + SHA('A' + master_secret + |
|
6183 * ServerHello.random + ClientHello.random)) + |
|
6184 * MD5(master_secret + SHA('BB' + master_secret + |
|
6185 * ServerHello.random + ClientHello.random)) + |
|
6186 * MD5(master_secret + SHA('CCC' + master_secret + |
|
6187 * ServerHello.random + ClientHello.random)) + |
|
6188 * [...]; |
|
6189 */ |
|
6190 for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { |
|
6191 SHA1_Begin(sha); |
|
6192 SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i])); |
|
6193 SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, |
|
6194 att->attrib.ulValueLen); |
|
6195 SHA1_Update(sha, srcrdata, sizeof srcrdata); |
|
6196 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
|
6197 PORT_Assert(outLen == SHA1_LENGTH); |
|
6198 MD5_Begin(md5); |
|
6199 MD5_Update(md5, (const unsigned char*)att->attrib.pValue, |
|
6200 att->attrib.ulValueLen); |
|
6201 MD5_Update(md5, sha_out, outLen); |
|
6202 MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH); |
|
6203 PORT_Assert(outLen == MD5_LENGTH); |
|
6204 block_bytes += outLen; |
|
6205 } |
|
6206 } |
|
6207 |
|
6208 /* |
|
6209 * Put the key material where it goes. |
|
6210 */ |
|
6211 i = 0; /* now shows how much consumed */ |
|
6212 |
|
6213 /* |
|
6214 * The key_block is partitioned as follows: |
|
6215 * client_write_MAC_secret[CipherSpec.hash_size] |
|
6216 */ |
|
6217 crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize, |
|
6218 &ssl3_keys_out->hClientMacSecret); |
|
6219 if (crv != CKR_OK) |
|
6220 goto key_and_mac_derive_fail; |
|
6221 |
|
6222 i += macSize; |
|
6223 |
|
6224 /* |
|
6225 * server_write_MAC_secret[CipherSpec.hash_size] |
|
6226 */ |
|
6227 crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize, |
|
6228 &ssl3_keys_out->hServerMacSecret); |
|
6229 if (crv != CKR_OK) { |
|
6230 goto key_and_mac_derive_fail; |
|
6231 } |
|
6232 i += macSize; |
|
6233 |
|
6234 if (keySize) { |
|
6235 if (!ssl3_keys->bIsExport) { |
|
6236 /* |
|
6237 ** Generate Domestic write keys and IVs. |
|
6238 ** client_write_key[CipherSpec.key_material] |
|
6239 */ |
|
6240 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i], |
|
6241 keySize, &ssl3_keys_out->hClientKey); |
|
6242 if (crv != CKR_OK) { |
|
6243 goto key_and_mac_derive_fail; |
|
6244 } |
|
6245 i += keySize; |
|
6246 |
|
6247 /* |
|
6248 ** server_write_key[CipherSpec.key_material] |
|
6249 */ |
|
6250 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i], |
|
6251 keySize, &ssl3_keys_out->hServerKey); |
|
6252 if (crv != CKR_OK) { |
|
6253 goto key_and_mac_derive_fail; |
|
6254 } |
|
6255 i += keySize; |
|
6256 |
|
6257 /* |
|
6258 ** client_write_IV[CipherSpec.IV_size] |
|
6259 */ |
|
6260 if (IVSize > 0) { |
|
6261 PORT_Memcpy(ssl3_keys_out->pIVClient, |
|
6262 &key_block[i], IVSize); |
|
6263 i += IVSize; |
|
6264 } |
|
6265 |
|
6266 /* |
|
6267 ** server_write_IV[CipherSpec.IV_size] |
|
6268 */ |
|
6269 if (IVSize > 0) { |
|
6270 PORT_Memcpy(ssl3_keys_out->pIVServer, |
|
6271 &key_block[i], IVSize); |
|
6272 i += IVSize; |
|
6273 } |
|
6274 PORT_Assert(i <= sizeof key_block); |
|
6275 |
|
6276 } else if (!isTLS) { |
|
6277 |
|
6278 /* |
|
6279 ** Generate SSL3 Export write keys and IVs. |
|
6280 ** client_write_key[CipherSpec.key_material] |
|
6281 ** final_client_write_key = MD5(client_write_key + |
|
6282 ** ClientHello.random + ServerHello.random); |
|
6283 */ |
|
6284 MD5_Begin(md5); |
|
6285 MD5_Update(md5, &key_block[i], effKeySize); |
|
6286 MD5_Update(md5, crsrdata, sizeof crsrdata); |
|
6287 MD5_End(md5, key_block2, &outLen, MD5_LENGTH); |
|
6288 i += effKeySize; |
|
6289 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2, |
|
6290 keySize,&ssl3_keys_out->hClientKey); |
|
6291 if (crv != CKR_OK) { |
|
6292 goto key_and_mac_derive_fail; |
|
6293 } |
|
6294 |
|
6295 /* |
|
6296 ** server_write_key[CipherSpec.key_material] |
|
6297 ** final_server_write_key = MD5(server_write_key + |
|
6298 ** ServerHello.random + ClientHello.random); |
|
6299 */ |
|
6300 MD5_Begin(md5); |
|
6301 MD5_Update(md5, &key_block[i], effKeySize); |
|
6302 MD5_Update(md5, srcrdata, sizeof srcrdata); |
|
6303 MD5_End(md5, key_block2, &outLen, MD5_LENGTH); |
|
6304 i += effKeySize; |
|
6305 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2, |
|
6306 keySize,&ssl3_keys_out->hServerKey); |
|
6307 if (crv != CKR_OK) { |
|
6308 goto key_and_mac_derive_fail; |
|
6309 } |
|
6310 |
|
6311 /* |
|
6312 ** client_write_IV = |
|
6313 ** MD5(ClientHello.random + ServerHello.random); |
|
6314 */ |
|
6315 MD5_Begin(md5); |
|
6316 MD5_Update(md5, crsrdata, sizeof crsrdata); |
|
6317 MD5_End(md5, key_block2, &outLen, MD5_LENGTH); |
|
6318 PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize); |
|
6319 |
|
6320 /* |
|
6321 ** server_write_IV = |
|
6322 ** MD5(ServerHello.random + ClientHello.random); |
|
6323 */ |
|
6324 MD5_Begin(md5); |
|
6325 MD5_Update(md5, srcrdata, sizeof srcrdata); |
|
6326 MD5_End(md5, key_block2, &outLen, MD5_LENGTH); |
|
6327 PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize); |
|
6328 |
|
6329 } else { |
|
6330 |
|
6331 /* |
|
6332 ** Generate TLS 1.0 Export write keys and IVs. |
|
6333 */ |
|
6334 SECStatus status; |
|
6335 SECItem secret = { siBuffer, NULL, 0 }; |
|
6336 SECItem crsr = { siBuffer, NULL, 0 }; |
|
6337 SECItem keyblk = { siBuffer, NULL, 0 }; |
|
6338 |
|
6339 /* |
|
6340 ** client_write_key[CipherSpec.key_material] |
|
6341 ** final_client_write_key = PRF(client_write_key, |
|
6342 ** "client write key", |
|
6343 ** client_random + server_random); |
|
6344 */ |
|
6345 secret.data = &key_block[i]; |
|
6346 secret.len = effKeySize; |
|
6347 i += effKeySize; |
|
6348 crsr.data = crsrdata; |
|
6349 crsr.len = sizeof crsrdata; |
|
6350 keyblk.data = key_block2; |
|
6351 keyblk.len = sizeof key_block2; |
|
6352 status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, |
|
6353 isFIPS); |
|
6354 if (status != SECSuccess) { |
|
6355 goto key_and_mac_derive_fail; |
|
6356 } |
|
6357 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2, |
|
6358 keySize, &ssl3_keys_out->hClientKey); |
|
6359 if (crv != CKR_OK) { |
|
6360 goto key_and_mac_derive_fail; |
|
6361 } |
|
6362 |
|
6363 /* |
|
6364 ** server_write_key[CipherSpec.key_material] |
|
6365 ** final_server_write_key = PRF(server_write_key, |
|
6366 ** "server write key", |
|
6367 ** client_random + server_random); |
|
6368 */ |
|
6369 secret.data = &key_block[i]; |
|
6370 secret.len = effKeySize; |
|
6371 i += effKeySize; |
|
6372 keyblk.data = key_block2; |
|
6373 keyblk.len = sizeof key_block2; |
|
6374 status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, |
|
6375 isFIPS); |
|
6376 if (status != SECSuccess) { |
|
6377 goto key_and_mac_derive_fail; |
|
6378 } |
|
6379 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2, |
|
6380 keySize, &ssl3_keys_out->hServerKey); |
|
6381 if (crv != CKR_OK) { |
|
6382 goto key_and_mac_derive_fail; |
|
6383 } |
|
6384 |
|
6385 /* |
|
6386 ** iv_block = PRF("", "IV block", |
|
6387 ** client_random + server_random); |
|
6388 ** client_write_IV[SecurityParameters.IV_size] |
|
6389 ** server_write_IV[SecurityParameters.IV_size] |
|
6390 */ |
|
6391 if (IVSize) { |
|
6392 secret.data = NULL; |
|
6393 secret.len = 0; |
|
6394 keyblk.data = &key_block[i]; |
|
6395 keyblk.len = 2 * IVSize; |
|
6396 status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, |
|
6397 isFIPS); |
|
6398 if (status != SECSuccess) { |
|
6399 goto key_and_mac_derive_fail; |
|
6400 } |
|
6401 PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize); |
|
6402 PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize, |
|
6403 IVSize); |
|
6404 } |
|
6405 } |
|
6406 } |
|
6407 |
|
6408 crv = CKR_OK; |
|
6409 |
|
6410 if (0) { |
|
6411 key_and_mac_derive_fail: |
|
6412 if (crv == CKR_OK) |
|
6413 crv = CKR_FUNCTION_FAILED; |
|
6414 sftk_freeSSLKeys(hSession, ssl3_keys_out); |
|
6415 } |
|
6416 MD5_DestroyContext(md5, PR_TRUE); |
|
6417 SHA1_DestroyContext(sha, PR_TRUE); |
|
6418 sftk_FreeObject(key); |
|
6419 key = NULL; |
|
6420 break; |
|
6421 } |
|
6422 |
|
6423 case CKM_CONCATENATE_BASE_AND_KEY: |
|
6424 { |
|
6425 SFTKObject *newKey; |
|
6426 |
|
6427 crv = sftk_DeriveSensitiveCheck(sourceKey,key); |
|
6428 if (crv != CKR_OK) break; |
|
6429 |
|
6430 session = sftk_SessionFromHandle(hSession); |
|
6431 if (session == NULL) { |
|
6432 crv = CKR_SESSION_HANDLE_INVALID; |
|
6433 break; |
|
6434 } |
|
6435 |
|
6436 newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *) |
|
6437 pMechanism->pParameter,session); |
|
6438 sftk_FreeSession(session); |
|
6439 if ( newKey == NULL) { |
|
6440 crv = CKR_KEY_HANDLE_INVALID; |
|
6441 break; |
|
6442 } |
|
6443 |
|
6444 if (sftk_isTrue(newKey,CKA_SENSITIVE)) { |
|
6445 crv = sftk_forceAttribute(newKey,CKA_SENSITIVE,&cktrue, |
|
6446 sizeof(CK_BBOOL)); |
|
6447 if (crv != CKR_OK) { |
|
6448 sftk_FreeObject(newKey); |
|
6449 break; |
|
6450 } |
|
6451 } |
|
6452 |
|
6453 att2 = sftk_FindAttribute(newKey,CKA_VALUE); |
|
6454 if (att2 == NULL) { |
|
6455 sftk_FreeObject(newKey); |
|
6456 crv = CKR_KEY_HANDLE_INVALID; |
|
6457 break; |
|
6458 } |
|
6459 tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen; |
|
6460 if (keySize == 0) keySize = tmpKeySize; |
|
6461 if (keySize > tmpKeySize) { |
|
6462 sftk_FreeObject(newKey); |
|
6463 sftk_FreeAttribute(att2); |
|
6464 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6465 break; |
|
6466 } |
|
6467 buf = (unsigned char*)PORT_Alloc(tmpKeySize); |
|
6468 if (buf == NULL) { |
|
6469 sftk_FreeAttribute(att2); |
|
6470 sftk_FreeObject(newKey); |
|
6471 crv = CKR_HOST_MEMORY; |
|
6472 break; |
|
6473 } |
|
6474 |
|
6475 PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen); |
|
6476 PORT_Memcpy(buf+att->attrib.ulValueLen, |
|
6477 att2->attrib.pValue,att2->attrib.ulValueLen); |
|
6478 |
|
6479 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); |
|
6480 PORT_ZFree(buf,tmpKeySize); |
|
6481 sftk_FreeAttribute(att2); |
|
6482 sftk_FreeObject(newKey); |
|
6483 break; |
|
6484 } |
|
6485 |
|
6486 case CKM_CONCATENATE_BASE_AND_DATA: |
|
6487 crv = sftk_DeriveSensitiveCheck(sourceKey,key); |
|
6488 if (crv != CKR_OK) break; |
|
6489 |
|
6490 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter; |
|
6491 tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen; |
|
6492 if (keySize == 0) keySize = tmpKeySize; |
|
6493 if (keySize > tmpKeySize) { |
|
6494 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6495 break; |
|
6496 } |
|
6497 buf = (unsigned char*)PORT_Alloc(tmpKeySize); |
|
6498 if (buf == NULL) { |
|
6499 crv = CKR_HOST_MEMORY; |
|
6500 break; |
|
6501 } |
|
6502 |
|
6503 PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen); |
|
6504 PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData, |
|
6505 stringPtr->ulLen); |
|
6506 |
|
6507 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); |
|
6508 PORT_ZFree(buf,tmpKeySize); |
|
6509 break; |
|
6510 case CKM_CONCATENATE_DATA_AND_BASE: |
|
6511 crv = sftk_DeriveSensitiveCheck(sourceKey,key); |
|
6512 if (crv != CKR_OK) break; |
|
6513 |
|
6514 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
|
6515 tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen; |
|
6516 if (keySize == 0) keySize = tmpKeySize; |
|
6517 if (keySize > tmpKeySize) { |
|
6518 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6519 break; |
|
6520 } |
|
6521 buf = (unsigned char*)PORT_Alloc(tmpKeySize); |
|
6522 if (buf == NULL) { |
|
6523 crv = CKR_HOST_MEMORY; |
|
6524 break; |
|
6525 } |
|
6526 |
|
6527 PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen); |
|
6528 PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue, |
|
6529 att->attrib.ulValueLen); |
|
6530 |
|
6531 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); |
|
6532 PORT_ZFree(buf,tmpKeySize); |
|
6533 break; |
|
6534 case CKM_XOR_BASE_AND_DATA: |
|
6535 crv = sftk_DeriveSensitiveCheck(sourceKey,key); |
|
6536 if (crv != CKR_OK) break; |
|
6537 |
|
6538 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
|
6539 tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen); |
|
6540 if (keySize == 0) keySize = tmpKeySize; |
|
6541 if (keySize > tmpKeySize) { |
|
6542 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6543 break; |
|
6544 } |
|
6545 buf = (unsigned char*)PORT_Alloc(keySize); |
|
6546 if (buf == NULL) { |
|
6547 crv = CKR_HOST_MEMORY; |
|
6548 break; |
|
6549 } |
|
6550 |
|
6551 |
|
6552 PORT_Memcpy(buf,att->attrib.pValue,keySize); |
|
6553 for (i=0; i < (int)keySize; i++) { |
|
6554 buf[i] ^= stringPtr->pData[i]; |
|
6555 } |
|
6556 |
|
6557 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); |
|
6558 PORT_ZFree(buf,keySize); |
|
6559 break; |
|
6560 |
|
6561 case CKM_EXTRACT_KEY_FROM_KEY: |
|
6562 { |
|
6563 /* the following assumes 8 bits per byte */ |
|
6564 CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter; |
|
6565 CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ |
|
6566 CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ |
|
6567 |
|
6568 crv = sftk_DeriveSensitiveCheck(sourceKey,key); |
|
6569 if (crv != CKR_OK) break; |
|
6570 |
|
6571 if (keySize == 0) { |
|
6572 crv = CKR_TEMPLATE_INCOMPLETE; |
|
6573 break; |
|
6574 } |
|
6575 /* make sure we have enough bits in the original key */ |
|
6576 if (att->attrib.ulValueLen < |
|
6577 (offset + keySize + ((shift != 0)? 1 :0)) ) { |
|
6578 crv = CKR_MECHANISM_PARAM_INVALID; |
|
6579 break; |
|
6580 } |
|
6581 buf = (unsigned char*)PORT_Alloc(keySize); |
|
6582 if (buf == NULL) { |
|
6583 crv = CKR_HOST_MEMORY; |
|
6584 break; |
|
6585 } |
|
6586 |
|
6587 /* copy the bits we need into the new key */ |
|
6588 for (i=0; i < (int)keySize; i++) { |
|
6589 unsigned char *value = |
|
6590 ((unsigned char *)att->attrib.pValue)+offset+i; |
|
6591 if (shift) { |
|
6592 buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift)); |
|
6593 } else { |
|
6594 buf[i] = value[0]; |
|
6595 } |
|
6596 } |
|
6597 |
|
6598 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); |
|
6599 PORT_ZFree(buf,keySize); |
|
6600 break; |
|
6601 } |
|
6602 case CKM_MD2_KEY_DERIVATION: |
|
6603 if (keySize == 0) keySize = MD2_LENGTH; |
|
6604 if (keySize > MD2_LENGTH) { |
|
6605 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6606 break; |
|
6607 } |
|
6608 /* now allocate the hash contexts */ |
|
6609 md2 = MD2_NewContext(); |
|
6610 if (md2 == NULL) { |
|
6611 crv = CKR_HOST_MEMORY; |
|
6612 break; |
|
6613 } |
|
6614 MD2_Begin(md2); |
|
6615 MD2_Update(md2,(const unsigned char*)att->attrib.pValue, |
|
6616 att->attrib.ulValueLen); |
|
6617 MD2_End(md2,key_block,&outLen,MD2_LENGTH); |
|
6618 MD2_DestroyContext(md2, PR_TRUE); |
|
6619 |
|
6620 crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize); |
|
6621 break; |
|
6622 case CKM_MD5_KEY_DERIVATION: |
|
6623 if (keySize == 0) keySize = MD5_LENGTH; |
|
6624 if (keySize > MD5_LENGTH) { |
|
6625 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6626 break; |
|
6627 } |
|
6628 MD5_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, |
|
6629 att->attrib.ulValueLen); |
|
6630 |
|
6631 crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize); |
|
6632 break; |
|
6633 case CKM_SHA1_KEY_DERIVATION: |
|
6634 if (keySize == 0) keySize = SHA1_LENGTH; |
|
6635 if (keySize > SHA1_LENGTH) { |
|
6636 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6637 break; |
|
6638 } |
|
6639 SHA1_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, |
|
6640 att->attrib.ulValueLen); |
|
6641 |
|
6642 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); |
|
6643 break; |
|
6644 |
|
6645 case CKM_SHA224_KEY_DERIVATION: |
|
6646 if (keySize == 0) keySize = SHA224_LENGTH; |
|
6647 if (keySize > SHA224_LENGTH) { |
|
6648 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6649 break; |
|
6650 } |
|
6651 SHA224_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, |
|
6652 att->attrib.ulValueLen); |
|
6653 |
|
6654 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); |
|
6655 break; |
|
6656 |
|
6657 case CKM_SHA256_KEY_DERIVATION: |
|
6658 if (keySize == 0) keySize = SHA256_LENGTH; |
|
6659 if (keySize > SHA256_LENGTH) { |
|
6660 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6661 break; |
|
6662 } |
|
6663 SHA256_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, |
|
6664 att->attrib.ulValueLen); |
|
6665 |
|
6666 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); |
|
6667 break; |
|
6668 |
|
6669 case CKM_SHA384_KEY_DERIVATION: |
|
6670 if (keySize == 0) keySize = SHA384_LENGTH; |
|
6671 if (keySize > SHA384_LENGTH) { |
|
6672 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6673 break; |
|
6674 } |
|
6675 SHA384_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, |
|
6676 att->attrib.ulValueLen); |
|
6677 |
|
6678 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); |
|
6679 break; |
|
6680 |
|
6681 case CKM_SHA512_KEY_DERIVATION: |
|
6682 if (keySize == 0) keySize = SHA512_LENGTH; |
|
6683 if (keySize > SHA512_LENGTH) { |
|
6684 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6685 break; |
|
6686 } |
|
6687 SHA512_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, |
|
6688 att->attrib.ulValueLen); |
|
6689 |
|
6690 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); |
|
6691 break; |
|
6692 |
|
6693 case CKM_DH_PKCS_DERIVE: |
|
6694 { |
|
6695 SECItem derived, dhPublic; |
|
6696 SECItem dhPrime, dhValue; |
|
6697 /* sourceKey - values for the local existing low key */ |
|
6698 /* get prime and value attributes */ |
|
6699 crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); |
|
6700 if (crv != SECSuccess) break; |
|
6701 crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); |
|
6702 if (crv != SECSuccess) { |
|
6703 PORT_Free(dhPrime.data); |
|
6704 break; |
|
6705 } |
|
6706 |
|
6707 dhPublic.data = pMechanism->pParameter; |
|
6708 dhPublic.len = pMechanism->ulParameterLen; |
|
6709 |
|
6710 /* calculate private value - oct */ |
|
6711 rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); |
|
6712 |
|
6713 PORT_Free(dhPrime.data); |
|
6714 PORT_Free(dhValue.data); |
|
6715 |
|
6716 if (rv == SECSuccess) { |
|
6717 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); |
|
6718 PORT_ZFree(derived.data, derived.len); |
|
6719 } else |
|
6720 crv = CKR_HOST_MEMORY; |
|
6721 |
|
6722 break; |
|
6723 } |
|
6724 |
|
6725 #ifndef NSS_DISABLE_ECC |
|
6726 case CKM_ECDH1_DERIVE: |
|
6727 case CKM_ECDH1_COFACTOR_DERIVE: |
|
6728 { |
|
6729 SECItem ecScalar, ecPoint; |
|
6730 SECItem tmp; |
|
6731 PRBool withCofactor = PR_FALSE; |
|
6732 unsigned char *secret; |
|
6733 unsigned char *keyData = NULL; |
|
6734 int secretlen, curveLen, pubKeyLen; |
|
6735 CK_ECDH1_DERIVE_PARAMS *mechParams; |
|
6736 NSSLOWKEYPrivateKey *privKey; |
|
6737 PLArenaPool *arena = NULL; |
|
6738 |
|
6739 /* Check mechanism parameters */ |
|
6740 mechParams = (CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter; |
|
6741 if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) || |
|
6742 ((mechParams->kdf == CKD_NULL) && |
|
6743 ((mechParams->ulSharedDataLen != 0) || |
|
6744 (mechParams->pSharedData != NULL)))) { |
|
6745 crv = CKR_MECHANISM_PARAM_INVALID; |
|
6746 break; |
|
6747 } |
|
6748 |
|
6749 privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv); |
|
6750 if (privKey == NULL) { |
|
6751 break; |
|
6752 } |
|
6753 |
|
6754 /* Now we are working with a non-NULL private key */ |
|
6755 SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); |
|
6756 |
|
6757 ecPoint.data = mechParams->pPublicData; |
|
6758 ecPoint.len = mechParams->ulPublicDataLen; |
|
6759 |
|
6760 curveLen = (privKey->u.ec.ecParams.fieldID.size +7)/8; |
|
6761 pubKeyLen = (2*curveLen) + 1; |
|
6762 |
|
6763 /* if the len is too small, can't be a valid point */ |
|
6764 if (ecPoint.len < pubKeyLen) { |
|
6765 goto ec_loser; |
|
6766 } |
|
6767 /* if the len is too large, must be an encoded point (length is |
|
6768 * equal case just falls through */ |
|
6769 if (ecPoint.len > pubKeyLen) { |
|
6770 SECItem newPoint; |
|
6771 |
|
6772 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
6773 if (arena == NULL) { |
|
6774 goto ec_loser; |
|
6775 } |
|
6776 |
|
6777 rv = SEC_QuickDERDecodeItem(arena, &newPoint, |
|
6778 SEC_ASN1_GET(SEC_OctetStringTemplate), |
|
6779 &ecPoint); |
|
6780 if (rv != SECSuccess) { |
|
6781 goto ec_loser; |
|
6782 } |
|
6783 ecPoint = newPoint; |
|
6784 } |
|
6785 |
|
6786 if (pMechanism->mechanism == CKM_ECDH1_COFACTOR_DERIVE) { |
|
6787 withCofactor = PR_TRUE; |
|
6788 } else { |
|
6789 /* When not using cofactor derivation, one should |
|
6790 * validate the public key to avoid small subgroup |
|
6791 * attacks. |
|
6792 */ |
|
6793 if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint) |
|
6794 != SECSuccess) { |
|
6795 goto ec_loser; |
|
6796 } |
|
6797 } |
|
6798 |
|
6799 rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, |
|
6800 withCofactor, &tmp); |
|
6801 PORT_Free(ecScalar.data); |
|
6802 ecScalar.data = NULL; |
|
6803 if (privKey != sourceKey->objectInfo) { |
|
6804 nsslowkey_DestroyPrivateKey(privKey); |
|
6805 privKey=NULL; |
|
6806 } |
|
6807 if (arena) { |
|
6808 PORT_FreeArena(arena,PR_FALSE); |
|
6809 arena=NULL; |
|
6810 } |
|
6811 |
|
6812 if (rv != SECSuccess) { |
|
6813 crv = sftk_MapCryptError(PORT_GetError()); |
|
6814 break; |
|
6815 } |
|
6816 |
|
6817 |
|
6818 /* |
|
6819 * apply the kdf function. |
|
6820 */ |
|
6821 if (mechParams->kdf == CKD_NULL) { |
|
6822 /* |
|
6823 * tmp is the raw data created by ECDH_Derive, |
|
6824 * secret and secretlen are the values we will |
|
6825 * eventually pass as our generated key. |
|
6826 */ |
|
6827 secret = tmp.data; |
|
6828 secretlen = tmp.len; |
|
6829 } else { |
|
6830 secretlen = keySize; |
|
6831 crv = sftk_ANSI_X9_63_kdf(&secret, keySize, |
|
6832 &tmp, mechParams->pSharedData, |
|
6833 mechParams->ulSharedDataLen, mechParams->kdf); |
|
6834 PORT_ZFree(tmp.data, tmp.len); |
|
6835 if (crv != CKR_OK) { |
|
6836 break; |
|
6837 } |
|
6838 tmp.data = secret; |
|
6839 tmp.len = secretlen; |
|
6840 } |
|
6841 |
|
6842 /* |
|
6843 * if keySize is supplied, then we are generating a key of a specific |
|
6844 * length. This is done by taking the least significant 'keySize' |
|
6845 * bytes from the unsigned value calculated by ECDH. Note: this may |
|
6846 * mean padding temp with extra leading zeros from what ECDH_Derive |
|
6847 * already returned (which itself may contain leading zeros). |
|
6848 */ |
|
6849 if (keySize) { |
|
6850 if (secretlen < keySize) { |
|
6851 keyData = PORT_ZAlloc(keySize); |
|
6852 if (!keyData) { |
|
6853 PORT_ZFree(tmp.data, tmp.len); |
|
6854 crv = CKR_HOST_MEMORY; |
|
6855 break; |
|
6856 } |
|
6857 PORT_Memcpy(&keyData[keySize-secretlen],secret,secretlen); |
|
6858 secret = keyData; |
|
6859 } else { |
|
6860 secret += (secretlen - keySize); |
|
6861 } |
|
6862 secretlen = keySize; |
|
6863 } |
|
6864 |
|
6865 sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); |
|
6866 PORT_ZFree(tmp.data, tmp.len); |
|
6867 if (keyData) { |
|
6868 PORT_ZFree(keyData, keySize); |
|
6869 } |
|
6870 break; |
|
6871 |
|
6872 ec_loser: |
|
6873 crv = CKR_ARGUMENTS_BAD; |
|
6874 PORT_Free(ecScalar.data); |
|
6875 if (privKey != sourceKey->objectInfo) |
|
6876 nsslowkey_DestroyPrivateKey(privKey); |
|
6877 if (arena) { |
|
6878 PORT_FreeArena(arena, PR_FALSE); |
|
6879 } |
|
6880 break; |
|
6881 |
|
6882 } |
|
6883 #endif /* NSS_DISABLE_ECC */ |
|
6884 |
|
6885 /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */ |
|
6886 case CKM_NSS_HKDF_SHA1: hashType = HASH_AlgSHA1; goto hkdf; |
|
6887 case CKM_NSS_HKDF_SHA256: hashType = HASH_AlgSHA256; goto hkdf; |
|
6888 case CKM_NSS_HKDF_SHA384: hashType = HASH_AlgSHA384; goto hkdf; |
|
6889 case CKM_NSS_HKDF_SHA512: hashType = HASH_AlgSHA512; goto hkdf; |
|
6890 hkdf: { |
|
6891 const CK_NSS_HKDFParams * params = |
|
6892 (const CK_NSS_HKDFParams *) pMechanism->pParameter; |
|
6893 const SECHashObject * rawHash; |
|
6894 unsigned hashLen; |
|
6895 CK_BYTE buf[HASH_LENGTH_MAX]; |
|
6896 CK_BYTE * prk; /* psuedo-random key */ |
|
6897 CK_ULONG prkLen; |
|
6898 CK_BYTE * okm; /* output keying material */ |
|
6899 |
|
6900 rawHash = HASH_GetRawHashObject(hashType); |
|
6901 if (rawHash == NULL || rawHash->length > sizeof buf) { |
|
6902 crv = CKR_FUNCTION_FAILED; |
|
6903 break; |
|
6904 } |
|
6905 hashLen = rawHash->length; |
|
6906 |
|
6907 if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams) || |
|
6908 !params || (!params->bExpand && !params->bExtract) || |
|
6909 (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) || |
|
6910 (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) { |
|
6911 crv = CKR_MECHANISM_PARAM_INVALID; |
|
6912 break; |
|
6913 } |
|
6914 if (keySize == 0 || keySize > sizeof key_block || |
|
6915 (!params->bExpand && keySize > hashLen) || |
|
6916 (params->bExpand && keySize > 255 * hashLen)) { |
|
6917 crv = CKR_TEMPLATE_INCONSISTENT; |
|
6918 break; |
|
6919 } |
|
6920 crv = sftk_DeriveSensitiveCheck(sourceKey, key); |
|
6921 if (crv != CKR_OK) |
|
6922 break; |
|
6923 |
|
6924 /* HKDF-Extract(salt, base key value) */ |
|
6925 if (params->bExtract) { |
|
6926 CK_BYTE * salt; |
|
6927 CK_ULONG saltLen; |
|
6928 HMACContext * hmac; |
|
6929 unsigned int bufLen; |
|
6930 |
|
6931 salt = params->pSalt; |
|
6932 saltLen = params->ulSaltLen; |
|
6933 if (salt == NULL) { |
|
6934 saltLen = hashLen; |
|
6935 salt = buf; |
|
6936 memset(salt, 0, saltLen); |
|
6937 } |
|
6938 hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); |
|
6939 if (!hmac) { |
|
6940 crv = CKR_HOST_MEMORY; |
|
6941 break; |
|
6942 } |
|
6943 HMAC_Begin(hmac); |
|
6944 HMAC_Update(hmac, (const unsigned char*) att->attrib.pValue, |
|
6945 att->attrib.ulValueLen); |
|
6946 HMAC_Finish(hmac, buf, &bufLen, sizeof(buf)); |
|
6947 HMAC_Destroy(hmac, PR_TRUE); |
|
6948 PORT_Assert(bufLen == rawHash->length); |
|
6949 prk = buf; |
|
6950 prkLen = bufLen; |
|
6951 } else { |
|
6952 /* PRK = base key value */ |
|
6953 prk = (CK_BYTE*) att->attrib.pValue; |
|
6954 prkLen = att->attrib.ulValueLen; |
|
6955 } |
|
6956 |
|
6957 /* HKDF-Expand */ |
|
6958 if (!params->bExpand) { |
|
6959 okm = prk; |
|
6960 } else { |
|
6961 /* T(1) = HMAC-Hash(prk, "" | info | 0x01) |
|
6962 * T(n) = HMAC-Hash(prk, T(n-1) | info | n |
|
6963 * key material = T(1) | ... | T(n) |
|
6964 */ |
|
6965 HMACContext * hmac; |
|
6966 CK_BYTE i; |
|
6967 unsigned iterations = PR_ROUNDUP(keySize, hashLen) / hashLen; |
|
6968 hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); |
|
6969 if (hmac == NULL) { |
|
6970 crv = CKR_HOST_MEMORY; |
|
6971 break; |
|
6972 } |
|
6973 for (i = 1; i <= iterations; ++i) { |
|
6974 unsigned len; |
|
6975 HMAC_Begin(hmac); |
|
6976 if (i > 1) { |
|
6977 HMAC_Update(hmac, key_block + ((i-2) * hashLen), hashLen); |
|
6978 } |
|
6979 if (params->ulInfoLen != 0) { |
|
6980 HMAC_Update(hmac, params->pInfo, params->ulInfoLen); |
|
6981 } |
|
6982 HMAC_Update(hmac, &i, 1); |
|
6983 HMAC_Finish(hmac, key_block + ((i-1) * hashLen), &len, |
|
6984 hashLen); |
|
6985 PORT_Assert(len == hashLen); |
|
6986 } |
|
6987 HMAC_Destroy(hmac, PR_TRUE); |
|
6988 okm = key_block; |
|
6989 } |
|
6990 /* key material = prk */ |
|
6991 crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize); |
|
6992 break; |
|
6993 } /* end of CKM_NSS_HKDF_* */ |
|
6994 |
|
6995 case CKM_NSS_JPAKE_ROUND2_SHA1: hashType = HASH_AlgSHA1; goto jpake2; |
|
6996 case CKM_NSS_JPAKE_ROUND2_SHA256: hashType = HASH_AlgSHA256; goto jpake2; |
|
6997 case CKM_NSS_JPAKE_ROUND2_SHA384: hashType = HASH_AlgSHA384; goto jpake2; |
|
6998 case CKM_NSS_JPAKE_ROUND2_SHA512: hashType = HASH_AlgSHA512; goto jpake2; |
|
6999 jpake2: |
|
7000 if (pMechanism->pParameter == NULL || |
|
7001 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params)) |
|
7002 crv = CKR_MECHANISM_PARAM_INVALID; |
|
7003 if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN)) |
|
7004 crv = CKR_TEMPLATE_INCONSISTENT; |
|
7005 if (crv == CKR_OK) |
|
7006 crv = sftk_DeriveSensitiveCheck(sourceKey, key); |
|
7007 if (crv == CKR_OK) |
|
7008 crv = jpake_Round2(hashType, |
|
7009 (CK_NSS_JPAKERound2Params *) pMechanism->pParameter, |
|
7010 sourceKey, key); |
|
7011 break; |
|
7012 |
|
7013 case CKM_NSS_JPAKE_FINAL_SHA1: hashType = HASH_AlgSHA1; goto jpakeFinal; |
|
7014 case CKM_NSS_JPAKE_FINAL_SHA256: hashType = HASH_AlgSHA256; goto jpakeFinal; |
|
7015 case CKM_NSS_JPAKE_FINAL_SHA384: hashType = HASH_AlgSHA384; goto jpakeFinal; |
|
7016 case CKM_NSS_JPAKE_FINAL_SHA512: hashType = HASH_AlgSHA512; goto jpakeFinal; |
|
7017 jpakeFinal: |
|
7018 if (pMechanism->pParameter == NULL || |
|
7019 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams)) |
|
7020 crv = CKR_MECHANISM_PARAM_INVALID; |
|
7021 /* We purposely do not do the derive sensitivity check; we want to be |
|
7022 able to derive non-sensitive keys while allowing the ROUND1 and |
|
7023 ROUND2 keys to be sensitive (which they always are, since they are |
|
7024 in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE |
|
7025 in the template in order for the resultant keyblock key to be |
|
7026 sensitive. |
|
7027 */ |
|
7028 if (crv == CKR_OK) |
|
7029 crv = jpake_Final(hashType, |
|
7030 (CK_NSS_JPAKEFinalParams *) pMechanism->pParameter, |
|
7031 sourceKey, key); |
|
7032 break; |
|
7033 |
|
7034 default: |
|
7035 crv = CKR_MECHANISM_INVALID; |
|
7036 } |
|
7037 if (att) { |
|
7038 sftk_FreeAttribute(att); |
|
7039 } |
|
7040 sftk_FreeObject(sourceKey); |
|
7041 if (crv != CKR_OK) { |
|
7042 if (key) sftk_FreeObject(key); |
|
7043 return crv; |
|
7044 } |
|
7045 |
|
7046 /* link the key object into the list */ |
|
7047 if (key) { |
|
7048 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
|
7049 PORT_Assert(sessKey); |
|
7050 /* get the session */ |
|
7051 sessKey->wasDerived = PR_TRUE; |
|
7052 session = sftk_SessionFromHandle(hSession); |
|
7053 if (session == NULL) { |
|
7054 sftk_FreeObject(key); |
|
7055 return CKR_HOST_MEMORY; |
|
7056 } |
|
7057 |
|
7058 crv = sftk_handleObject(key,session); |
|
7059 sftk_FreeSession(session); |
|
7060 *phKey = key->handle; |
|
7061 sftk_FreeObject(key); |
|
7062 } |
|
7063 return crv; |
|
7064 } |
|
7065 |
|
7066 |
|
7067 /* NSC_GetFunctionStatus obtains an updated status of a function running |
|
7068 * in parallel with an application. */ |
|
7069 CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) |
|
7070 { |
|
7071 CHECK_FORK(); |
|
7072 |
|
7073 return CKR_FUNCTION_NOT_PARALLEL; |
|
7074 } |
|
7075 |
|
7076 /* NSC_CancelFunction cancels a function running in parallel */ |
|
7077 CK_RV NSC_CancelFunction(CK_SESSION_HANDLE hSession) |
|
7078 { |
|
7079 CHECK_FORK(); |
|
7080 |
|
7081 return CKR_FUNCTION_NOT_PARALLEL; |
|
7082 } |
|
7083 |
|
7084 /* NSC_GetOperationState saves the state of the cryptographic |
|
7085 *operation in a session. |
|
7086 * NOTE: This code only works for digest functions for now. eventually need |
|
7087 * to add full flatten/resurect to our state stuff so that all types of state |
|
7088 * can be saved */ |
|
7089 CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession, |
|
7090 CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) |
|
7091 { |
|
7092 SFTKSessionContext *context; |
|
7093 SFTKSession *session; |
|
7094 CK_RV crv; |
|
7095 CK_ULONG pOSLen = *pulOperationStateLen; |
|
7096 |
|
7097 CHECK_FORK(); |
|
7098 |
|
7099 /* make sure we're legal */ |
|
7100 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
|
7101 if (crv != CKR_OK) return crv; |
|
7102 |
|
7103 *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) |
|
7104 + sizeof(SFTKContextType); |
|
7105 if (pOperationState == NULL) { |
|
7106 sftk_FreeSession(session); |
|
7107 return CKR_OK; |
|
7108 } else { |
|
7109 if (pOSLen < *pulOperationStateLen) { |
|
7110 return CKR_BUFFER_TOO_SMALL; |
|
7111 } |
|
7112 } |
|
7113 PORT_Memcpy(pOperationState,&context->type,sizeof(SFTKContextType)); |
|
7114 pOperationState += sizeof(SFTKContextType); |
|
7115 PORT_Memcpy(pOperationState,&context->currentMech, |
|
7116 sizeof(CK_MECHANISM_TYPE)); |
|
7117 pOperationState += sizeof(CK_MECHANISM_TYPE); |
|
7118 PORT_Memcpy(pOperationState,context->cipherInfo,context->cipherInfoLen); |
|
7119 sftk_FreeSession(session); |
|
7120 return CKR_OK; |
|
7121 } |
|
7122 |
|
7123 |
|
7124 #define sftk_Decrement(stateSize,len) \ |
|
7125 stateSize = ((stateSize) > (CK_ULONG)(len)) ? \ |
|
7126 ((stateSize) - (CK_ULONG)(len)) : 0; |
|
7127 |
|
7128 /* NSC_SetOperationState restores the state of the cryptographic |
|
7129 * operation in a session. This is coded like it can restore lots of |
|
7130 * states, but it only works for truly flat cipher structures. */ |
|
7131 CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession, |
|
7132 CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, |
|
7133 CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) |
|
7134 { |
|
7135 SFTKSessionContext *context; |
|
7136 SFTKSession *session; |
|
7137 SFTKContextType type; |
|
7138 CK_MECHANISM mech; |
|
7139 CK_RV crv = CKR_OK; |
|
7140 |
|
7141 CHECK_FORK(); |
|
7142 |
|
7143 while (ulOperationStateLen != 0) { |
|
7144 /* get what type of state we're dealing with... */ |
|
7145 PORT_Memcpy(&type,pOperationState, sizeof(SFTKContextType)); |
|
7146 |
|
7147 /* fix up session contexts based on type */ |
|
7148 session = sftk_SessionFromHandle(hSession); |
|
7149 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; |
|
7150 context = sftk_ReturnContextByType(session, type); |
|
7151 sftk_SetContextByType(session, type, NULL); |
|
7152 if (context) { |
|
7153 sftk_FreeContext(context); |
|
7154 } |
|
7155 pOperationState += sizeof(SFTKContextType); |
|
7156 sftk_Decrement(ulOperationStateLen,sizeof(SFTKContextType)); |
|
7157 |
|
7158 |
|
7159 /* get the mechanism structure */ |
|
7160 PORT_Memcpy(&mech.mechanism,pOperationState,sizeof(CK_MECHANISM_TYPE)); |
|
7161 pOperationState += sizeof(CK_MECHANISM_TYPE); |
|
7162 sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE)); |
|
7163 /* should be filled in... but not necessary for hash */ |
|
7164 mech.pParameter = NULL; |
|
7165 mech.ulParameterLen = 0; |
|
7166 switch (type) { |
|
7167 case SFTK_HASH: |
|
7168 crv = NSC_DigestInit(hSession,&mech); |
|
7169 if (crv != CKR_OK) break; |
|
7170 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, |
|
7171 NULL); |
|
7172 if (crv != CKR_OK) break; |
|
7173 PORT_Memcpy(context->cipherInfo,pOperationState, |
|
7174 context->cipherInfoLen); |
|
7175 pOperationState += context->cipherInfoLen; |
|
7176 sftk_Decrement(ulOperationStateLen,context->cipherInfoLen); |
|
7177 break; |
|
7178 default: |
|
7179 /* do sign/encrypt/decrypt later */ |
|
7180 crv = CKR_SAVED_STATE_INVALID; |
|
7181 } |
|
7182 sftk_FreeSession(session); |
|
7183 if (crv != CKR_OK) break; |
|
7184 } |
|
7185 return crv; |
|
7186 } |
|
7187 |
|
7188 /* Dual-function cryptographic operations */ |
|
7189 |
|
7190 /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption |
|
7191 * operation. */ |
|
7192 CK_RV NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
|
7193 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
|
7194 CK_ULONG_PTR pulEncryptedPartLen) |
|
7195 { |
|
7196 CK_RV crv; |
|
7197 |
|
7198 CHECK_FORK(); |
|
7199 |
|
7200 crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart, |
|
7201 pulEncryptedPartLen); |
|
7202 if (crv != CKR_OK) return crv; |
|
7203 crv = NSC_DigestUpdate(hSession,pPart,ulPartLen); |
|
7204 |
|
7205 return crv; |
|
7206 } |
|
7207 |
|
7208 |
|
7209 /* NSC_DecryptDigestUpdate continues a multiple-part decryption and |
|
7210 * digesting operation. */ |
|
7211 CK_RV NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, |
|
7212 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
|
7213 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
|
7214 { |
|
7215 CK_RV crv; |
|
7216 |
|
7217 CHECK_FORK(); |
|
7218 |
|
7219 crv = NSC_DecryptUpdate(hSession,pEncryptedPart, ulEncryptedPartLen, |
|
7220 pPart, pulPartLen); |
|
7221 if (crv != CKR_OK) return crv; |
|
7222 crv = NSC_DigestUpdate(hSession,pPart,*pulPartLen); |
|
7223 |
|
7224 return crv; |
|
7225 } |
|
7226 |
|
7227 |
|
7228 /* NSC_SignEncryptUpdate continues a multiple-part signing and |
|
7229 * encryption operation. */ |
|
7230 CK_RV NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
|
7231 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
|
7232 CK_ULONG_PTR pulEncryptedPartLen) |
|
7233 { |
|
7234 CK_RV crv; |
|
7235 |
|
7236 CHECK_FORK(); |
|
7237 |
|
7238 crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart, |
|
7239 pulEncryptedPartLen); |
|
7240 if (crv != CKR_OK) return crv; |
|
7241 crv = NSC_SignUpdate(hSession,pPart,ulPartLen); |
|
7242 |
|
7243 return crv; |
|
7244 } |
|
7245 |
|
7246 |
|
7247 /* NSC_DecryptVerifyUpdate continues a multiple-part decryption |
|
7248 * and verify operation. */ |
|
7249 CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, |
|
7250 CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, |
|
7251 CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
|
7252 { |
|
7253 CK_RV crv; |
|
7254 |
|
7255 CHECK_FORK(); |
|
7256 |
|
7257 crv = NSC_DecryptUpdate(hSession,pEncryptedData, ulEncryptedDataLen, |
|
7258 pData, pulDataLen); |
|
7259 if (crv != CKR_OK) return crv; |
|
7260 crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen); |
|
7261 |
|
7262 return crv; |
|
7263 } |
|
7264 |
|
7265 /* NSC_DigestKey continues a multi-part message-digesting operation, |
|
7266 * by digesting the value of a secret key as part of the data already digested. |
|
7267 */ |
|
7268 CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) |
|
7269 { |
|
7270 SFTKSession *session = NULL; |
|
7271 SFTKObject *key = NULL; |
|
7272 SFTKAttribute *att; |
|
7273 CK_RV crv; |
|
7274 |
|
7275 CHECK_FORK(); |
|
7276 |
|
7277 session = sftk_SessionFromHandle(hSession); |
|
7278 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; |
|
7279 |
|
7280 key = sftk_ObjectFromHandle(hKey,session); |
|
7281 sftk_FreeSession(session); |
|
7282 if (key == NULL) return CKR_KEY_HANDLE_INVALID; |
|
7283 |
|
7284 /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */ |
|
7285 |
|
7286 /* make sure it's a valid key for this operation */ |
|
7287 if (key->objclass != CKO_SECRET_KEY) { |
|
7288 sftk_FreeObject(key); |
|
7289 return CKR_KEY_TYPE_INCONSISTENT; |
|
7290 } |
|
7291 /* get the key value */ |
|
7292 att = sftk_FindAttribute(key,CKA_VALUE); |
|
7293 sftk_FreeObject(key); |
|
7294 if (!att) { |
|
7295 return CKR_KEY_HANDLE_INVALID; |
|
7296 } |
|
7297 crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue, |
|
7298 att->attrib.ulValueLen); |
|
7299 sftk_FreeAttribute(att); |
|
7300 return crv; |
|
7301 } |