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