/src/nss/lib/softoken/pkcs11c.c
Line | Count | Source (jump to first uncovered line) |
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 | | |
21 | | #include <limits.h> /* for UINT_MAX and ULONG_MAX */ |
22 | | |
23 | | #include "seccomon.h" |
24 | | #include "secitem.h" |
25 | | #include "secport.h" |
26 | | #include "blapi.h" |
27 | | #include "pkcs11.h" |
28 | | #include "pkcs11i.h" |
29 | | #include "pkcs1sig.h" |
30 | | #include "lowkeyi.h" |
31 | | #include "secder.h" |
32 | | #include "secdig.h" |
33 | | #include "lowpbe.h" /* We do PBE below */ |
34 | | #include "pkcs11t.h" |
35 | | #include "secoid.h" |
36 | | #include "cmac.h" |
37 | | #include "alghmac.h" |
38 | | #include "softoken.h" |
39 | | #include "secasn1.h" |
40 | | #include "secerr.h" |
41 | | #include "kem.h" |
42 | | #include "kyber.h" |
43 | | |
44 | | #include "prprf.h" |
45 | | #include "prenv.h" |
46 | | |
47 | | #define __PASTE(x, y) x##y |
48 | 25.4k | #define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize) |
49 | | /* |
50 | | * we renamed all our internal functions, get the correct |
51 | | * definitions for them... |
52 | | */ |
53 | | #undef CK_PKCS11_FUNCTION_INFO |
54 | | #undef CK_NEED_ARG_LIST |
55 | | |
56 | | #define CK_PKCS11_3_0 1 |
57 | | |
58 | | #define CK_EXTERN extern |
59 | | #define CK_PKCS11_FUNCTION_INFO(func) \ |
60 | | CK_RV __PASTE(NS, func) |
61 | | #define CK_NEED_ARG_LIST 1 |
62 | | |
63 | | #include "pkcs11f.h" |
64 | | |
65 | | /* create a definition of SHA1 that's consistent |
66 | | * with the rest of the CKM_SHAxxx hashes*/ |
67 | 217k | #define CKM_SHA1 CKM_SHA_1 |
68 | 13.3k | #define CKM_SHA1_HMAC CKM_SHA_1_HMAC |
69 | 0 | #define CKM_SHA1_HMAC_GENERAL CKM_SHA_1_HMAC_GENERAL |
70 | | |
71 | | typedef struct { |
72 | | PRUint8 client_version[2]; |
73 | | PRUint8 random[46]; |
74 | | } SSL3RSAPreMasterSecret; |
75 | | |
76 | | static void |
77 | | sftk_Null(void *data, PRBool freeit) |
78 | 18.9k | { |
79 | 18.9k | return; |
80 | 18.9k | } |
81 | | |
82 | | #ifdef EC_DEBUG |
83 | | #define SEC_PRINT(str1, str2, num, sitem) \ |
84 | | printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \ |
85 | | str1, str2, num, sitem->len); \ |
86 | | for (i = 0; i < sitem->len; i++) { \ |
87 | | printf("%02x:", sitem->data[i]); \ |
88 | | } \ |
89 | | printf("\n") |
90 | | #else |
91 | | #undef EC_DEBUG |
92 | | #define SEC_PRINT(a, b, c, d) |
93 | | #endif |
94 | | |
95 | | /* |
96 | | * free routines.... Free local type allocated data, and convert |
97 | | * other free routines to the destroy signature. |
98 | | */ |
99 | | static void |
100 | | sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit) |
101 | 0 | { |
102 | 0 | nsslowkey_DestroyPrivateKey(key); |
103 | 0 | } |
104 | | |
105 | | static void |
106 | | sftk_Space(void *data, PRBool freeit) |
107 | 34.9k | { |
108 | 34.9k | PORT_Free(data); |
109 | 34.9k | } |
110 | | |
111 | | static void |
112 | | sftk_ZSpace(void *data, PRBool freeit) |
113 | 2.86k | { |
114 | 2.86k | size_t len = *(size_t *)data; |
115 | 2.86k | PORT_ZFree(data, len); |
116 | 2.86k | } |
117 | | |
118 | | /* |
119 | | * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by |
120 | | * Deprecating a full des key to 40 bit key strenth. |
121 | | */ |
122 | | static CK_RV |
123 | | sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey) |
124 | 0 | { |
125 | 0 | unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae }; |
126 | 0 | unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 }; |
127 | 0 | unsigned char enc_src[8]; |
128 | 0 | unsigned char enc_dest[8]; |
129 | 0 | unsigned int leng, i; |
130 | 0 | DESContext *descx; |
131 | 0 | SECStatus rv; |
132 | 0 | CK_RV crv = CKR_OK; |
133 | | |
134 | | /* zero the parity bits */ |
135 | 0 | for (i = 0; i < 8; i++) { |
136 | 0 | enc_src[i] = cdmfkey[i] & 0xfe; |
137 | 0 | } |
138 | | |
139 | | /* encrypt with key 1 */ |
140 | 0 | descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE); |
141 | 0 | if (descx == NULL) { |
142 | 0 | crv = CKR_HOST_MEMORY; |
143 | 0 | goto done; |
144 | 0 | } |
145 | 0 | rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8); |
146 | 0 | DES_DestroyContext(descx, PR_TRUE); |
147 | 0 | if (rv != SECSuccess) { |
148 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
149 | 0 | goto done; |
150 | 0 | } |
151 | | |
152 | | /* xor source with des, zero the parity bits and deprecate the key*/ |
153 | 0 | for (i = 0; i < 8; i++) { |
154 | 0 | if (i & 1) { |
155 | 0 | enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe; |
156 | 0 | } else { |
157 | 0 | enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e; |
158 | 0 | } |
159 | 0 | } |
160 | | |
161 | | /* encrypt with key 2 */ |
162 | 0 | descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE); |
163 | 0 | if (descx == NULL) { |
164 | 0 | crv = CKR_HOST_MEMORY; |
165 | 0 | goto done; |
166 | 0 | } |
167 | 0 | rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8); |
168 | 0 | DES_DestroyContext(descx, PR_TRUE); |
169 | 0 | if (rv != SECSuccess) { |
170 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
171 | 0 | goto done; |
172 | 0 | } |
173 | | |
174 | | /* set the corret parity on our new des key */ |
175 | 0 | sftk_FormatDESKey(deskey, 8); |
176 | 0 | done: |
177 | 0 | PORT_Memset(enc_src, 0, sizeof enc_src); |
178 | 0 | PORT_Memset(enc_dest, 0, sizeof enc_dest); |
179 | 0 | return crv; |
180 | 0 | } |
181 | | |
182 | | /* NSC_DestroyObject destroys an object. */ |
183 | | CK_RV |
184 | | NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) |
185 | 198k | { |
186 | 198k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
187 | 198k | SFTKSession *session; |
188 | 198k | SFTKObject *object; |
189 | 198k | SFTKFreeStatus status; |
190 | | |
191 | 198k | CHECK_FORK(); |
192 | | |
193 | 198k | if (slot == NULL) { |
194 | 0 | return CKR_SESSION_HANDLE_INVALID; |
195 | 0 | } |
196 | | /* |
197 | | * This whole block just makes sure we really can destroy the |
198 | | * requested object. |
199 | | */ |
200 | 198k | session = sftk_SessionFromHandle(hSession); |
201 | 198k | if (session == NULL) { |
202 | 0 | return CKR_SESSION_HANDLE_INVALID; |
203 | 0 | } |
204 | | |
205 | 198k | object = sftk_ObjectFromHandle(hObject, session); |
206 | 198k | if (object == NULL) { |
207 | 0 | sftk_FreeSession(session); |
208 | 0 | return CKR_OBJECT_HANDLE_INVALID; |
209 | 0 | } |
210 | | |
211 | | /* don't destroy a private object if we aren't logged in */ |
212 | 198k | if ((!slot->isLoggedIn) && (slot->needLogin) && |
213 | 198k | (sftk_isTrue(object, CKA_PRIVATE))) { |
214 | 0 | sftk_FreeSession(session); |
215 | 0 | sftk_FreeObject(object); |
216 | 0 | return CKR_USER_NOT_LOGGED_IN; |
217 | 0 | } |
218 | | |
219 | | /* don't destroy a token object if we aren't in a rw session */ |
220 | | |
221 | 198k | if (((session->info.flags & CKF_RW_SESSION) == 0) && |
222 | 198k | (sftk_isTrue(object, CKA_TOKEN))) { |
223 | 0 | sftk_FreeSession(session); |
224 | 0 | sftk_FreeObject(object); |
225 | 0 | return CKR_SESSION_READ_ONLY; |
226 | 0 | } |
227 | | |
228 | 198k | sftk_DeleteObject(session, object); |
229 | | |
230 | 198k | sftk_FreeSession(session); |
231 | | |
232 | | /* |
233 | | * get some indication if the object is destroyed. Note: this is not |
234 | | * 100%. Someone may have an object reference outstanding (though that |
235 | | * should not be the case by here. Also note that the object is "half" |
236 | | * destroyed. Our internal representation is destroyed, but it may still |
237 | | * be in the data base. |
238 | | */ |
239 | 198k | status = sftk_FreeObject(object); |
240 | | |
241 | 198k | return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR; |
242 | 198k | } |
243 | | |
244 | | /* |
245 | | * Returns true if "params" contains a valid set of PSS parameters |
246 | | */ |
247 | | static PRBool |
248 | | sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params) |
249 | 2.86k | { |
250 | 2.86k | if (!params) { |
251 | 0 | return PR_FALSE; |
252 | 0 | } |
253 | 2.86k | if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL || |
254 | 2.86k | sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) { |
255 | 0 | return PR_FALSE; |
256 | 0 | } |
257 | 2.86k | return PR_TRUE; |
258 | 2.86k | } |
259 | | |
260 | | /* |
261 | | * Returns true if "params" contains a valid set of OAEP parameters |
262 | | */ |
263 | | static PRBool |
264 | | sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params) |
265 | 0 | { |
266 | 0 | if (!params) { |
267 | 0 | return PR_FALSE; |
268 | 0 | } |
269 | | /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which |
270 | | * state: |
271 | | * If the parameter is empty, pSourceData must be NULL and |
272 | | * ulSourceDataLen must be zero. |
273 | | */ |
274 | 0 | if (params->source != CKZ_DATA_SPECIFIED || |
275 | 0 | (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) || |
276 | 0 | (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) || |
277 | 0 | (params->ulSourceDataLen == 0 && params->pSourceData != NULL) || |
278 | 0 | (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) { |
279 | 0 | return PR_FALSE; |
280 | 0 | } |
281 | 0 | return PR_TRUE; |
282 | 0 | } |
283 | | |
284 | | /* |
285 | | * return a context based on the SFTKContext type. |
286 | | */ |
287 | | SFTKSessionContext * |
288 | | sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type) |
289 | 885k | { |
290 | 885k | switch (type) { |
291 | 21.3k | case SFTK_ENCRYPT: |
292 | 40.3k | case SFTK_DECRYPT: |
293 | 45.7k | case SFTK_MESSAGE_ENCRYPT: |
294 | 62.4k | case SFTK_MESSAGE_DECRYPT: |
295 | 62.4k | return session->enc_context; |
296 | 640k | case SFTK_HASH: |
297 | 640k | return session->hash_context; |
298 | 172k | case SFTK_SIGN: |
299 | 172k | case SFTK_SIGN_RECOVER: |
300 | 180k | case SFTK_VERIFY: |
301 | 182k | case SFTK_VERIFY_RECOVER: |
302 | 182k | case SFTK_MESSAGE_SIGN: |
303 | 182k | case SFTK_MESSAGE_VERIFY: |
304 | 182k | return session->hash_context; |
305 | 885k | } |
306 | 0 | return NULL; |
307 | 885k | } |
308 | | |
309 | | /* |
310 | | * change a context based on the SFTKContext type. |
311 | | */ |
312 | | void |
313 | | sftk_SetContextByType(SFTKSession *session, SFTKContextType type, |
314 | | SFTKSessionContext *context) |
315 | 448k | { |
316 | 448k | switch (type) { |
317 | 14.4k | case SFTK_ENCRYPT: |
318 | 19.6k | case SFTK_DECRYPT: |
319 | 21.9k | case SFTK_MESSAGE_ENCRYPT: |
320 | 24.2k | case SFTK_MESSAGE_DECRYPT: |
321 | 24.2k | session->enc_context = context; |
322 | 24.2k | break; |
323 | 304k | case SFTK_HASH: |
324 | 304k | session->hash_context = context; |
325 | 304k | break; |
326 | 110k | case SFTK_SIGN: |
327 | 110k | case SFTK_SIGN_RECOVER: |
328 | 118k | case SFTK_VERIFY: |
329 | 119k | case SFTK_VERIFY_RECOVER: |
330 | 119k | case SFTK_MESSAGE_SIGN: |
331 | 119k | case SFTK_MESSAGE_VERIFY: |
332 | 119k | session->hash_context = context; |
333 | 119k | break; |
334 | 448k | } |
335 | 448k | return; |
336 | 448k | } |
337 | | |
338 | | /* |
339 | | * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal, |
340 | | * and C_XXX function. The function takes a session handle, the context type, |
341 | | * and wether or not the session needs to be multipart. It returns the context, |
342 | | * and optionally returns the session pointer (if sessionPtr != NULL) if session |
343 | | * pointer is returned, the caller is responsible for freeing it. |
344 | | */ |
345 | | CK_RV |
346 | | sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr, |
347 | | SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr) |
348 | 624k | { |
349 | 624k | SFTKSession *session; |
350 | 624k | SFTKSessionContext *context; |
351 | | |
352 | 624k | session = sftk_SessionFromHandle(handle); |
353 | 624k | if (session == NULL) |
354 | 0 | return CKR_SESSION_HANDLE_INVALID; |
355 | 624k | context = sftk_ReturnContextByType(session, type); |
356 | | /* make sure the context is valid */ |
357 | 624k | if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) { |
358 | 27.2k | sftk_FreeSession(session); |
359 | 27.2k | return CKR_OPERATION_NOT_INITIALIZED; |
360 | 27.2k | } |
361 | 597k | *contextPtr = context; |
362 | 597k | if (sessionPtr != NULL) { |
363 | 262k | *sessionPtr = session; |
364 | 334k | } else { |
365 | 334k | sftk_FreeSession(session); |
366 | 334k | } |
367 | 597k | return CKR_OK; |
368 | 624k | } |
369 | | |
370 | | /** Terminate operation (in the PKCS#11 spec sense). |
371 | | * Intuitive name for FreeContext/SetNullContext pair. |
372 | | */ |
373 | | void |
374 | | sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype, |
375 | | SFTKSessionContext *context) |
376 | 187k | { |
377 | 187k | session->lastOpWasFIPS = context->isFIPS; |
378 | 187k | sftk_FreeContext(context); |
379 | 187k | sftk_SetContextByType(session, ctype, NULL); |
380 | 187k | } |
381 | | |
382 | | /* |
383 | | ************** Crypto Functions: Encrypt ************************ |
384 | | */ |
385 | | |
386 | | /* |
387 | | * All the NSC_InitXXX functions have a set of common checks and processing they |
388 | | * all need to do at the beginning. This is done here. |
389 | | */ |
390 | | CK_RV |
391 | | sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism, |
392 | | SFTKSessionContext **contextPtr, |
393 | | SFTKContextType ctype, SFTKObject **keyPtr, |
394 | | CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, |
395 | | CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation) |
396 | 240k | { |
397 | 240k | SFTKObject *key = NULL; |
398 | 240k | SFTKAttribute *att; |
399 | 240k | SFTKSessionContext *context; |
400 | | |
401 | | /* We can only init if there is not current context active */ |
402 | 240k | if (sftk_ReturnContextByType(session, ctype) != NULL) { |
403 | 0 | return CKR_OPERATION_ACTIVE; |
404 | 0 | } |
405 | | |
406 | | /* find the key */ |
407 | 240k | if (keyPtr) { |
408 | 84.8k | key = sftk_ObjectFromHandle(hKey, session); |
409 | 84.8k | if (key == NULL) { |
410 | 0 | return CKR_KEY_HANDLE_INVALID; |
411 | 0 | } |
412 | | |
413 | | /* make sure it's a valid key for this operation */ |
414 | 84.8k | if (((key->objclass != CKO_SECRET_KEY) && |
415 | 84.8k | (key->objclass != pubKeyType)) || |
416 | 84.8k | !sftk_isTrue(key, operation)) { |
417 | 0 | sftk_FreeObject(key); |
418 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
419 | 0 | } |
420 | | /* get the key type */ |
421 | 84.8k | att = sftk_FindAttribute(key, CKA_KEY_TYPE); |
422 | 84.8k | if (att == NULL) { |
423 | 0 | sftk_FreeObject(key); |
424 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
425 | 0 | } |
426 | 84.8k | PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE)); |
427 | 84.8k | if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) { |
428 | 0 | sftk_FreeAttribute(att); |
429 | 0 | sftk_FreeObject(key); |
430 | 0 | return CKR_ATTRIBUTE_VALUE_INVALID; |
431 | 0 | } |
432 | 84.8k | PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE)); |
433 | 84.8k | sftk_FreeAttribute(att); |
434 | 84.8k | *keyPtr = key; |
435 | 84.8k | } |
436 | | |
437 | | /* allocate the context structure */ |
438 | 240k | context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext)); |
439 | 240k | if (context == NULL) { |
440 | 0 | if (key) |
441 | 0 | sftk_FreeObject(key); |
442 | 0 | return CKR_HOST_MEMORY; |
443 | 0 | } |
444 | 240k | context->type = ctype; |
445 | 240k | context->multi = PR_TRUE; |
446 | 240k | context->rsa = PR_FALSE; |
447 | 240k | context->cipherInfo = NULL; |
448 | 240k | context->hashInfo = NULL; |
449 | 240k | context->doPad = PR_FALSE; |
450 | 240k | context->padDataLength = 0; |
451 | 240k | context->key = key; |
452 | 240k | context->blockSize = 0; |
453 | 240k | context->maxLen = 0; |
454 | 240k | context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism, |
455 | 240k | operation, key); |
456 | 240k | *contextPtr = context; |
457 | 240k | return CKR_OK; |
458 | 240k | } |
459 | | |
460 | | static int |
461 | | sftk_aes_mode(CK_MECHANISM_TYPE mechanism) |
462 | 6.38k | { |
463 | 6.38k | switch (mechanism) { |
464 | 153 | case CKM_AES_CBC_PAD: |
465 | 6.38k | case CKM_AES_CBC: |
466 | 6.38k | return NSS_AES_CBC; |
467 | 0 | case CKM_AES_ECB: |
468 | 0 | return NSS_AES; |
469 | 0 | case CKM_AES_CTS: |
470 | 0 | return NSS_AES_CTS; |
471 | 0 | case CKM_AES_CTR: |
472 | 0 | return NSS_AES_CTR; |
473 | 0 | case CKM_AES_GCM: |
474 | 0 | return NSS_AES_GCM; |
475 | 6.38k | } |
476 | 0 | return -1; |
477 | 6.38k | } |
478 | | |
479 | | static SECStatus |
480 | | sftk_RSAEncryptRaw(NSSLOWKEYPublicKey *key, unsigned char *output, |
481 | | unsigned int *outputLen, unsigned int maxLen, |
482 | | const unsigned char *input, unsigned int inputLen) |
483 | 0 | { |
484 | 0 | SECStatus rv = SECFailure; |
485 | |
|
486 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
487 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
488 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
489 | 0 | return SECFailure; |
490 | 0 | } |
491 | | |
492 | 0 | rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input, |
493 | 0 | inputLen); |
494 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
495 | 0 | sftk_fatalError = PR_TRUE; |
496 | 0 | } |
497 | |
|
498 | 0 | return rv; |
499 | 0 | } |
500 | | |
501 | | static SECStatus |
502 | | sftk_RSADecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, |
503 | | unsigned int *outputLen, unsigned int maxLen, |
504 | | const unsigned char *input, unsigned int inputLen) |
505 | 0 | { |
506 | 0 | SECStatus rv = SECFailure; |
507 | |
|
508 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
509 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
510 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
511 | 0 | return SECFailure; |
512 | 0 | } |
513 | | |
514 | 0 | rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input, |
515 | 0 | inputLen); |
516 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
517 | 0 | sftk_fatalError = PR_TRUE; |
518 | 0 | } |
519 | |
|
520 | 0 | return rv; |
521 | 0 | } |
522 | | |
523 | | static SECStatus |
524 | | sftk_RSAEncrypt(NSSLOWKEYPublicKey *key, unsigned char *output, |
525 | | unsigned int *outputLen, unsigned int maxLen, |
526 | | const unsigned char *input, unsigned int inputLen) |
527 | 2.73k | { |
528 | 2.73k | SECStatus rv = SECFailure; |
529 | | |
530 | 2.73k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
531 | 2.73k | if (key->keyType != NSSLOWKEYRSAKey) { |
532 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
533 | 0 | return SECFailure; |
534 | 0 | } |
535 | | |
536 | 2.73k | rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
537 | 2.73k | inputLen); |
538 | 2.73k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
539 | 0 | sftk_fatalError = PR_TRUE; |
540 | 0 | } |
541 | | |
542 | 2.73k | return rv; |
543 | 2.73k | } |
544 | | |
545 | | static SECStatus |
546 | | sftk_RSADecrypt(NSSLOWKEYPrivateKey *key, unsigned char *output, |
547 | | unsigned int *outputLen, unsigned int maxLen, |
548 | | const unsigned char *input, unsigned int inputLen) |
549 | 47 | { |
550 | 47 | SECStatus rv = SECFailure; |
551 | | |
552 | 47 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
553 | 47 | if (key->keyType != NSSLOWKEYRSAKey) { |
554 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
555 | 0 | return SECFailure; |
556 | 0 | } |
557 | | |
558 | 47 | rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
559 | 47 | inputLen); |
560 | 47 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
561 | 0 | sftk_fatalError = PR_TRUE; |
562 | 0 | } |
563 | | |
564 | 47 | return rv; |
565 | 47 | } |
566 | | |
567 | | static void |
568 | | sftk_freeRSAOAEPInfo(SFTKOAEPInfo *info, PRBool freeit) |
569 | 0 | { |
570 | 0 | PORT_ZFree(info->params.pSourceData, info->params.ulSourceDataLen); |
571 | 0 | PORT_ZFree(info, sizeof(SFTKOAEPInfo)); |
572 | 0 | } |
573 | | |
574 | | static SECStatus |
575 | | sftk_RSAEncryptOAEP(SFTKOAEPInfo *info, unsigned char *output, |
576 | | unsigned int *outputLen, unsigned int maxLen, |
577 | | const unsigned char *input, unsigned int inputLen) |
578 | 0 | { |
579 | 0 | HASH_HashType hashAlg; |
580 | 0 | HASH_HashType maskHashAlg; |
581 | |
|
582 | 0 | PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey); |
583 | 0 | if (info->key.pub->keyType != NSSLOWKEYRSAKey) { |
584 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
585 | 0 | return SECFailure; |
586 | 0 | } |
587 | | |
588 | 0 | hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg); |
589 | 0 | maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf); |
590 | |
|
591 | 0 | return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg, |
592 | 0 | (const unsigned char *)info->params.pSourceData, |
593 | 0 | info->params.ulSourceDataLen, NULL, 0, |
594 | 0 | output, outputLen, maxLen, input, inputLen); |
595 | 0 | } |
596 | | |
597 | | static SECStatus |
598 | | sftk_RSADecryptOAEP(SFTKOAEPInfo *info, unsigned char *output, |
599 | | unsigned int *outputLen, unsigned int maxLen, |
600 | | const unsigned char *input, unsigned int inputLen) |
601 | 0 | { |
602 | 0 | SECStatus rv = SECFailure; |
603 | 0 | HASH_HashType hashAlg; |
604 | 0 | HASH_HashType maskHashAlg; |
605 | |
|
606 | 0 | PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey); |
607 | 0 | if (info->key.priv->keyType != NSSLOWKEYRSAKey) { |
608 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
609 | 0 | return SECFailure; |
610 | 0 | } |
611 | | |
612 | 0 | hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg); |
613 | 0 | maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf); |
614 | |
|
615 | 0 | rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg, |
616 | 0 | (const unsigned char *)info->params.pSourceData, |
617 | 0 | info->params.ulSourceDataLen, |
618 | 0 | output, outputLen, maxLen, input, inputLen); |
619 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
620 | 0 | sftk_fatalError = PR_TRUE; |
621 | 0 | } |
622 | 0 | return rv; |
623 | 0 | } |
624 | | |
625 | | static SFTKChaCha20Poly1305Info * |
626 | | sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key, |
627 | | unsigned int keyLen, |
628 | | const CK_NSS_AEAD_PARAMS *params) |
629 | 0 | { |
630 | 0 | SFTKChaCha20Poly1305Info *ctx; |
631 | |
|
632 | 0 | if (params->ulNonceLen != sizeof(ctx->nonce)) { |
633 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
634 | 0 | return NULL; |
635 | 0 | } |
636 | | |
637 | 0 | ctx = PORT_New(SFTKChaCha20Poly1305Info); |
638 | 0 | if (ctx == NULL) { |
639 | 0 | return NULL; |
640 | 0 | } |
641 | | |
642 | 0 | if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen, |
643 | 0 | params->ulTagLen) != SECSuccess) { |
644 | 0 | PORT_Free(ctx); |
645 | 0 | return NULL; |
646 | 0 | } |
647 | | |
648 | 0 | PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce)); |
649 | | |
650 | | /* AAD data and length must both be null, or both non-null. */ |
651 | 0 | PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0)); |
652 | |
|
653 | 0 | if (params->ulAADLen > sizeof(ctx->ad)) { |
654 | | /* Need to allocate an overflow buffer for the additional data. */ |
655 | 0 | ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen); |
656 | 0 | if (!ctx->adOverflow) { |
657 | 0 | PORT_Free(ctx); |
658 | 0 | return NULL; |
659 | 0 | } |
660 | 0 | PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen); |
661 | 0 | } else { |
662 | 0 | ctx->adOverflow = NULL; |
663 | 0 | if (params->pAAD) { |
664 | 0 | PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen); |
665 | 0 | } |
666 | 0 | } |
667 | 0 | ctx->adLen = params->ulAADLen; |
668 | |
|
669 | 0 | return ctx; |
670 | 0 | } |
671 | | |
672 | | static void |
673 | | sftk_ChaCha20Poly1305_DestroyContext(SFTKChaCha20Poly1305Info *ctx, |
674 | | PRBool freeit) |
675 | 0 | { |
676 | 0 | ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE); |
677 | 0 | if (ctx->adOverflow != NULL) { |
678 | 0 | PORT_ZFree(ctx->adOverflow, ctx->adLen); |
679 | 0 | ctx->adOverflow = NULL; |
680 | 0 | } else { |
681 | 0 | PORT_Memset(ctx->ad, 0, ctx->adLen); |
682 | 0 | } |
683 | 0 | ctx->adLen = 0; |
684 | 0 | if (freeit) { |
685 | 0 | PORT_Free(ctx); |
686 | 0 | } |
687 | 0 | } |
688 | | |
689 | | static SECStatus |
690 | | sftk_ChaCha20Poly1305_Encrypt(const SFTKChaCha20Poly1305Info *ctx, |
691 | | unsigned char *output, unsigned int *outputLen, |
692 | | unsigned int maxOutputLen, |
693 | | const unsigned char *input, unsigned int inputLen) |
694 | 0 | { |
695 | 0 | const unsigned char *ad = ctx->adOverflow; |
696 | |
|
697 | 0 | if (ad == NULL) { |
698 | 0 | ad = ctx->ad; |
699 | 0 | } |
700 | |
|
701 | 0 | return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen, |
702 | 0 | maxOutputLen, input, inputLen, ctx->nonce, |
703 | 0 | sizeof(ctx->nonce), ad, ctx->adLen); |
704 | 0 | } |
705 | | |
706 | | static SECStatus |
707 | | sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info *ctx, |
708 | | unsigned char *output, unsigned int *outputLen, |
709 | | unsigned int maxOutputLen, |
710 | | const unsigned char *input, unsigned int inputLen) |
711 | 0 | { |
712 | 0 | const unsigned char *ad = ctx->adOverflow; |
713 | |
|
714 | 0 | if (ad == NULL) { |
715 | 0 | ad = ctx->ad; |
716 | 0 | } |
717 | |
|
718 | 0 | return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen, |
719 | 0 | maxOutputLen, input, inputLen, ctx->nonce, |
720 | 0 | sizeof(ctx->nonce), ad, ctx->adLen); |
721 | 0 | } |
722 | | |
723 | | static SECStatus |
724 | | sftk_ChaCha20Ctr(const SFTKChaCha20CtrInfo *ctx, |
725 | | unsigned char *output, unsigned int *outputLen, |
726 | | unsigned int maxOutputLen, |
727 | | const unsigned char *input, unsigned int inputLen) |
728 | 0 | { |
729 | 0 | if (maxOutputLen < inputLen) { |
730 | 0 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
731 | 0 | return SECFailure; |
732 | 0 | } |
733 | 0 | ChaCha20_Xor(output, input, inputLen, ctx->key, |
734 | 0 | ctx->nonce, ctx->counter); |
735 | 0 | *outputLen = inputLen; |
736 | 0 | return SECSuccess; |
737 | 0 | } |
738 | | |
739 | | static void |
740 | | sftk_ChaCha20Ctr_DestroyContext(SFTKChaCha20CtrInfo *ctx, |
741 | | PRBool freeit) |
742 | 0 | { |
743 | 0 | memset(ctx, 0, sizeof(*ctx)); |
744 | 0 | if (freeit) { |
745 | 0 | PORT_Free(ctx); |
746 | 0 | } |
747 | 0 | } |
748 | | |
749 | | /** NSC_CryptInit initializes an encryption/Decryption operation. |
750 | | * |
751 | | * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. |
752 | | * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block |
753 | | * ciphers MAC'ing. |
754 | | */ |
755 | | CK_RV |
756 | | sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
757 | | CK_OBJECT_HANDLE hKey, |
758 | | CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage, |
759 | | SFTKContextType contextType, PRBool isEncrypt) |
760 | 15.0k | { |
761 | 15.0k | SFTKSession *session; |
762 | 15.0k | SFTKObject *key; |
763 | 15.0k | SFTKSessionContext *context; |
764 | 15.0k | SFTKAttribute *att; |
765 | 15.0k | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
766 | 15.0k | CK_RC2_CBC_PARAMS *rc2_param; |
767 | 15.0k | unsigned effectiveKeyLength; |
768 | 15.0k | #endif |
769 | | #if NSS_SOFTOKEN_DOES_RC5 |
770 | | CK_RC5_CBC_PARAMS *rc5_param; |
771 | | SECItem rc5Key; |
772 | | #endif |
773 | 15.0k | CK_NSS_GCM_PARAMS nss_gcm_param; |
774 | 15.0k | void *aes_param; |
775 | 15.0k | CK_NSS_AEAD_PARAMS nss_aead_params; |
776 | 15.0k | CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL; |
777 | 15.0k | CK_KEY_TYPE key_type; |
778 | 15.0k | CK_RV crv = CKR_OK; |
779 | 15.0k | unsigned char newdeskey[24]; |
780 | 15.0k | PRBool useNewKey = PR_FALSE; |
781 | 15.0k | int t; |
782 | | |
783 | 15.0k | if (!pMechanism) { |
784 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
785 | 0 | } |
786 | | |
787 | 15.0k | crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage); |
788 | 15.0k | if (crv != CKR_OK) |
789 | 18 | return crv; |
790 | | |
791 | 15.0k | session = sftk_SessionFromHandle(hSession); |
792 | 15.0k | if (session == NULL) |
793 | 0 | return CKR_SESSION_HANDLE_INVALID; |
794 | | |
795 | 15.0k | crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key, |
796 | 15.0k | hKey, &key_type, |
797 | 15.0k | isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY, |
798 | 15.0k | keyUsage); |
799 | | |
800 | 15.0k | if (crv != CKR_OK) { |
801 | 0 | sftk_FreeSession(session); |
802 | 0 | return crv; |
803 | 0 | } |
804 | | |
805 | 15.0k | context->doPad = PR_FALSE; |
806 | 15.0k | switch (pMechanism->mechanism) { |
807 | 2.78k | case CKM_RSA_PKCS: |
808 | 2.78k | case CKM_RSA_X_509: |
809 | 2.78k | if (key_type != CKK_RSA) { |
810 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
811 | 0 | break; |
812 | 0 | } |
813 | 2.78k | context->multi = PR_FALSE; |
814 | 2.78k | context->rsa = PR_TRUE; |
815 | 2.78k | if (isEncrypt) { |
816 | 2.73k | NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
817 | 2.73k | if (pubKey == NULL) { |
818 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
819 | 0 | break; |
820 | 0 | } |
821 | 2.73k | context->maxLen = nsslowkey_PublicModulusLen(pubKey); |
822 | 2.73k | context->cipherInfo = (void *)pubKey; |
823 | 2.73k | context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509 |
824 | 2.73k | ? sftk_RSAEncryptRaw |
825 | 2.73k | : sftk_RSAEncrypt); |
826 | 2.73k | } else { |
827 | 47 | NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); |
828 | 47 | if (privKey == NULL) { |
829 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
830 | 0 | break; |
831 | 0 | } |
832 | 47 | context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
833 | 47 | context->cipherInfo = (void *)privKey; |
834 | 47 | context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509 |
835 | 47 | ? sftk_RSADecryptRaw |
836 | 47 | : sftk_RSADecrypt); |
837 | 47 | } |
838 | 2.78k | context->destroy = sftk_Null; |
839 | 2.78k | break; |
840 | 0 | case CKM_RSA_PKCS_OAEP: |
841 | 0 | if (key_type != CKK_RSA) { |
842 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
843 | 0 | break; |
844 | 0 | } |
845 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) || |
846 | 0 | !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) { |
847 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
848 | 0 | break; |
849 | 0 | } |
850 | 0 | context->multi = PR_FALSE; |
851 | 0 | context->rsa = PR_TRUE; |
852 | 0 | { |
853 | 0 | SFTKOAEPInfo *info; |
854 | 0 | CK_RSA_PKCS_OAEP_PARAMS *params = |
855 | 0 | (CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter; |
856 | | /* make a copy of the source data value for future |
857 | | * use (once the user has reclaimed his data in pParameter)*/ |
858 | 0 | void *newSource = NULL; |
859 | 0 | if (params->pSourceData) { |
860 | 0 | newSource = PORT_Alloc(params->ulSourceDataLen); |
861 | 0 | if (newSource == NULL) { |
862 | 0 | crv = CKR_HOST_MEMORY; |
863 | 0 | break; |
864 | 0 | } |
865 | 0 | PORT_Memcpy(newSource, params->pSourceData, params->ulSourceDataLen); |
866 | 0 | } |
867 | 0 | info = PORT_New(SFTKOAEPInfo); |
868 | 0 | if (info == NULL) { |
869 | 0 | PORT_ZFree(newSource, params->ulSourceDataLen); |
870 | 0 | crv = CKR_HOST_MEMORY; |
871 | 0 | break; |
872 | 0 | } |
873 | 0 | info->params = *params; |
874 | 0 | info->params.pSourceData = newSource; |
875 | 0 | info->isEncrypt = isEncrypt; |
876 | | |
877 | | /* now setup encryption and decryption contexts */ |
878 | 0 | if (isEncrypt) { |
879 | 0 | info->key.pub = sftk_GetPubKey(key, CKK_RSA, &crv); |
880 | 0 | if (info->key.pub == NULL) { |
881 | 0 | sftk_freeRSAOAEPInfo(info, PR_TRUE); |
882 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
883 | 0 | break; |
884 | 0 | } |
885 | 0 | context->update = (SFTKCipher)sftk_RSAEncryptOAEP; |
886 | 0 | context->maxLen = nsslowkey_PublicModulusLen(info->key.pub); |
887 | 0 | } else { |
888 | 0 | info->key.priv = sftk_GetPrivKey(key, CKK_RSA, &crv); |
889 | 0 | if (info->key.priv == NULL) { |
890 | 0 | sftk_freeRSAOAEPInfo(info, PR_TRUE); |
891 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
892 | 0 | break; |
893 | 0 | } |
894 | 0 | context->update = (SFTKCipher)sftk_RSADecryptOAEP; |
895 | 0 | context->maxLen = nsslowkey_PrivateModulusLen(info->key.priv); |
896 | 0 | } |
897 | 0 | context->cipherInfo = info; |
898 | 0 | } |
899 | 0 | context->destroy = (SFTKDestroy)sftk_freeRSAOAEPInfo; |
900 | 0 | break; |
901 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
902 | 0 | case CKM_RC2_CBC_PAD: |
903 | 0 | context->doPad = PR_TRUE; |
904 | | /* fall thru */ |
905 | 0 | case CKM_RC2_ECB: |
906 | 0 | case CKM_RC2_CBC: |
907 | 0 | context->blockSize = 8; |
908 | 0 | if (key_type != CKK_RC2) { |
909 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
910 | 0 | break; |
911 | 0 | } |
912 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
913 | 0 | if (att == NULL) { |
914 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
915 | 0 | break; |
916 | 0 | } |
917 | | |
918 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) { |
919 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
920 | 0 | break; |
921 | 0 | } |
922 | 0 | rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; |
923 | 0 | effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8; |
924 | 0 | context->cipherInfo = |
925 | 0 | RC2_CreateContext((unsigned char *)att->attrib.pValue, |
926 | 0 | att->attrib.ulValueLen, rc2_param->iv, |
927 | 0 | pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength); |
928 | 0 | sftk_FreeAttribute(att); |
929 | 0 | if (context->cipherInfo == NULL) { |
930 | 0 | crv = CKR_HOST_MEMORY; |
931 | 0 | break; |
932 | 0 | } |
933 | 0 | context->update = (SFTKCipher)(isEncrypt ? RC2_Encrypt : RC2_Decrypt); |
934 | 0 | context->destroy = (SFTKDestroy)RC2_DestroyContext; |
935 | 0 | break; |
936 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
937 | | |
938 | | #if NSS_SOFTOKEN_DOES_RC5 |
939 | | case CKM_RC5_CBC_PAD: |
940 | | context->doPad = PR_TRUE; |
941 | | /* fall thru */ |
942 | | case CKM_RC5_ECB: |
943 | | case CKM_RC5_CBC: |
944 | | if (key_type != CKK_RC5) { |
945 | | crv = CKR_KEY_TYPE_INCONSISTENT; |
946 | | break; |
947 | | } |
948 | | att = sftk_FindAttribute(key, CKA_VALUE); |
949 | | if (att == NULL) { |
950 | | crv = CKR_KEY_HANDLE_INVALID; |
951 | | break; |
952 | | } |
953 | | |
954 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) { |
955 | | crv = CKR_MECHANISM_PARAM_INVALID; |
956 | | break; |
957 | | } |
958 | | rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; |
959 | | context->blockSize = rc5_param->ulWordsize * 2; |
960 | | rc5Key.data = (unsigned char *)att->attrib.pValue; |
961 | | rc5Key.len = att->attrib.ulValueLen; |
962 | | context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds, |
963 | | rc5_param->ulWordsize, rc5_param->pIv, |
964 | | pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); |
965 | | sftk_FreeAttribute(att); |
966 | | if (context->cipherInfo == NULL) { |
967 | | crv = CKR_HOST_MEMORY; |
968 | | break; |
969 | | } |
970 | | context->update = (SFTKCipher)(isEncrypt ? RC5_Encrypt : RC5_Decrypt); |
971 | | context->destroy = (SFTKDestroy)RC5_DestroyContext; |
972 | | break; |
973 | | #endif |
974 | 498 | case CKM_RC4: |
975 | 498 | if (key_type != CKK_RC4) { |
976 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
977 | 0 | break; |
978 | 0 | } |
979 | 498 | att = sftk_FindAttribute(key, CKA_VALUE); |
980 | 498 | if (att == NULL) { |
981 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
982 | 0 | break; |
983 | 0 | } |
984 | 498 | context->cipherInfo = |
985 | 498 | RC4_CreateContext((unsigned char *)att->attrib.pValue, |
986 | 498 | att->attrib.ulValueLen); |
987 | 498 | sftk_FreeAttribute(att); |
988 | 498 | if (context->cipherInfo == NULL) { |
989 | 0 | crv = CKR_HOST_MEMORY; /* WRONG !!! */ |
990 | 0 | break; |
991 | 0 | } |
992 | 498 | context->update = (SFTKCipher)(isEncrypt ? RC4_Encrypt : RC4_Decrypt); |
993 | 498 | context->destroy = (SFTKDestroy)RC4_DestroyContext; |
994 | 498 | break; |
995 | 0 | case CKM_CDMF_CBC_PAD: |
996 | 0 | context->doPad = PR_TRUE; |
997 | | /* fall thru */ |
998 | 0 | case CKM_CDMF_ECB: |
999 | 0 | case CKM_CDMF_CBC: |
1000 | 0 | if (key_type != CKK_CDMF) { |
1001 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1002 | 0 | break; |
1003 | 0 | } |
1004 | 0 | t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; |
1005 | 0 | goto finish_des; |
1006 | 0 | case CKM_DES_ECB: |
1007 | 0 | if (key_type != CKK_DES) { |
1008 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1009 | 0 | break; |
1010 | 0 | } |
1011 | 0 | t = NSS_DES; |
1012 | 0 | goto finish_des; |
1013 | 0 | case CKM_DES_CBC_PAD: |
1014 | 0 | context->doPad = PR_TRUE; |
1015 | | /* fall thru */ |
1016 | 356 | case CKM_DES_CBC: |
1017 | 356 | if (key_type != CKK_DES) { |
1018 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1019 | 0 | break; |
1020 | 0 | } |
1021 | 356 | t = NSS_DES_CBC; |
1022 | 356 | goto finish_des; |
1023 | 1.73k | case CKM_DES3_ECB: |
1024 | 1.73k | if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
1025 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1026 | 0 | break; |
1027 | 0 | } |
1028 | 1.73k | t = NSS_DES_EDE3; |
1029 | 1.73k | goto finish_des; |
1030 | 0 | case CKM_DES3_CBC_PAD: |
1031 | 0 | context->doPad = PR_TRUE; |
1032 | | /* fall thru */ |
1033 | 1.60k | case CKM_DES3_CBC: |
1034 | 1.60k | if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
1035 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1036 | 0 | break; |
1037 | 0 | } |
1038 | 1.60k | t = NSS_DES_EDE3_CBC; |
1039 | 3.69k | finish_des: |
1040 | 3.69k | if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL || |
1041 | 1.96k | pMechanism->ulParameterLen < 8)) { |
1042 | 0 | crv = CKR_DOMAIN_PARAMS_INVALID; |
1043 | 0 | break; |
1044 | 0 | } |
1045 | 3.69k | context->blockSize = 8; |
1046 | 3.69k | att = sftk_FindAttribute(key, CKA_VALUE); |
1047 | 3.69k | if (att == NULL) { |
1048 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1049 | 0 | break; |
1050 | 0 | } |
1051 | 3.69k | if (key_type == CKK_DES2 && |
1052 | 3.69k | (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) { |
1053 | | /* extend DES2 key to DES3 key. */ |
1054 | 0 | memcpy(newdeskey, att->attrib.pValue, 16); |
1055 | 0 | memcpy(newdeskey + 16, newdeskey, 8); |
1056 | 0 | useNewKey = PR_TRUE; |
1057 | 3.69k | } else if (key_type == CKK_CDMF) { |
1058 | 0 | crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey); |
1059 | 0 | if (crv != CKR_OK) { |
1060 | 0 | sftk_FreeAttribute(att); |
1061 | 0 | break; |
1062 | 0 | } |
1063 | 0 | useNewKey = PR_TRUE; |
1064 | 0 | } |
1065 | 3.69k | context->cipherInfo = DES_CreateContext( |
1066 | 3.69k | useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue, |
1067 | 3.69k | (unsigned char *)pMechanism->pParameter, t, isEncrypt); |
1068 | 3.69k | if (useNewKey) |
1069 | 0 | memset(newdeskey, 0, sizeof newdeskey); |
1070 | 3.69k | sftk_FreeAttribute(att); |
1071 | 3.69k | if (context->cipherInfo == NULL) { |
1072 | 0 | crv = CKR_HOST_MEMORY; |
1073 | 0 | break; |
1074 | 0 | } |
1075 | 3.69k | context->update = (SFTKCipher)(isEncrypt ? DES_Encrypt : DES_Decrypt); |
1076 | 3.69k | context->destroy = (SFTKDestroy)DES_DestroyContext; |
1077 | 3.69k | break; |
1078 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
1079 | 0 | case CKM_SEED_CBC_PAD: |
1080 | 0 | context->doPad = PR_TRUE; |
1081 | | /* fall thru */ |
1082 | 564 | case CKM_SEED_CBC: |
1083 | 564 | if (!pMechanism->pParameter || |
1084 | 564 | pMechanism->ulParameterLen != 16) { |
1085 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1086 | 0 | break; |
1087 | 0 | } |
1088 | | /* fall thru */ |
1089 | 564 | case CKM_SEED_ECB: |
1090 | 564 | context->blockSize = 16; |
1091 | 564 | if (key_type != CKK_SEED) { |
1092 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1093 | 0 | break; |
1094 | 0 | } |
1095 | 564 | att = sftk_FindAttribute(key, CKA_VALUE); |
1096 | 564 | if (att == NULL) { |
1097 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1098 | 0 | break; |
1099 | 0 | } |
1100 | 564 | context->cipherInfo = SEED_CreateContext( |
1101 | 564 | (unsigned char *)att->attrib.pValue, |
1102 | 564 | (unsigned char *)pMechanism->pParameter, |
1103 | 564 | pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC, |
1104 | 564 | isEncrypt); |
1105 | 564 | sftk_FreeAttribute(att); |
1106 | 564 | if (context->cipherInfo == NULL) { |
1107 | 0 | crv = CKR_HOST_MEMORY; |
1108 | 0 | break; |
1109 | 0 | } |
1110 | 564 | context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt); |
1111 | 564 | context->destroy = (SFTKDestroy)SEED_DestroyContext; |
1112 | 564 | break; |
1113 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
1114 | 0 | case CKM_CAMELLIA_CBC_PAD: |
1115 | 0 | context->doPad = PR_TRUE; |
1116 | | /* fall thru */ |
1117 | 1.08k | case CKM_CAMELLIA_CBC: |
1118 | 1.08k | if (!pMechanism->pParameter || |
1119 | 1.08k | pMechanism->ulParameterLen != 16) { |
1120 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1121 | 0 | break; |
1122 | 0 | } |
1123 | | /* fall thru */ |
1124 | 1.08k | case CKM_CAMELLIA_ECB: |
1125 | 1.08k | context->blockSize = 16; |
1126 | 1.08k | if (key_type != CKK_CAMELLIA) { |
1127 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1128 | 0 | break; |
1129 | 0 | } |
1130 | 1.08k | att = sftk_FindAttribute(key, CKA_VALUE); |
1131 | 1.08k | if (att == NULL) { |
1132 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1133 | 0 | break; |
1134 | 0 | } |
1135 | 1.08k | context->cipherInfo = Camellia_CreateContext( |
1136 | 1.08k | (unsigned char *)att->attrib.pValue, |
1137 | 1.08k | (unsigned char *)pMechanism->pParameter, |
1138 | 1.08k | pMechanism->mechanism == |
1139 | 1.08k | CKM_CAMELLIA_ECB |
1140 | 1.08k | ? NSS_CAMELLIA |
1141 | 1.08k | : NSS_CAMELLIA_CBC, |
1142 | 1.08k | isEncrypt, att->attrib.ulValueLen); |
1143 | 1.08k | sftk_FreeAttribute(att); |
1144 | 1.08k | if (context->cipherInfo == NULL) { |
1145 | 0 | crv = CKR_HOST_MEMORY; |
1146 | 0 | break; |
1147 | 0 | } |
1148 | 1.08k | context->update = (SFTKCipher)(isEncrypt ? Camellia_Encrypt : Camellia_Decrypt); |
1149 | 1.08k | context->destroy = (SFTKDestroy)Camellia_DestroyContext; |
1150 | 1.08k | break; |
1151 | | |
1152 | 153 | case CKM_AES_CBC_PAD: |
1153 | 153 | context->doPad = PR_TRUE; |
1154 | | /* fall thru */ |
1155 | 153 | case CKM_AES_ECB: |
1156 | 6.38k | case CKM_AES_CBC: |
1157 | 6.38k | context->blockSize = 16; |
1158 | 6.38k | case CKM_AES_CTS: |
1159 | 6.38k | case CKM_AES_CTR: |
1160 | 6.38k | case CKM_AES_GCM: |
1161 | 6.38k | aes_param = pMechanism->pParameter; |
1162 | | /* |
1163 | | * Due to a mismatch between the documentation and the header |
1164 | | * file, two different definitions for CK_GCM_PARAMS exist. |
1165 | | * The header file is normative according to Oasis, but NSS used |
1166 | | * the documentation. In PKCS #11 v3.0, this was reconciled in |
1167 | | * favor of the header file definition. To maintain binary |
1168 | | * compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official |
1169 | | * version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the |
1170 | | * legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS |
1171 | | * is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not |
1172 | | * defined and CK_NSS_GCM_PARAMS if it is. Internally |
1173 | | * softoken continues to use the legacy version. The code below |
1174 | | * automatically detects which parameter was passed in and |
1175 | | * converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy |
1176 | | * version) on the fly. NSS proper will eventually start |
1177 | | * using the CK_GCM_PARAMS_V3 version and fall back to the |
1178 | | * CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with |
1179 | | * CKR_MECHANISM_PARAM_INVALID. |
1180 | | */ |
1181 | 6.38k | if (pMechanism->mechanism == CKM_AES_GCM) { |
1182 | 0 | if (!aes_param) { |
1183 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1184 | 0 | break; |
1185 | 0 | } |
1186 | 0 | if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) { |
1187 | | /* convert the true V3 parameters into the old NSS parameters */ |
1188 | 0 | CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param; |
1189 | 0 | if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) { |
1190 | | /* only support byte aligned IV lengths */ |
1191 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1192 | 0 | break; |
1193 | 0 | } |
1194 | 0 | aes_param = (void *)&nss_gcm_param; |
1195 | 0 | nss_gcm_param.pIv = gcm_params->pIv; |
1196 | 0 | nss_gcm_param.ulIvLen = gcm_params->ulIvLen; |
1197 | 0 | nss_gcm_param.pAAD = gcm_params->pAAD; |
1198 | 0 | nss_gcm_param.ulAADLen = gcm_params->ulAADLen; |
1199 | 0 | nss_gcm_param.ulTagBits = gcm_params->ulTagBits; |
1200 | 0 | } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) { |
1201 | | /* neither old nor new style params, must be invalid */ |
1202 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1203 | 0 | break; |
1204 | 0 | } |
1205 | 6.38k | } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) || |
1206 | 6.38k | ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) { |
1207 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1208 | 0 | break; |
1209 | 0 | } |
1210 | | |
1211 | 6.38k | if (pMechanism->mechanism == CKM_AES_GCM) { |
1212 | 0 | context->multi = PR_FALSE; |
1213 | 0 | } |
1214 | 6.38k | if (key_type != CKK_AES) { |
1215 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1216 | 0 | break; |
1217 | 0 | } |
1218 | 6.38k | att = sftk_FindAttribute(key, CKA_VALUE); |
1219 | 6.38k | if (att == NULL) { |
1220 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1221 | 0 | break; |
1222 | 0 | } |
1223 | 6.38k | context->cipherInfo = AES_CreateContext( |
1224 | 6.38k | (unsigned char *)att->attrib.pValue, |
1225 | 6.38k | (unsigned char *)aes_param, |
1226 | 6.38k | sftk_aes_mode(pMechanism->mechanism), |
1227 | 6.38k | isEncrypt, att->attrib.ulValueLen, 16); |
1228 | 6.38k | sftk_FreeAttribute(att); |
1229 | 6.38k | if (context->cipherInfo == NULL) { |
1230 | 0 | crv = CKR_HOST_MEMORY; |
1231 | 0 | break; |
1232 | 0 | } |
1233 | 6.38k | context->update = (SFTKCipher)(isEncrypt ? AES_Encrypt : AES_Decrypt); |
1234 | 6.38k | context->destroy = (SFTKDestroy)AES_DestroyContext; |
1235 | 6.38k | break; |
1236 | | |
1237 | 0 | case CKM_NSS_CHACHA20_POLY1305: |
1238 | 0 | case CKM_CHACHA20_POLY1305: |
1239 | 0 | if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) { |
1240 | 0 | if (key_type != CKK_NSS_CHACHA20) { |
1241 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1242 | 0 | break; |
1243 | 0 | } |
1244 | 0 | if ((pMechanism->pParameter == NULL) || |
1245 | 0 | (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) { |
1246 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1247 | 0 | break; |
1248 | 0 | } |
1249 | 0 | nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter; |
1250 | 0 | } else { |
1251 | 0 | CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params; |
1252 | 0 | if (key_type != CKK_CHACHA20) { |
1253 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1254 | 0 | break; |
1255 | 0 | } |
1256 | 0 | if ((pMechanism->pParameter == NULL) || |
1257 | 0 | (pMechanism->ulParameterLen != |
1258 | 0 | sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) { |
1259 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1260 | 0 | break; |
1261 | 0 | } |
1262 | 0 | chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR) |
1263 | 0 | pMechanism->pParameter; |
1264 | 0 | nss_aead_params_ptr = &nss_aead_params; |
1265 | 0 | nss_aead_params.pNonce = chacha_poly_params->pNonce; |
1266 | 0 | nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen; |
1267 | 0 | nss_aead_params.pAAD = chacha_poly_params->pAAD; |
1268 | 0 | nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen; |
1269 | 0 | nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */ |
1270 | 0 | } |
1271 | | |
1272 | 0 | context->multi = PR_FALSE; |
1273 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1274 | 0 | if (att == NULL) { |
1275 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1276 | 0 | break; |
1277 | 0 | } |
1278 | 0 | context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext( |
1279 | 0 | (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen, |
1280 | 0 | nss_aead_params_ptr); |
1281 | 0 | sftk_FreeAttribute(att); |
1282 | 0 | if (context->cipherInfo == NULL) { |
1283 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
1284 | 0 | break; |
1285 | 0 | } |
1286 | 0 | context->update = (SFTKCipher)(isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt); |
1287 | 0 | context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext; |
1288 | 0 | break; |
1289 | | |
1290 | 0 | case CKM_NSS_CHACHA20_CTR: /* old NSS private version */ |
1291 | 0 | case CKM_CHACHA20: /* PKCS #11 v3 version */ |
1292 | 0 | { |
1293 | 0 | unsigned char *counter; |
1294 | 0 | unsigned char *nonce; |
1295 | 0 | unsigned long counter_len; |
1296 | 0 | unsigned long nonce_len; |
1297 | 0 | context->multi = PR_FALSE; |
1298 | 0 | if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) { |
1299 | 0 | if (key_type != CKK_NSS_CHACHA20) { |
1300 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1301 | 0 | break; |
1302 | 0 | } |
1303 | 0 | if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) { |
1304 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1305 | 0 | break; |
1306 | 0 | } |
1307 | 0 | counter_len = 4; |
1308 | 0 | counter = pMechanism->pParameter; |
1309 | 0 | nonce = counter + 4; |
1310 | 0 | nonce_len = 12; |
1311 | 0 | } else { |
1312 | 0 | CK_CHACHA20_PARAMS_PTR chacha20_param_ptr; |
1313 | 0 | if (key_type != CKK_CHACHA20) { |
1314 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1315 | 0 | break; |
1316 | 0 | } |
1317 | 0 | if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) { |
1318 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1319 | 0 | break; |
1320 | 0 | } |
1321 | 0 | chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter; |
1322 | 0 | if ((chacha20_param_ptr->blockCounterBits != 32) && |
1323 | 0 | (chacha20_param_ptr->blockCounterBits != 64)) { |
1324 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1325 | 0 | break; |
1326 | 0 | } |
1327 | 0 | counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE; |
1328 | 0 | counter = chacha20_param_ptr->pBlockCounter; |
1329 | 0 | nonce = chacha20_param_ptr->pNonce; |
1330 | 0 | nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE; |
1331 | 0 | } |
1332 | | |
1333 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1334 | 0 | if (att == NULL) { |
1335 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1336 | 0 | break; |
1337 | 0 | } |
1338 | 0 | SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo); |
1339 | 0 | if (!ctx) { |
1340 | 0 | sftk_FreeAttribute(att); |
1341 | 0 | crv = CKR_HOST_MEMORY; |
1342 | 0 | break; |
1343 | 0 | } |
1344 | 0 | if (att->attrib.ulValueLen != sizeof(ctx->key)) { |
1345 | 0 | sftk_FreeAttribute(att); |
1346 | 0 | PORT_Free(ctx); |
1347 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1348 | 0 | break; |
1349 | 0 | } |
1350 | 0 | memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen); |
1351 | 0 | sftk_FreeAttribute(att); |
1352 | | |
1353 | | /* make sure we don't overflow our parameters */ |
1354 | 0 | if ((sizeof(ctx->counter) < counter_len) || |
1355 | 0 | (sizeof(ctx->nonce) < nonce_len)) { |
1356 | 0 | PORT_Free(ctx); |
1357 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1358 | 0 | break; |
1359 | 0 | } |
1360 | | |
1361 | | /* The counter is little endian. */ |
1362 | 0 | int i = 0; |
1363 | 0 | for (; i < counter_len; ++i) { |
1364 | 0 | ctx->counter |= (PRUint32)counter[i] << (i * 8); |
1365 | 0 | } |
1366 | 0 | memcpy(ctx->nonce, nonce, nonce_len); |
1367 | 0 | context->cipherInfo = ctx; |
1368 | 0 | context->update = (SFTKCipher)sftk_ChaCha20Ctr; |
1369 | 0 | context->destroy = (SFTKDestroy)sftk_ChaCha20Ctr_DestroyContext; |
1370 | 0 | break; |
1371 | 0 | } |
1372 | | |
1373 | 0 | case CKM_NSS_AES_KEY_WRAP_PAD: |
1374 | 0 | case CKM_AES_KEY_WRAP_PAD: |
1375 | 0 | context->doPad = PR_TRUE; |
1376 | | /* fall thru */ |
1377 | 0 | case CKM_NSS_AES_KEY_WRAP: |
1378 | 0 | case CKM_AES_KEY_WRAP: |
1379 | 0 | context->blockSize = 8; |
1380 | 0 | case CKM_AES_KEY_WRAP_KWP: |
1381 | 0 | context->multi = PR_FALSE; |
1382 | 0 | if (key_type != CKK_AES) { |
1383 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1384 | 0 | break; |
1385 | 0 | } |
1386 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1387 | 0 | if (att == NULL) { |
1388 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1389 | 0 | break; |
1390 | 0 | } |
1391 | 0 | context->cipherInfo = AESKeyWrap_CreateContext( |
1392 | 0 | (unsigned char *)att->attrib.pValue, |
1393 | 0 | (unsigned char *)pMechanism->pParameter, |
1394 | 0 | isEncrypt, att->attrib.ulValueLen); |
1395 | 0 | sftk_FreeAttribute(att); |
1396 | 0 | if (context->cipherInfo == NULL) { |
1397 | 0 | crv = CKR_HOST_MEMORY; |
1398 | 0 | break; |
1399 | 0 | } |
1400 | 0 | if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) { |
1401 | 0 | context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_EncryptKWP |
1402 | 0 | : AESKeyWrap_DecryptKWP); |
1403 | 0 | } else { |
1404 | 0 | context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_Encrypt |
1405 | 0 | : AESKeyWrap_Decrypt); |
1406 | 0 | } |
1407 | 0 | context->destroy = (SFTKDestroy)AESKeyWrap_DestroyContext; |
1408 | 0 | break; |
1409 | | |
1410 | 0 | default: |
1411 | 0 | crv = CKR_MECHANISM_INVALID; |
1412 | 0 | break; |
1413 | 15.0k | } |
1414 | | |
1415 | 15.0k | if (crv != CKR_OK) { |
1416 | 0 | sftk_FreeContext(context); |
1417 | 0 | sftk_FreeSession(session); |
1418 | 0 | return crv; |
1419 | 0 | } |
1420 | 15.0k | sftk_SetContextByType(session, contextType, context); |
1421 | 15.0k | sftk_FreeSession(session); |
1422 | 15.0k | return CKR_OK; |
1423 | 15.0k | } |
1424 | | |
1425 | | /* NSC_EncryptInit initializes an encryption operation. */ |
1426 | | CK_RV |
1427 | | NSC_EncryptInit(CK_SESSION_HANDLE hSession, |
1428 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
1429 | 5.32k | { |
1430 | 5.32k | CHECK_FORK(); |
1431 | 5.32k | return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT, |
1432 | 5.32k | SFTK_ENCRYPT, PR_TRUE); |
1433 | 5.32k | } |
1434 | | |
1435 | | /* NSC_EncryptUpdate continues a multiple-part encryption operation. */ |
1436 | | CK_RV |
1437 | | NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, |
1438 | | CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
1439 | | CK_ULONG_PTR pulEncryptedPartLen) |
1440 | 2.27k | { |
1441 | 2.27k | SFTKSessionContext *context; |
1442 | 2.27k | unsigned int outlen, i; |
1443 | 2.27k | unsigned int padoutlen = 0; |
1444 | 2.27k | unsigned int maxout = *pulEncryptedPartLen; |
1445 | 2.27k | CK_RV crv; |
1446 | 2.27k | SECStatus rv; |
1447 | | |
1448 | 2.27k | CHECK_FORK(); |
1449 | | |
1450 | | /* make sure we're legal */ |
1451 | 2.27k | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, NULL); |
1452 | 2.27k | if (crv != CKR_OK) |
1453 | 0 | return crv; |
1454 | | |
1455 | 2.27k | if (!pEncryptedPart) { |
1456 | 0 | if (context->doPad) { |
1457 | 0 | CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; |
1458 | 0 | CK_ULONG blocksToSend = totalDataAvailable / context->blockSize; |
1459 | |
|
1460 | 0 | *pulEncryptedPartLen = blocksToSend * context->blockSize; |
1461 | 0 | return CKR_OK; |
1462 | 0 | } |
1463 | 0 | *pulEncryptedPartLen = ulPartLen; |
1464 | 0 | return CKR_OK; |
1465 | 0 | } |
1466 | | |
1467 | | /* do padding */ |
1468 | 2.27k | if (context->doPad) { |
1469 | | /* deal with previous buffered data */ |
1470 | 153 | if (context->padDataLength != 0) { |
1471 | | /* fill in the padded to a full block size */ |
1472 | 0 | for (i = context->padDataLength; |
1473 | 0 | (ulPartLen != 0) && i < context->blockSize; i++) { |
1474 | 0 | context->padBuf[i] = *pPart++; |
1475 | 0 | ulPartLen--; |
1476 | 0 | context->padDataLength++; |
1477 | 0 | } |
1478 | | |
1479 | | /* not enough data to encrypt yet? then return */ |
1480 | 0 | if (context->padDataLength != context->blockSize) { |
1481 | 0 | *pulEncryptedPartLen = 0; |
1482 | 0 | return CKR_OK; |
1483 | 0 | } |
1484 | | /* encrypt the current padded data */ |
1485 | 0 | rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
1486 | 0 | &padoutlen, maxout, context->padBuf, |
1487 | 0 | context->blockSize); |
1488 | 0 | if (rv != SECSuccess) { |
1489 | 0 | return sftk_MapCryptError(PORT_GetError()); |
1490 | 0 | } |
1491 | 0 | pEncryptedPart += padoutlen; |
1492 | 0 | maxout -= padoutlen; |
1493 | 0 | } |
1494 | | /* save the residual */ |
1495 | 153 | context->padDataLength = ulPartLen % context->blockSize; |
1496 | 153 | if (context->padDataLength) { |
1497 | 153 | PORT_Memcpy(context->padBuf, |
1498 | 153 | &pPart[ulPartLen - context->padDataLength], |
1499 | 153 | context->padDataLength); |
1500 | 153 | ulPartLen -= context->padDataLength; |
1501 | 153 | } |
1502 | | /* if we've exhausted our new buffer, we're done */ |
1503 | 153 | if (ulPartLen == 0) { |
1504 | 0 | *pulEncryptedPartLen = padoutlen; |
1505 | 0 | return CKR_OK; |
1506 | 0 | } |
1507 | 153 | } |
1508 | | |
1509 | | /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
1510 | 2.27k | rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
1511 | 2.27k | &outlen, maxout, pPart, ulPartLen); |
1512 | 2.27k | if (rv != SECSuccess) { |
1513 | 0 | return sftk_MapCryptError(PORT_GetError()); |
1514 | 0 | } |
1515 | 2.27k | *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen); |
1516 | 2.27k | return CKR_OK; |
1517 | 2.27k | } |
1518 | | |
1519 | | /* NSC_EncryptFinal finishes a multiple-part encryption operation. */ |
1520 | | CK_RV |
1521 | | NSC_EncryptFinal(CK_SESSION_HANDLE hSession, |
1522 | | CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) |
1523 | 153 | { |
1524 | 153 | SFTKSession *session; |
1525 | 153 | SFTKSessionContext *context; |
1526 | 153 | unsigned int outlen, i; |
1527 | 153 | unsigned int maxout = *pulLastEncryptedPartLen; |
1528 | 153 | CK_RV crv; |
1529 | 153 | SECStatus rv = SECSuccess; |
1530 | 153 | PRBool contextFinished = PR_TRUE; |
1531 | | |
1532 | 153 | CHECK_FORK(); |
1533 | | |
1534 | | /* make sure we're legal */ |
1535 | 153 | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session); |
1536 | 153 | if (crv != CKR_OK) |
1537 | 0 | return crv; |
1538 | | |
1539 | 153 | *pulLastEncryptedPartLen = 0; |
1540 | 153 | if (!pLastEncryptedPart) { |
1541 | | /* caller is checking the amount of remaining data */ |
1542 | 0 | if (context->blockSize > 0 && context->doPad) { |
1543 | 0 | *pulLastEncryptedPartLen = context->blockSize; |
1544 | 0 | contextFinished = PR_FALSE; /* still have padding to go */ |
1545 | 0 | } |
1546 | 0 | goto finish; |
1547 | 0 | } |
1548 | | |
1549 | | /* do padding */ |
1550 | 153 | if (context->doPad) { |
1551 | 153 | unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength); |
1552 | | /* fill out rest of pad buffer with pad magic*/ |
1553 | 1.37k | for (i = context->padDataLength; i < context->blockSize; i++) { |
1554 | 1.22k | context->padBuf[i] = padbyte; |
1555 | 1.22k | } |
1556 | 153 | rv = (*context->update)(context->cipherInfo, pLastEncryptedPart, |
1557 | 153 | &outlen, maxout, context->padBuf, context->blockSize); |
1558 | 153 | if (rv == SECSuccess) |
1559 | 153 | *pulLastEncryptedPartLen = (CK_ULONG)outlen; |
1560 | 153 | } |
1561 | | |
1562 | 153 | finish: |
1563 | 153 | if (contextFinished) |
1564 | 153 | sftk_TerminateOp(session, SFTK_ENCRYPT, context); |
1565 | 153 | sftk_FreeSession(session); |
1566 | 153 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
1567 | 153 | } |
1568 | | |
1569 | | /* NSC_Encrypt encrypts single-part data. */ |
1570 | | CK_RV |
1571 | | NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
1572 | | CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, |
1573 | | CK_ULONG_PTR pulEncryptedDataLen) |
1574 | 4.62k | { |
1575 | 4.62k | SFTKSession *session; |
1576 | 4.62k | SFTKSessionContext *context; |
1577 | 4.62k | unsigned int outlen; |
1578 | 4.62k | unsigned int maxoutlen = *pulEncryptedDataLen; |
1579 | 4.62k | CK_RV crv; |
1580 | 4.62k | CK_RV crv2; |
1581 | 4.62k | SECStatus rv = SECSuccess; |
1582 | 4.62k | SECItem pText; |
1583 | | |
1584 | 4.62k | pText.type = siBuffer; |
1585 | 4.62k | pText.data = pData; |
1586 | 4.62k | pText.len = ulDataLen; |
1587 | | |
1588 | 4.62k | CHECK_FORK(); |
1589 | | |
1590 | | /* make sure we're legal */ |
1591 | 4.62k | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session); |
1592 | 4.62k | if (crv != CKR_OK) |
1593 | 0 | return crv; |
1594 | | |
1595 | 4.62k | if (!pEncryptedData) { |
1596 | 0 | outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize; |
1597 | 0 | goto done; |
1598 | 0 | } |
1599 | | |
1600 | 4.62k | if (context->doPad) { |
1601 | 153 | if (context->multi) { |
1602 | 153 | CK_ULONG updateLen = maxoutlen; |
1603 | 153 | CK_ULONG finalLen; |
1604 | | /* padding is fairly complicated, have the update and final |
1605 | | * code deal with it */ |
1606 | 153 | sftk_FreeSession(session); |
1607 | 153 | crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, |
1608 | 153 | &updateLen); |
1609 | 153 | if (crv != CKR_OK) { |
1610 | 0 | updateLen = 0; |
1611 | 0 | } |
1612 | 153 | maxoutlen -= updateLen; |
1613 | 153 | pEncryptedData += updateLen; |
1614 | 153 | finalLen = maxoutlen; |
1615 | 153 | crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen); |
1616 | 153 | if (crv == CKR_OK && crv2 == CKR_OK) { |
1617 | 153 | *pulEncryptedDataLen = updateLen + finalLen; |
1618 | 153 | } |
1619 | 153 | return crv == CKR_OK ? crv2 : crv; |
1620 | 153 | } |
1621 | | /* doPad without multi means that padding must be done on the first |
1622 | | ** and only update. There will be no final. |
1623 | | */ |
1624 | 0 | PORT_Assert(context->blockSize > 1); |
1625 | 0 | if (context->blockSize > 1) { |
1626 | 0 | CK_ULONG remainder = ulDataLen % context->blockSize; |
1627 | 0 | CK_ULONG padding = context->blockSize - remainder; |
1628 | 0 | pText.len += padding; |
1629 | 0 | pText.data = PORT_ZAlloc(pText.len); |
1630 | 0 | if (pText.data) { |
1631 | 0 | memcpy(pText.data, pData, ulDataLen); |
1632 | 0 | memset(pText.data + ulDataLen, padding, padding); |
1633 | 0 | } else { |
1634 | 0 | crv = CKR_HOST_MEMORY; |
1635 | 0 | goto fail; |
1636 | 0 | } |
1637 | 0 | } |
1638 | 0 | } |
1639 | | |
1640 | | /* do it: NOTE: this assumes buf size is big enough. */ |
1641 | 4.46k | rv = (*context->update)(context->cipherInfo, pEncryptedData, |
1642 | 4.46k | &outlen, maxoutlen, pText.data, pText.len); |
1643 | 4.46k | crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
1644 | 4.46k | if (pText.data != pData) |
1645 | 0 | PORT_ZFree(pText.data, pText.len); |
1646 | 4.46k | fail: |
1647 | 4.46k | sftk_TerminateOp(session, SFTK_ENCRYPT, context); |
1648 | 4.46k | done: |
1649 | 4.46k | sftk_FreeSession(session); |
1650 | 4.46k | if (crv == CKR_OK) { |
1651 | 4.46k | *pulEncryptedDataLen = (CK_ULONG)outlen; |
1652 | 4.46k | } |
1653 | 4.46k | return crv; |
1654 | 4.46k | } |
1655 | | |
1656 | | /* |
1657 | | ************** Crypto Functions: Decrypt ************************ |
1658 | | */ |
1659 | | |
1660 | | /* NSC_DecryptInit initializes a decryption operation. */ |
1661 | | CK_RV |
1662 | | NSC_DecryptInit(CK_SESSION_HANDLE hSession, |
1663 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
1664 | 5.18k | { |
1665 | 5.18k | CHECK_FORK(); |
1666 | 5.18k | return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT, |
1667 | 5.18k | SFTK_DECRYPT, PR_FALSE); |
1668 | 5.18k | } |
1669 | | |
1670 | | /* NSC_DecryptUpdate continues a multiple-part decryption operation. */ |
1671 | | CK_RV |
1672 | | NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, |
1673 | | CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
1674 | | CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
1675 | 13.7k | { |
1676 | 13.7k | SFTKSessionContext *context; |
1677 | 13.7k | unsigned int padoutlen = 0; |
1678 | 13.7k | unsigned int outlen; |
1679 | 13.7k | unsigned int maxout = *pulPartLen; |
1680 | 13.7k | CK_RV crv; |
1681 | 13.7k | SECStatus rv; |
1682 | | |
1683 | 13.7k | CHECK_FORK(); |
1684 | | |
1685 | | /* make sure we're legal */ |
1686 | 13.7k | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, NULL); |
1687 | 13.7k | if (crv != CKR_OK) |
1688 | 0 | return crv; |
1689 | | |
1690 | | /* this can only happen on an NSS programming error */ |
1691 | 13.7k | PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize); |
1692 | | |
1693 | 13.7k | if (context->doPad) { |
1694 | | /* Check the data length for block ciphers. If we are padding, |
1695 | | * then we must be using a block cipher. In the non-padding case |
1696 | | * the error will be returned by the underlying decryption |
1697 | | * function when we do the actual decrypt. We need to do the |
1698 | | * check here to avoid returning a negative length to the caller |
1699 | | * or reading before the beginning of the pEncryptedPart buffer. |
1700 | | */ |
1701 | 0 | if ((ulEncryptedPartLen == 0) || |
1702 | 0 | (ulEncryptedPartLen % context->blockSize) != 0) { |
1703 | 0 | return CKR_ENCRYPTED_DATA_LEN_RANGE; |
1704 | 0 | } |
1705 | 0 | } |
1706 | | |
1707 | 13.7k | if (!pPart) { |
1708 | 0 | if (context->doPad) { |
1709 | 0 | *pulPartLen = |
1710 | 0 | ulEncryptedPartLen + context->padDataLength - context->blockSize; |
1711 | 0 | return CKR_OK; |
1712 | 0 | } |
1713 | | /* for stream ciphers there is are no constraints on ulEncryptedPartLen. |
1714 | | * for block ciphers, it must be a multiple of blockSize. The error is |
1715 | | * detected when this function is called again do decrypt the output. |
1716 | | */ |
1717 | 0 | *pulPartLen = ulEncryptedPartLen; |
1718 | 0 | return CKR_OK; |
1719 | 0 | } |
1720 | | |
1721 | 13.7k | if (context->doPad) { |
1722 | | /* first decrypt our saved buffer */ |
1723 | 0 | if (context->padDataLength != 0) { |
1724 | 0 | rv = (*context->update)(context->cipherInfo, pPart, &padoutlen, |
1725 | 0 | maxout, context->padBuf, context->blockSize); |
1726 | 0 | if (rv != SECSuccess) |
1727 | 0 | return sftk_MapDecryptError(PORT_GetError()); |
1728 | 0 | pPart += padoutlen; |
1729 | 0 | maxout -= padoutlen; |
1730 | 0 | } |
1731 | | /* now save the final block for the next decrypt or the final */ |
1732 | 0 | PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize], |
1733 | 0 | context->blockSize); |
1734 | 0 | context->padDataLength = context->blockSize; |
1735 | 0 | ulEncryptedPartLen -= context->padDataLength; |
1736 | 0 | } |
1737 | | |
1738 | | /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
1739 | 13.7k | rv = (*context->update)(context->cipherInfo, pPart, &outlen, |
1740 | 13.7k | maxout, pEncryptedPart, ulEncryptedPartLen); |
1741 | 13.7k | if (rv != SECSuccess) { |
1742 | 0 | return sftk_MapDecryptError(PORT_GetError()); |
1743 | 0 | } |
1744 | 13.7k | *pulPartLen = (CK_ULONG)(outlen + padoutlen); |
1745 | 13.7k | return CKR_OK; |
1746 | 13.7k | } |
1747 | | |
1748 | | /* NSC_DecryptFinal finishes a multiple-part decryption operation. */ |
1749 | | CK_RV |
1750 | | NSC_DecryptFinal(CK_SESSION_HANDLE hSession, |
1751 | | CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) |
1752 | 0 | { |
1753 | 0 | SFTKSession *session; |
1754 | 0 | SFTKSessionContext *context; |
1755 | 0 | unsigned int outlen; |
1756 | 0 | unsigned int maxout = *pulLastPartLen; |
1757 | 0 | CK_RV crv; |
1758 | 0 | SECStatus rv = SECSuccess; |
1759 | |
|
1760 | 0 | CHECK_FORK(); |
1761 | | |
1762 | | /* make sure we're legal */ |
1763 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session); |
1764 | 0 | if (crv != CKR_OK) |
1765 | 0 | return crv; |
1766 | | |
1767 | 0 | *pulLastPartLen = 0; |
1768 | 0 | if (!pLastPart) { |
1769 | | /* caller is checking the amount of remaining data */ |
1770 | 0 | if (context->padDataLength > 0) { |
1771 | 0 | *pulLastPartLen = context->padDataLength; |
1772 | 0 | } |
1773 | 0 | goto finish; |
1774 | 0 | } |
1775 | | |
1776 | 0 | if (context->doPad) { |
1777 | | /* decrypt our saved buffer */ |
1778 | 0 | if (context->padDataLength != 0) { |
1779 | | /* this assumes that pLastPart is big enough to hold the *whole* |
1780 | | * buffer!!! */ |
1781 | 0 | rv = (*context->update)(context->cipherInfo, pLastPart, &outlen, |
1782 | 0 | maxout, context->padBuf, context->blockSize); |
1783 | 0 | if (rv != SECSuccess) { |
1784 | 0 | crv = sftk_MapDecryptError(PORT_GetError()); |
1785 | 0 | } else { |
1786 | 0 | unsigned int padSize = 0; |
1787 | 0 | crv = sftk_CheckCBCPadding(pLastPart, outlen, |
1788 | 0 | context->blockSize, &padSize); |
1789 | | /* Update pulLastPartLen, in constant time, if crv is OK */ |
1790 | 0 | *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen); |
1791 | 0 | } |
1792 | 0 | } |
1793 | 0 | } |
1794 | |
|
1795 | 0 | sftk_TerminateOp(session, SFTK_DECRYPT, context); |
1796 | 0 | finish: |
1797 | 0 | sftk_FreeSession(session); |
1798 | 0 | return crv; |
1799 | 0 | } |
1800 | | |
1801 | | /* NSC_Decrypt decrypts encrypted data in a single part. */ |
1802 | | CK_RV |
1803 | | NSC_Decrypt(CK_SESSION_HANDLE hSession, |
1804 | | CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, |
1805 | | CK_ULONG_PTR pulDataLen) |
1806 | 47 | { |
1807 | 47 | SFTKSession *session; |
1808 | 47 | SFTKSessionContext *context; |
1809 | 47 | unsigned int outlen; |
1810 | 47 | unsigned int maxoutlen = *pulDataLen; |
1811 | 47 | CK_RV crv; |
1812 | 47 | CK_RV crv2; |
1813 | 47 | SECStatus rv = SECSuccess; |
1814 | | |
1815 | 47 | CHECK_FORK(); |
1816 | | |
1817 | | /* make sure we're legal */ |
1818 | 47 | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session); |
1819 | 47 | if (crv != CKR_OK) |
1820 | 0 | return crv; |
1821 | | |
1822 | 47 | if (!pData) { |
1823 | 0 | *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize); |
1824 | 0 | goto done; |
1825 | 0 | } |
1826 | | |
1827 | 47 | if (context->doPad && context->multi) { |
1828 | 0 | CK_ULONG updateLen = maxoutlen; |
1829 | 0 | CK_ULONG finalLen; |
1830 | | /* padding is fairly complicated, have the update and final |
1831 | | * code deal with it */ |
1832 | 0 | sftk_FreeSession(session); |
1833 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, |
1834 | 0 | pData, &updateLen); |
1835 | 0 | if (crv == CKR_OK) { |
1836 | 0 | maxoutlen -= updateLen; |
1837 | 0 | pData += updateLen; |
1838 | 0 | } |
1839 | 0 | finalLen = maxoutlen; |
1840 | 0 | crv2 = NSC_DecryptFinal(hSession, pData, &finalLen); |
1841 | 0 | if (crv == CKR_OK) { |
1842 | 0 | *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen); |
1843 | 0 | return crv2; |
1844 | 0 | } else { |
1845 | 0 | return crv; |
1846 | 0 | } |
1847 | 0 | } |
1848 | | |
1849 | 47 | rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
1850 | 47 | pEncryptedData, ulEncryptedDataLen); |
1851 | | /* XXX need to do MUCH better error mapping than this. */ |
1852 | 47 | crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); |
1853 | 47 | if (rv == SECSuccess) { |
1854 | 7 | if (context->doPad) { |
1855 | 0 | unsigned int padSize = 0; |
1856 | 0 | crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize, |
1857 | 0 | &padSize); |
1858 | | /* Update pulDataLen, in constant time, if crv is OK */ |
1859 | 0 | *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen); |
1860 | 7 | } else { |
1861 | 7 | *pulDataLen = (CK_ULONG)outlen; |
1862 | 7 | } |
1863 | 7 | } |
1864 | 47 | sftk_TerminateOp(session, SFTK_DECRYPT, context); |
1865 | 47 | done: |
1866 | 47 | sftk_FreeSession(session); |
1867 | 47 | return crv; |
1868 | 47 | } |
1869 | | |
1870 | | /* |
1871 | | ************** Crypto Functions: Digest (HASH) ************************ |
1872 | | */ |
1873 | | |
1874 | | /* NSC_DigestInit initializes a message-digesting operation. */ |
1875 | | CK_RV |
1876 | | NSC_DigestInit(CK_SESSION_HANDLE hSession, |
1877 | | CK_MECHANISM_PTR pMechanism) |
1878 | 155k | { |
1879 | 155k | SFTKSession *session; |
1880 | 155k | SFTKSessionContext *context; |
1881 | 155k | CK_RV crv = CKR_OK; |
1882 | | |
1883 | 155k | CHECK_FORK(); |
1884 | | |
1885 | 155k | session = sftk_SessionFromHandle(hSession); |
1886 | 155k | if (session == NULL) |
1887 | 0 | return CKR_SESSION_HANDLE_INVALID; |
1888 | 155k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH, |
1889 | 155k | NULL, 0, NULL, 0, CKA_DIGEST); |
1890 | 155k | if (crv != CKR_OK) { |
1891 | 0 | sftk_FreeSession(session); |
1892 | 0 | return crv; |
1893 | 0 | } |
1894 | | |
1895 | 155k | #define INIT_MECH(mmm) \ |
1896 | 155k | case CKM_##mmm: { \ |
1897 | 155k | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ |
1898 | 155k | context->cipherInfo = (void *)mmm##_ctx; \ |
1899 | 155k | context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \ |
1900 | 155k | context->currentMech = CKM_##mmm; \ |
1901 | 155k | context->hashUpdate = (SFTKHash)mmm##_Update; \ |
1902 | 155k | context->end = (SFTKEnd)mmm##_End; \ |
1903 | 155k | context->destroy = (SFTKDestroy)mmm##_DestroyContext; \ |
1904 | 155k | context->maxLen = mmm##_LENGTH; \ |
1905 | 155k | if (mmm##_ctx) \ |
1906 | 155k | mmm##_Begin(mmm##_ctx); \ |
1907 | 155k | else \ |
1908 | 155k | crv = CKR_HOST_MEMORY; \ |
1909 | 155k | break; \ |
1910 | 155k | } |
1911 | | |
1912 | 155k | switch (pMechanism->mechanism) { |
1913 | 0 | INIT_MECH(MD2) |
1914 | 16.3k | INIT_MECH(MD5) |
1915 | 108k | INIT_MECH(SHA1) |
1916 | 0 | INIT_MECH(SHA224) |
1917 | 20.4k | INIT_MECH(SHA256) |
1918 | 9.71k | INIT_MECH(SHA384) |
1919 | 766 | INIT_MECH(SHA512) |
1920 | 0 | INIT_MECH(SHA3_224) |
1921 | 0 | INIT_MECH(SHA3_256) |
1922 | 0 | INIT_MECH(SHA3_384) |
1923 | 0 | INIT_MECH(SHA3_512) |
1924 | | |
1925 | 0 | default: |
1926 | 0 | crv = CKR_MECHANISM_INVALID; |
1927 | 0 | break; |
1928 | 155k | } |
1929 | | |
1930 | 155k | if (crv != CKR_OK) { |
1931 | 0 | sftk_FreeContext(context); |
1932 | 0 | sftk_FreeSession(session); |
1933 | 0 | return crv; |
1934 | 0 | } |
1935 | 155k | sftk_SetContextByType(session, SFTK_HASH, context); |
1936 | 155k | sftk_FreeSession(session); |
1937 | 155k | return CKR_OK; |
1938 | 155k | } |
1939 | | |
1940 | | /* NSC_Digest digests data in a single part. */ |
1941 | | CK_RV |
1942 | | NSC_Digest(CK_SESSION_HANDLE hSession, |
1943 | | CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, |
1944 | | CK_ULONG_PTR pulDigestLen) |
1945 | 0 | { |
1946 | 0 | SFTKSession *session; |
1947 | 0 | SFTKSessionContext *context; |
1948 | 0 | unsigned int digestLen; |
1949 | 0 | unsigned int maxout = *pulDigestLen; |
1950 | 0 | CK_RV crv; |
1951 | |
|
1952 | 0 | CHECK_FORK(); |
1953 | | |
1954 | | /* make sure we're legal */ |
1955 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session); |
1956 | 0 | if (crv != CKR_OK) |
1957 | 0 | return crv; |
1958 | | |
1959 | 0 | if (pDigest == NULL) { |
1960 | 0 | *pulDigestLen = context->maxLen; |
1961 | 0 | goto finish; |
1962 | 0 | } |
1963 | | |
1964 | 0 | #if (ULONG_MAX > UINT_MAX) |
1965 | | /* The context->hashUpdate function takes an unsigned int for its data |
1966 | | * length argument, but NSC_Digest takes an unsigned long. */ |
1967 | 0 | while (ulDataLen > UINT_MAX) { |
1968 | 0 | (*context->hashUpdate)(context->cipherInfo, pData, UINT_MAX); |
1969 | 0 | pData += UINT_MAX; |
1970 | 0 | ulDataLen -= UINT_MAX; |
1971 | 0 | } |
1972 | 0 | #endif |
1973 | 0 | (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen); |
1974 | | |
1975 | | /* NOTE: this assumes buf size is bigenough for the algorithm */ |
1976 | 0 | (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
1977 | 0 | *pulDigestLen = digestLen; |
1978 | |
|
1979 | 0 | sftk_TerminateOp(session, SFTK_HASH, context); |
1980 | 0 | finish: |
1981 | 0 | sftk_FreeSession(session); |
1982 | 0 | return CKR_OK; |
1983 | 0 | } |
1984 | | |
1985 | | /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */ |
1986 | | CK_RV |
1987 | | NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
1988 | | CK_ULONG ulPartLen) |
1989 | 276k | { |
1990 | 276k | SFTKSessionContext *context; |
1991 | 276k | CK_RV crv; |
1992 | | |
1993 | 276k | CHECK_FORK(); |
1994 | | |
1995 | | /* make sure we're legal */ |
1996 | 276k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, NULL); |
1997 | 276k | if (crv != CKR_OK) |
1998 | 0 | return crv; |
1999 | | |
2000 | 276k | #if (ULONG_MAX > UINT_MAX) |
2001 | | /* The context->hashUpdate function takes an unsigned int for its data |
2002 | | * length argument, but NSC_DigestUpdate takes an unsigned long. */ |
2003 | 276k | while (ulPartLen > UINT_MAX) { |
2004 | 0 | (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX); |
2005 | 0 | pPart += UINT_MAX; |
2006 | 0 | ulPartLen -= UINT_MAX; |
2007 | 0 | } |
2008 | 276k | #endif |
2009 | 276k | (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen); |
2010 | | |
2011 | 276k | return CKR_OK; |
2012 | 276k | } |
2013 | | |
2014 | | /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */ |
2015 | | CK_RV |
2016 | | NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, |
2017 | | CK_ULONG_PTR pulDigestLen) |
2018 | 141k | { |
2019 | 141k | SFTKSession *session; |
2020 | 141k | SFTKSessionContext *context; |
2021 | 141k | unsigned int maxout = *pulDigestLen; |
2022 | 141k | unsigned int digestLen; |
2023 | 141k | CK_RV crv; |
2024 | | |
2025 | 141k | CHECK_FORK(); |
2026 | | |
2027 | | /* make sure we're legal */ |
2028 | 141k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
2029 | 141k | if (crv != CKR_OK) |
2030 | 12.5k | return crv; |
2031 | | |
2032 | 128k | if (pDigest != NULL) { |
2033 | 128k | (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
2034 | 128k | *pulDigestLen = digestLen; |
2035 | 128k | sftk_TerminateOp(session, SFTK_HASH, context); |
2036 | 128k | } else { |
2037 | 0 | *pulDigestLen = context->maxLen; |
2038 | 0 | } |
2039 | | |
2040 | 128k | sftk_FreeSession(session); |
2041 | 128k | return CKR_OK; |
2042 | 141k | } |
2043 | | |
2044 | | /* |
2045 | | * these helper functions are used by Generic Macing and Signing functions |
2046 | | * that use hashes as part of their operations. |
2047 | | */ |
2048 | | #define DOSUB(mmm) \ |
2049 | | static CK_RV \ |
2050 | | sftk_doSub##mmm(SFTKSessionContext *context) \ |
2051 | 7 | { \ |
2052 | 7 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ |
2053 | 7 | context->hashInfo = (void *)mmm##_ctx; \ |
2054 | 7 | context->hashUpdate = (SFTKHash)mmm##_Update; \ |
2055 | 7 | context->end = (SFTKEnd)mmm##_End; \ |
2056 | 7 | context->hashdestroy = (SFTKDestroy)mmm##_DestroyContext; \ |
2057 | 7 | if (!context->hashInfo) { \ |
2058 | 0 | return CKR_HOST_MEMORY; \ |
2059 | 0 | } \ |
2060 | 7 | mmm##_Begin(mmm##_ctx); \ |
2061 | 7 | return CKR_OK; \ |
2062 | 7 | } Unexecuted instantiation: pkcs11c.c:sftk_doSubMD5 Unexecuted instantiation: pkcs11c.c:sftk_doSubMD2 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA1 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA224 pkcs11c.c:sftk_doSubSHA256 Line | Count | Source | 2051 | 5 | { \ | 2052 | 5 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2053 | 5 | context->hashInfo = (void *)mmm##_ctx; \ | 2054 | 5 | context->hashUpdate = (SFTKHash)mmm##_Update; \ | 2055 | 5 | context->end = (SFTKEnd)mmm##_End; \ | 2056 | 5 | context->hashdestroy = (SFTKDestroy)mmm##_DestroyContext; \ | 2057 | 5 | if (!context->hashInfo) { \ | 2058 | 0 | return CKR_HOST_MEMORY; \ | 2059 | 0 | } \ | 2060 | 5 | mmm##_Begin(mmm##_ctx); \ | 2061 | 5 | return CKR_OK; \ | 2062 | 5 | } |
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA384 pkcs11c.c:sftk_doSubSHA512 Line | Count | Source | 2051 | 2 | { \ | 2052 | 2 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2053 | 2 | context->hashInfo = (void *)mmm##_ctx; \ | 2054 | 2 | context->hashUpdate = (SFTKHash)mmm##_Update; \ | 2055 | 2 | context->end = (SFTKEnd)mmm##_End; \ | 2056 | 2 | context->hashdestroy = (SFTKDestroy)mmm##_DestroyContext; \ | 2057 | 2 | if (!context->hashInfo) { \ | 2058 | 0 | return CKR_HOST_MEMORY; \ | 2059 | 0 | } \ | 2060 | 2 | mmm##_Begin(mmm##_ctx); \ | 2061 | 2 | return CKR_OK; \ | 2062 | 2 | } |
|
2063 | | |
2064 | | DOSUB(MD2) |
2065 | | DOSUB(MD5) |
2066 | | DOSUB(SHA1) |
2067 | | DOSUB(SHA224) |
2068 | | DOSUB(SHA256) |
2069 | | DOSUB(SHA384) |
2070 | | DOSUB(SHA512) |
2071 | | |
2072 | | static SECStatus |
2073 | | sftk_SignCopy( |
2074 | | CK_ULONG *copyLen, |
2075 | | void *out, unsigned int *outLength, |
2076 | | unsigned int maxLength, |
2077 | | const unsigned char *hashResult, |
2078 | | unsigned int hashResultLength) |
2079 | 24.1k | { |
2080 | 24.1k | unsigned int toCopy = *copyLen; |
2081 | 24.1k | if (toCopy > maxLength) { |
2082 | 0 | toCopy = maxLength; |
2083 | 0 | } |
2084 | 24.1k | if (toCopy > hashResultLength) { |
2085 | 0 | toCopy = hashResultLength; |
2086 | 0 | } |
2087 | 24.1k | memcpy(out, hashResult, toCopy); |
2088 | 24.1k | if (outLength) { |
2089 | 24.1k | *outLength = toCopy; |
2090 | 24.1k | } |
2091 | 24.1k | return SECSuccess; |
2092 | 24.1k | } |
2093 | | |
2094 | | /* Verify is just a compare for HMAC */ |
2095 | | static SECStatus |
2096 | | sftk_HMACCmp(CK_ULONG *copyLen, unsigned char *sig, unsigned int sigLen, |
2097 | | unsigned char *hash, unsigned int hashLen) |
2098 | 0 | { |
2099 | 0 | if (NSS_SecureMemcmp(sig, hash, *copyLen) == 0) { |
2100 | 0 | return SECSuccess; |
2101 | 0 | } |
2102 | | |
2103 | 0 | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
2104 | 0 | return SECFailure; |
2105 | 0 | } |
2106 | | |
2107 | | /* |
2108 | | * common HMAC + CMAC initialization routine |
2109 | | */ |
2110 | | static CK_RV |
2111 | | sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session, |
2112 | | SFTKObject *key, CK_ULONG mac_size) |
2113 | 28.1k | { |
2114 | 28.1k | CK_RV crv; |
2115 | 28.1k | sftk_MACCtx *context; |
2116 | 28.1k | CK_ULONG *intpointer; |
2117 | 28.1k | PRBool isFIPS = sftk_isFIPS(key->slot->slotID); |
2118 | | |
2119 | | /* Set up the initial context. */ |
2120 | 28.1k | crv = sftk_MAC_Create(mech, key, &context); |
2121 | 28.1k | if (crv != CKR_OK) { |
2122 | 0 | return crv; |
2123 | 0 | } |
2124 | | |
2125 | 28.1k | session->hashInfo = context; |
2126 | 28.1k | session->multi = PR_TRUE; |
2127 | | |
2128 | | /* Required by FIPS 198 Section 4. Delay this check until after the MAC |
2129 | | * has been initialized to steal the output size of the MAC. */ |
2130 | 28.1k | if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) { |
2131 | 0 | sftk_MAC_Destroy(context, PR_TRUE); |
2132 | 0 | return CKR_BUFFER_TOO_SMALL; |
2133 | 0 | } |
2134 | | |
2135 | | /* Configure our helper functions appropriately. Note that these casts |
2136 | | * ignore the return values. */ |
2137 | 28.1k | session->hashUpdate = (SFTKHash)sftk_MAC_Update; |
2138 | 28.1k | session->end = (SFTKEnd)sftk_MAC_Finish; |
2139 | 28.1k | session->hashdestroy = (SFTKDestroy)sftk_MAC_Destroy; |
2140 | | |
2141 | 28.1k | intpointer = PORT_New(CK_ULONG); |
2142 | 28.1k | if (intpointer == NULL) { |
2143 | 0 | sftk_MAC_Destroy(context, PR_TRUE); |
2144 | 0 | return CKR_HOST_MEMORY; |
2145 | 0 | } |
2146 | 28.1k | *intpointer = mac_size; |
2147 | 28.1k | session->cipherInfo = intpointer; |
2148 | | |
2149 | | /* Since we're only "hashing", copy the result from session->end to the |
2150 | | * caller using sftk_SignCopy. */ |
2151 | 28.1k | session->update = (SFTKCipher)sftk_SignCopy; |
2152 | 28.1k | session->verify = (SFTKVerify)sftk_HMACCmp; |
2153 | 28.1k | session->destroy = (SFTKDestroy)sftk_Space; |
2154 | | |
2155 | 28.1k | session->maxLen = context->mac_size; |
2156 | | |
2157 | 28.1k | return CKR_OK; |
2158 | 28.1k | } |
2159 | | |
2160 | | /* |
2161 | | * SSL Macing support. SSL Macs are inited, then update with the base |
2162 | | * hashing algorithm, then finalized in sign and verify |
2163 | | */ |
2164 | | |
2165 | | /* |
2166 | | * FROM SSL: |
2167 | | * 60 bytes is 3 times the maximum length MAC size that is supported. |
2168 | | * We probably should have one copy of this table. We still need this table |
2169 | | * in ssl to 'sign' the handshake hashes. |
2170 | | */ |
2171 | | static unsigned char ssl_pad_1[60] = { |
2172 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2173 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2174 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2175 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2176 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2177 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2178 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2179 | | 0x36, 0x36, 0x36, 0x36 |
2180 | | }; |
2181 | | static unsigned char ssl_pad_2[60] = { |
2182 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2183 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2184 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2185 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2186 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2187 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2188 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2189 | | 0x5c, 0x5c, 0x5c, 0x5c |
2190 | | }; |
2191 | | |
2192 | | static SECStatus |
2193 | | sftk_SSLMACSign(SFTKSSLMACInfo *info, unsigned char *sig, unsigned int *sigLen, |
2194 | | unsigned int maxLen, unsigned char *hash, unsigned int hashLen) |
2195 | 0 | { |
2196 | 0 | unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
2197 | 0 | unsigned int out; |
2198 | |
|
2199 | 0 | info->begin(info->hashContext); |
2200 | 0 | info->update(info->hashContext, info->key, info->keySize); |
2201 | 0 | info->update(info->hashContext, ssl_pad_2, info->padSize); |
2202 | 0 | info->update(info->hashContext, hash, hashLen); |
2203 | 0 | info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); |
2204 | 0 | PORT_Memcpy(sig, tmpBuf, info->macSize); |
2205 | 0 | PORT_Memset(tmpBuf, 0, info->macSize); |
2206 | 0 | *sigLen = info->macSize; |
2207 | 0 | return SECSuccess; |
2208 | 0 | } |
2209 | | |
2210 | | static SECStatus |
2211 | | sftk_SSLMACVerify(SFTKSSLMACInfo *info, unsigned char *sig, unsigned int sigLen, |
2212 | | unsigned char *hash, unsigned int hashLen) |
2213 | 0 | { |
2214 | 0 | unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
2215 | 0 | unsigned int out; |
2216 | 0 | int cmp; |
2217 | |
|
2218 | 0 | info->begin(info->hashContext); |
2219 | 0 | info->update(info->hashContext, info->key, info->keySize); |
2220 | 0 | info->update(info->hashContext, ssl_pad_2, info->padSize); |
2221 | 0 | info->update(info->hashContext, hash, hashLen); |
2222 | 0 | info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); |
2223 | 0 | cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize); |
2224 | 0 | PORT_Memset(tmpBuf, 0, info->macSize); |
2225 | 0 | return (cmp == 0) ? SECSuccess : SECFailure; |
2226 | 0 | } |
2227 | | |
2228 | | /* |
2229 | | * common HMAC initalization routine |
2230 | | */ |
2231 | | static CK_RV |
2232 | | sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid, |
2233 | | SFTKObject *key, CK_ULONG mac_size) |
2234 | 0 | { |
2235 | 0 | SFTKAttribute *keyval; |
2236 | 0 | SFTKBegin begin; |
2237 | 0 | int padSize; |
2238 | 0 | SFTKSSLMACInfo *sslmacinfo; |
2239 | 0 | CK_RV crv = CKR_MECHANISM_INVALID; |
2240 | |
|
2241 | 0 | if (oid == SEC_OID_SHA1) { |
2242 | 0 | crv = sftk_doSubSHA1(context); |
2243 | 0 | if (crv != CKR_OK) |
2244 | 0 | return crv; |
2245 | 0 | begin = (SFTKBegin)SHA1_Begin; |
2246 | 0 | padSize = 40; |
2247 | 0 | } else { |
2248 | 0 | crv = sftk_doSubMD5(context); |
2249 | 0 | if (crv != CKR_OK) |
2250 | 0 | return crv; |
2251 | 0 | begin = (SFTKBegin)MD5_Begin; |
2252 | 0 | padSize = 48; |
2253 | 0 | } |
2254 | 0 | context->multi = PR_TRUE; |
2255 | |
|
2256 | 0 | keyval = sftk_FindAttribute(key, CKA_VALUE); |
2257 | 0 | if (keyval == NULL) |
2258 | 0 | return CKR_KEY_SIZE_RANGE; |
2259 | | |
2260 | 0 | context->hashUpdate(context->hashInfo, keyval->attrib.pValue, |
2261 | 0 | keyval->attrib.ulValueLen); |
2262 | 0 | context->hashUpdate(context->hashInfo, ssl_pad_1, padSize); |
2263 | 0 | sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo)); |
2264 | 0 | if (sslmacinfo == NULL) { |
2265 | 0 | sftk_FreeAttribute(keyval); |
2266 | 0 | return CKR_HOST_MEMORY; |
2267 | 0 | } |
2268 | 0 | sslmacinfo->size = sizeof(SFTKSSLMACInfo); |
2269 | 0 | sslmacinfo->macSize = mac_size; |
2270 | 0 | sslmacinfo->hashContext = context->hashInfo; |
2271 | 0 | PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue, |
2272 | 0 | keyval->attrib.ulValueLen); |
2273 | 0 | sslmacinfo->keySize = keyval->attrib.ulValueLen; |
2274 | 0 | sslmacinfo->begin = begin; |
2275 | 0 | sslmacinfo->end = context->end; |
2276 | 0 | sslmacinfo->update = context->hashUpdate; |
2277 | 0 | sslmacinfo->padSize = padSize; |
2278 | 0 | sftk_FreeAttribute(keyval); |
2279 | 0 | context->cipherInfo = (void *)sslmacinfo; |
2280 | 0 | context->destroy = (SFTKDestroy)sftk_ZSpace; |
2281 | 0 | context->update = (SFTKCipher)sftk_SSLMACSign; |
2282 | 0 | context->verify = (SFTKVerify)sftk_SSLMACVerify; |
2283 | 0 | context->maxLen = mac_size; |
2284 | 0 | return CKR_OK; |
2285 | 0 | } |
2286 | | |
2287 | | /* |
2288 | | ************** Crypto Functions: Sign ************************ |
2289 | | */ |
2290 | | |
2291 | | /** |
2292 | | * Check if We're using CBCMacing and initialize the session context if we are. |
2293 | | * @param contextType SFTK_SIGN or SFTK_VERIFY |
2294 | | * @param keyUsage check whether key allows this usage |
2295 | | */ |
2296 | | static CK_RV |
2297 | | sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
2298 | | CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, |
2299 | | SFTKContextType contextType) |
2300 | | |
2301 | 64.4k | { |
2302 | 64.4k | CK_MECHANISM cbc_mechanism; |
2303 | 64.4k | CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE; |
2304 | 64.4k | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
2305 | 64.4k | CK_RC2_CBC_PARAMS rc2_params; |
2306 | 64.4k | #endif |
2307 | | #if NSS_SOFTOKEN_DOES_RC5 |
2308 | | CK_RC5_CBC_PARAMS rc5_params; |
2309 | | CK_RC5_MAC_GENERAL_PARAMS *rc5_mac; |
2310 | | #endif |
2311 | 64.4k | unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE]; |
2312 | 64.4k | unsigned char k2[SFTK_MAX_BLOCK_SIZE]; |
2313 | 64.4k | unsigned char k3[SFTK_MAX_BLOCK_SIZE]; |
2314 | 64.4k | SFTKSessionContext *context; |
2315 | 64.4k | CK_RV crv; |
2316 | 64.4k | unsigned int blockSize; |
2317 | 64.4k | PRBool isXCBC = PR_FALSE; |
2318 | | |
2319 | 64.4k | if (!pMechanism) { |
2320 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
2321 | 0 | } |
2322 | | |
2323 | 64.4k | switch (pMechanism->mechanism) { |
2324 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
2325 | 0 | case CKM_RC2_MAC_GENERAL: |
2326 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) { |
2327 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
2328 | 0 | } |
2329 | 0 | mac_bytes = |
2330 | 0 | ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
2331 | | /* fall through */ |
2332 | 0 | case CKM_RC2_MAC: |
2333 | | /* this works because ulEffectiveBits is in the same place in both the |
2334 | | * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ |
2335 | 0 | rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) |
2336 | 0 | pMechanism->pParameter) |
2337 | 0 | ->ulEffectiveBits; |
2338 | 0 | PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv)); |
2339 | 0 | cbc_mechanism.mechanism = CKM_RC2_CBC; |
2340 | 0 | cbc_mechanism.pParameter = &rc2_params; |
2341 | 0 | cbc_mechanism.ulParameterLen = sizeof(rc2_params); |
2342 | 0 | blockSize = 8; |
2343 | 0 | break; |
2344 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
2345 | | |
2346 | | #if NSS_SOFTOKEN_DOES_RC5 |
2347 | | case CKM_RC5_MAC_GENERAL: |
2348 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) { |
2349 | | return CKR_MECHANISM_PARAM_INVALID; |
2350 | | } |
2351 | | mac_bytes = |
2352 | | ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
2353 | | /* fall through */ |
2354 | | case CKM_RC5_MAC: |
2355 | | /* this works because ulEffectiveBits is in the same place in both the |
2356 | | * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ |
2357 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) { |
2358 | | return CKR_MECHANISM_PARAM_INVALID; |
2359 | | } |
2360 | | rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; |
2361 | | rc5_params.ulWordsize = rc5_mac->ulWordsize; |
2362 | | rc5_params.ulRounds = rc5_mac->ulRounds; |
2363 | | rc5_params.pIv = ivBlock; |
2364 | | if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE) |
2365 | | return CKR_MECHANISM_PARAM_INVALID; |
2366 | | rc5_params.ulIvLen = blockSize; |
2367 | | PORT_Memset(ivBlock, 0, blockSize); |
2368 | | cbc_mechanism.mechanism = CKM_RC5_CBC; |
2369 | | cbc_mechanism.pParameter = &rc5_params; |
2370 | | cbc_mechanism.ulParameterLen = sizeof(rc5_params); |
2371 | | break; |
2372 | | #endif |
2373 | | /* add cast and idea later */ |
2374 | 0 | case CKM_DES_MAC_GENERAL: |
2375 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2376 | | /* fall through */ |
2377 | 0 | case CKM_DES_MAC: |
2378 | 0 | blockSize = 8; |
2379 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2380 | 0 | cbc_mechanism.mechanism = CKM_DES_CBC; |
2381 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2382 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2383 | 0 | break; |
2384 | 0 | case CKM_DES3_MAC_GENERAL: |
2385 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2386 | | /* fall through */ |
2387 | 0 | case CKM_DES3_MAC: |
2388 | 0 | blockSize = 8; |
2389 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2390 | 0 | cbc_mechanism.mechanism = CKM_DES3_CBC; |
2391 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2392 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2393 | 0 | break; |
2394 | 0 | case CKM_CDMF_MAC_GENERAL: |
2395 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2396 | | /* fall through */ |
2397 | 0 | case CKM_CDMF_MAC: |
2398 | 0 | blockSize = 8; |
2399 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2400 | 0 | cbc_mechanism.mechanism = CKM_CDMF_CBC; |
2401 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2402 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2403 | 0 | break; |
2404 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
2405 | 0 | case CKM_SEED_MAC_GENERAL: |
2406 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2407 | | /* fall through */ |
2408 | 0 | case CKM_SEED_MAC: |
2409 | 0 | blockSize = 16; |
2410 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2411 | 0 | cbc_mechanism.mechanism = CKM_SEED_CBC; |
2412 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2413 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2414 | 0 | break; |
2415 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
2416 | 0 | case CKM_CAMELLIA_MAC_GENERAL: |
2417 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2418 | | /* fall through */ |
2419 | 0 | case CKM_CAMELLIA_MAC: |
2420 | 0 | blockSize = 16; |
2421 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2422 | 0 | cbc_mechanism.mechanism = CKM_CAMELLIA_CBC; |
2423 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2424 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2425 | 0 | break; |
2426 | 0 | case CKM_AES_MAC_GENERAL: |
2427 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2428 | | /* fall through */ |
2429 | 0 | case CKM_AES_MAC: |
2430 | 0 | blockSize = 16; |
2431 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2432 | 0 | cbc_mechanism.mechanism = CKM_AES_CBC; |
2433 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2434 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2435 | 0 | break; |
2436 | 0 | case CKM_AES_XCBC_MAC_96: |
2437 | 0 | case CKM_AES_XCBC_MAC: |
2438 | | /* The only difference between CKM_AES_XCBC_MAC |
2439 | | * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */ |
2440 | 0 | mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16; |
2441 | 0 | blockSize = 16; |
2442 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2443 | 0 | cbc_mechanism.mechanism = CKM_AES_CBC; |
2444 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2445 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2446 | | /* is XCBC requires extra processing at the end of the operation */ |
2447 | 0 | isXCBC = PR_TRUE; |
2448 | | /* The input key is used to generate k1, k2, and k3. k2 and k3 |
2449 | | * are used at the end in the pad step. k1 replaces the input |
2450 | | * key in the aes cbc mac */ |
2451 | 0 | crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3); |
2452 | 0 | if (crv != CKR_OK) { |
2453 | 0 | return crv; |
2454 | 0 | } |
2455 | 0 | break; |
2456 | 64.4k | default: |
2457 | 64.4k | return CKR_FUNCTION_NOT_SUPPORTED; |
2458 | 64.4k | } |
2459 | | |
2460 | | /* if MAC size is externally supplied, it should be checked. |
2461 | | */ |
2462 | 0 | if (mac_bytes == SFTK_INVALID_MAC_SIZE) |
2463 | 0 | mac_bytes = blockSize >> 1; |
2464 | 0 | else { |
2465 | 0 | if (mac_bytes > blockSize) { |
2466 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
2467 | 0 | goto fail; |
2468 | 0 | } |
2469 | 0 | } |
2470 | | |
2471 | 0 | crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, |
2472 | 0 | CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ |
2473 | 0 | keyUsage, contextType, PR_TRUE); |
2474 | 0 | if (crv != CKR_OK) |
2475 | 0 | goto fail; |
2476 | 0 | crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL); |
2477 | | |
2478 | | /* this shouldn't happen! */ |
2479 | 0 | PORT_Assert(crv == CKR_OK); |
2480 | 0 | if (crv != CKR_OK) |
2481 | 0 | goto fail; |
2482 | 0 | context->blockSize = blockSize; |
2483 | 0 | context->macSize = mac_bytes; |
2484 | 0 | context->isXCBC = isXCBC; |
2485 | 0 | if (isXCBC) { |
2486 | | /* save the xcbc specific parameters */ |
2487 | 0 | PORT_Memcpy(context->k2, k2, blockSize); |
2488 | 0 | PORT_Memcpy(context->k3, k3, blockSize); |
2489 | 0 | PORT_Memset(k2, 0, blockSize); |
2490 | 0 | PORT_Memset(k3, 0, blockSize); |
2491 | | /* get rid of the temp key now that the context has been created */ |
2492 | 0 | NSC_DestroyObject(hSession, hKey); |
2493 | 0 | } |
2494 | 0 | return CKR_OK; |
2495 | 0 | fail: |
2496 | 0 | if (isXCBC) { |
2497 | 0 | PORT_Memset(k2, 0, blockSize); |
2498 | 0 | PORT_Memset(k3, 0, blockSize); |
2499 | 0 | NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */ |
2500 | 0 | } |
2501 | 0 | return crv; |
2502 | 0 | } |
2503 | | |
2504 | | /* |
2505 | | * encode RSA PKCS #1 Signature data before signing... |
2506 | | */ |
2507 | | static SECStatus |
2508 | | sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig, |
2509 | | unsigned int *sigLen, unsigned int maxLen, |
2510 | | const unsigned char *hash, unsigned int hashLen) |
2511 | 0 | { |
2512 | 0 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
2513 | 0 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
2514 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2515 | 0 | return SECFailure; |
2516 | 0 | } |
2517 | | |
2518 | 0 | return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen, |
2519 | 0 | hash, hashLen); |
2520 | 0 | } |
2521 | | |
2522 | | /* XXX Old template; want to expunge it eventually. */ |
2523 | | static DERTemplate SECAlgorithmIDTemplate[] = { |
2524 | | { DER_SEQUENCE, |
2525 | | 0, NULL, sizeof(SECAlgorithmID) }, |
2526 | | { DER_OBJECT_ID, |
2527 | | offsetof(SECAlgorithmID, algorithm) }, |
2528 | | { DER_OPTIONAL | DER_ANY, |
2529 | | offsetof(SECAlgorithmID, parameters) }, |
2530 | | { 0 } |
2531 | | }; |
2532 | | |
2533 | | /* |
2534 | | * XXX OLD Template. Once all uses have been switched over to new one, |
2535 | | * remove this. |
2536 | | */ |
2537 | | static DERTemplate SGNDigestInfoTemplate[] = { |
2538 | | { DER_SEQUENCE, |
2539 | | 0, NULL, sizeof(SGNDigestInfo) }, |
2540 | | { DER_INLINE, |
2541 | | offsetof(SGNDigestInfo, digestAlgorithm), |
2542 | | SECAlgorithmIDTemplate }, |
2543 | | { DER_OCTET_STRING, |
2544 | | offsetof(SGNDigestInfo, digest) }, |
2545 | | { 0 } |
2546 | | }; |
2547 | | |
2548 | | /* |
2549 | | * encode RSA PKCS #1 Signature data before signing... |
2550 | | */ |
2551 | | SECStatus |
2552 | | RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, |
2553 | | unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, |
2554 | | const unsigned char *hash, unsigned int hashLen) |
2555 | 0 | { |
2556 | 0 | SECStatus rv = SECFailure; |
2557 | 0 | SECItem digder; |
2558 | 0 | PLArenaPool *arena = NULL; |
2559 | 0 | SGNDigestInfo *di = NULL; |
2560 | |
|
2561 | 0 | digder.data = NULL; |
2562 | |
|
2563 | 0 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
2564 | 0 | if (!arena) { |
2565 | 0 | goto loser; |
2566 | 0 | } |
2567 | | |
2568 | | /* Construct digest info */ |
2569 | 0 | di = SGN_CreateDigestInfo(hashOid, hash, hashLen); |
2570 | 0 | if (!di) { |
2571 | 0 | goto loser; |
2572 | 0 | } |
2573 | | |
2574 | | /* Der encode the digest as a DigestInfo */ |
2575 | 0 | rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); |
2576 | 0 | if (rv != SECSuccess) { |
2577 | 0 | goto loser; |
2578 | 0 | } |
2579 | | |
2580 | | /* |
2581 | | ** Encrypt signature after constructing appropriate PKCS#1 signature |
2582 | | ** block |
2583 | | */ |
2584 | 0 | rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data, |
2585 | 0 | digder.len); |
2586 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2587 | 0 | sftk_fatalError = PR_TRUE; |
2588 | 0 | } |
2589 | |
|
2590 | 0 | loser: |
2591 | 0 | SGN_DestroyDigestInfo(di); |
2592 | 0 | if (arena != NULL) { |
2593 | 0 | PORT_FreeArena(arena, PR_TRUE); |
2594 | 0 | } |
2595 | 0 | return rv; |
2596 | 0 | } |
2597 | | |
2598 | | static SECStatus |
2599 | | sftk_RSASign(NSSLOWKEYPrivateKey *key, unsigned char *output, |
2600 | | unsigned int *outputLen, unsigned int maxOutputLen, |
2601 | | const unsigned char *input, unsigned int inputLen) |
2602 | 12.0k | { |
2603 | 12.0k | SECStatus rv = SECFailure; |
2604 | | |
2605 | 12.0k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
2606 | 12.0k | if (key->keyType != NSSLOWKEYRSAKey) { |
2607 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2608 | 0 | return SECFailure; |
2609 | 0 | } |
2610 | | |
2611 | 12.0k | rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input, |
2612 | 12.0k | inputLen); |
2613 | 12.0k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2614 | 0 | sftk_fatalError = PR_TRUE; |
2615 | 0 | } |
2616 | 12.0k | return rv; |
2617 | 12.0k | } |
2618 | | |
2619 | | static SECStatus |
2620 | | sftk_RSASignRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, |
2621 | | unsigned int *outputLen, unsigned int maxOutputLen, |
2622 | | const unsigned char *input, unsigned int inputLen) |
2623 | 0 | { |
2624 | 0 | SECStatus rv = SECFailure; |
2625 | |
|
2626 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
2627 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
2628 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2629 | 0 | return SECFailure; |
2630 | 0 | } |
2631 | | |
2632 | 0 | rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input, |
2633 | 0 | inputLen); |
2634 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2635 | 0 | sftk_fatalError = PR_TRUE; |
2636 | 0 | } |
2637 | 0 | return rv; |
2638 | 0 | } |
2639 | | |
2640 | | static SECStatus |
2641 | | sftk_RSASignPSS(SFTKPSSSignInfo *info, unsigned char *sig, |
2642 | | unsigned int *sigLen, unsigned int maxLen, |
2643 | | const unsigned char *hash, unsigned int hashLen) |
2644 | 939 | { |
2645 | 939 | SECStatus rv = SECFailure; |
2646 | 939 | HASH_HashType hashAlg; |
2647 | 939 | HASH_HashType maskHashAlg; |
2648 | 939 | CK_RSA_PKCS_PSS_PARAMS *params = &info->params; |
2649 | | |
2650 | 939 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
2651 | 939 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
2652 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2653 | 0 | return SECFailure; |
2654 | 0 | } |
2655 | | |
2656 | 939 | hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg); |
2657 | 939 | maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf); |
2658 | | |
2659 | 939 | rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL, |
2660 | 939 | params->sLen, sig, sigLen, maxLen, hash, hashLen); |
2661 | 939 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2662 | 0 | sftk_fatalError = PR_TRUE; |
2663 | 0 | } |
2664 | 939 | return rv; |
2665 | 939 | } |
2666 | | |
2667 | | static SECStatus |
2668 | | nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen, |
2669 | | void *dataBuf, unsigned int dataLen) |
2670 | 10 | { |
2671 | 10 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2672 | 10 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2673 | 10 | NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; |
2674 | 10 | return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest); |
2675 | 10 | } |
2676 | | |
2677 | | static SECStatus |
2678 | | nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, |
2679 | | unsigned int *sigLen, unsigned int maxSigLen, |
2680 | | void *dataBuf, unsigned int dataLen) |
2681 | 0 | { |
2682 | 0 | NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; |
2683 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen }; |
2684 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2685 | 0 | SECStatus rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); |
2686 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2687 | 0 | sftk_fatalError = PR_TRUE; |
2688 | 0 | } |
2689 | 0 | *sigLen = signature.len; |
2690 | 0 | return rv; |
2691 | 0 | } |
2692 | | |
2693 | | static SECStatus |
2694 | | nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen, |
2695 | | void *dataBuf, unsigned int dataLen) |
2696 | 1.37k | { |
2697 | 1.37k | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2698 | 1.37k | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2699 | 1.37k | NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; |
2700 | 1.37k | return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest); |
2701 | 1.37k | } |
2702 | | |
2703 | | static SECStatus |
2704 | | nsc_ECDSASignStub(void *ctx, void *sigBuf, |
2705 | | unsigned int *sigLen, unsigned int maxSigLen, |
2706 | | void *dataBuf, unsigned int dataLen) |
2707 | 1.30k | { |
2708 | 1.30k | NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; |
2709 | 1.30k | SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen }; |
2710 | 1.30k | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2711 | | |
2712 | 1.30k | SECStatus rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); |
2713 | 1.30k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2714 | 0 | sftk_fatalError = PR_TRUE; |
2715 | 0 | } |
2716 | 1.30k | *sigLen = signature.len; |
2717 | 1.30k | return rv; |
2718 | 1.30k | } |
2719 | | |
2720 | | static SECStatus |
2721 | | nsc_EDDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen, |
2722 | | void *dataBuf, unsigned int dataLen) |
2723 | 0 | { |
2724 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2725 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2726 | 0 | NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; |
2727 | 0 | return ED_VerifyMessage(&(key->u.ec), &signature, &digest); |
2728 | 0 | } |
2729 | | |
2730 | | static SECStatus |
2731 | | nsc_EDDSASignStub(void *ctx, void *sigBuf, |
2732 | | unsigned int *sigLen, unsigned int maxSigLen, |
2733 | | void *dataBuf, unsigned int dataLen) |
2734 | 0 | { |
2735 | 0 | NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; |
2736 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen }; |
2737 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2738 | |
|
2739 | 0 | SECStatus rv = ED_SignMessage(&(key->u.ec), &signature, &digest); |
2740 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2741 | 0 | sftk_fatalError = PR_TRUE; |
2742 | 0 | } |
2743 | 0 | *sigLen = signature.len; |
2744 | 0 | return rv; |
2745 | 0 | } |
2746 | | |
2747 | | /* NSC_SignInit setups up the signing operations. There are three basic |
2748 | | * types of signing: |
2749 | | * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied |
2750 | | * to data in a single Sign operation (which often looks a lot like an |
2751 | | * encrypt, with data coming in and data going out). |
2752 | | * (2) Hash based signing, where we continually hash the data, then apply |
2753 | | * some sort of signature to the end. |
2754 | | * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, |
2755 | | * and only the final block is part of the mac. |
2756 | | * |
2757 | | * For case number 3, we initialize a context much like the Encryption Context |
2758 | | * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and |
2759 | | * C_Final by the following method... if it's not multi-part, and it's doesn't |
2760 | | * have a hash context, it must be a block Encryption CBC MAC. |
2761 | | * |
2762 | | * For case number 2, we initialize a hash structure, as well as make it |
2763 | | * multi-part. Updates are simple calls to the hash update function. Final |
2764 | | * calls the hashend, then passes the result to the 'update' function (which |
2765 | | * operates as a final signature function). In some hash based MAC'ing (as |
2766 | | * opposed to hash base signatures), the update function is can be simply a |
2767 | | * copy (as is the case with HMAC). |
2768 | | */ |
2769 | | CK_RV |
2770 | | NSC_SignInit(CK_SESSION_HANDLE hSession, |
2771 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
2772 | 60.4k | { |
2773 | 60.4k | SFTKSession *session; |
2774 | 60.4k | SFTKObject *key; |
2775 | 60.4k | SFTKSessionContext *context; |
2776 | 60.4k | CK_KEY_TYPE key_type; |
2777 | 60.4k | CK_RV crv = CKR_OK; |
2778 | 60.4k | NSSLOWKEYPrivateKey *privKey; |
2779 | 60.4k | SFTKHashSignInfo *info = NULL; |
2780 | 60.4k | SFTKPSSSignInfo *pinfo = NULL; |
2781 | | |
2782 | 60.4k | CHECK_FORK(); |
2783 | | |
2784 | | /* Block Cipher MACing Algorithms use a different Context init method..*/ |
2785 | 60.4k | crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN); |
2786 | 60.4k | if (crv != CKR_FUNCTION_NOT_SUPPORTED) |
2787 | 0 | return crv; |
2788 | | |
2789 | | /* we're not using a block cipher mac */ |
2790 | 60.4k | session = sftk_SessionFromHandle(hSession); |
2791 | 60.4k | if (session == NULL) |
2792 | 0 | return CKR_SESSION_HANDLE_INVALID; |
2793 | 60.4k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key, |
2794 | 60.4k | hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN); |
2795 | 60.4k | if (crv != CKR_OK) { |
2796 | 0 | sftk_FreeSession(session); |
2797 | 0 | return crv; |
2798 | 0 | } |
2799 | | |
2800 | 60.4k | context->multi = PR_FALSE; |
2801 | | |
2802 | 60.4k | #define INIT_RSA_SIGN_MECH(mmm) \ |
2803 | 60.4k | case CKM_##mmm##_RSA_PKCS: \ |
2804 | 0 | context->multi = PR_TRUE; \ |
2805 | 0 | crv = sftk_doSub##mmm(context); \ |
2806 | 0 | if (crv != CKR_OK) \ |
2807 | 0 | break; \ |
2808 | 0 | context->update = (SFTKCipher)sftk_RSAHashSign; \ |
2809 | 0 | info = PORT_New(SFTKHashSignInfo); \ |
2810 | 0 | if (info == NULL) { \ |
2811 | 0 | crv = CKR_HOST_MEMORY; \ |
2812 | 0 | break; \ |
2813 | 0 | } \ |
2814 | 0 | info->hashOid = SEC_OID_##mmm; \ |
2815 | 0 | goto finish_rsa; |
2816 | | |
2817 | 60.4k | switch (pMechanism->mechanism) { |
2818 | 0 | INIT_RSA_SIGN_MECH(MD5) |
2819 | 0 | INIT_RSA_SIGN_MECH(MD2) |
2820 | 0 | INIT_RSA_SIGN_MECH(SHA1) |
2821 | 0 | INIT_RSA_SIGN_MECH(SHA224) |
2822 | 0 | INIT_RSA_SIGN_MECH(SHA256) |
2823 | 0 | INIT_RSA_SIGN_MECH(SHA384) |
2824 | 0 | INIT_RSA_SIGN_MECH(SHA512) |
2825 | | |
2826 | 12.0k | case CKM_RSA_PKCS: |
2827 | 12.0k | context->update = (SFTKCipher)sftk_RSASign; |
2828 | 12.0k | goto finish_rsa; |
2829 | 0 | case CKM_RSA_X_509: |
2830 | 0 | context->update = (SFTKCipher)sftk_RSASignRaw; |
2831 | 12.0k | finish_rsa: |
2832 | 12.0k | if (key_type != CKK_RSA) { |
2833 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2834 | 0 | break; |
2835 | 0 | } |
2836 | 12.0k | context->rsa = PR_TRUE; |
2837 | 12.0k | privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); |
2838 | 12.0k | if (privKey == NULL) { |
2839 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2840 | 0 | break; |
2841 | 0 | } |
2842 | | /* OK, info is allocated only if we're doing hash and sign mechanism. |
2843 | | * It's necessary to be able to set the correct OID in the final |
2844 | | * signature. |
2845 | | */ |
2846 | 12.0k | if (info) { |
2847 | 0 | info->key = privKey; |
2848 | 0 | context->cipherInfo = info; |
2849 | 0 | context->destroy = (SFTKDestroy)sftk_Space; |
2850 | 12.0k | } else { |
2851 | 12.0k | context->cipherInfo = privKey; |
2852 | 12.0k | context->destroy = (SFTKDestroy)sftk_Null; |
2853 | 12.0k | } |
2854 | 12.0k | context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
2855 | 12.0k | break; |
2856 | | |
2857 | 0 | #define INIT_RSA_PSS_SIG_MECH(mmm) \ |
2858 | 0 | case CKM_##mmm##_RSA_PKCS_PSS: \ |
2859 | 0 | context->multi = PR_TRUE; \ |
2860 | 0 | crv = sftk_doSub##mmm(context); \ |
2861 | 0 | if (crv != CKR_OK) \ |
2862 | 0 | break; \ |
2863 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) { \ |
2864 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
2865 | 0 | break; \ |
2866 | 0 | } \ |
2867 | 0 | if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \ |
2868 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
2869 | 0 | break; \ |
2870 | 0 | } \ |
2871 | 0 | goto finish_rsa_pss; |
2872 | 0 | INIT_RSA_PSS_SIG_MECH(SHA1) |
2873 | 0 | INIT_RSA_PSS_SIG_MECH(SHA224) |
2874 | 0 | INIT_RSA_PSS_SIG_MECH(SHA256) |
2875 | 0 | INIT_RSA_PSS_SIG_MECH(SHA384) |
2876 | 0 | INIT_RSA_PSS_SIG_MECH(SHA512) |
2877 | 939 | case CKM_RSA_PKCS_PSS: |
2878 | 939 | finish_rsa_pss: |
2879 | 939 | if (key_type != CKK_RSA) { |
2880 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2881 | 0 | break; |
2882 | 0 | } |
2883 | 939 | context->rsa = PR_TRUE; |
2884 | 939 | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
2885 | 939 | !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { |
2886 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
2887 | 0 | break; |
2888 | 0 | } |
2889 | 939 | pinfo = PORT_New(SFTKPSSSignInfo); |
2890 | 939 | if (pinfo == NULL) { |
2891 | 0 | crv = CKR_HOST_MEMORY; |
2892 | 0 | break; |
2893 | 0 | } |
2894 | 939 | pinfo->size = sizeof(SFTKPSSSignInfo); |
2895 | 939 | pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter; |
2896 | 939 | pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv); |
2897 | 939 | if (pinfo->key == NULL) { |
2898 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2899 | 0 | break; |
2900 | 0 | } |
2901 | 939 | context->cipherInfo = pinfo; |
2902 | 939 | context->destroy = (SFTKDestroy)sftk_ZSpace; |
2903 | 939 | context->update = (SFTKCipher)sftk_RSASignPSS; |
2904 | 939 | context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key); |
2905 | 939 | break; |
2906 | | |
2907 | 0 | #define INIT_DSA_SIG_MECH(mmm) \ |
2908 | 0 | case CKM_DSA_##mmm: \ |
2909 | 0 | context->multi = PR_TRUE; \ |
2910 | 0 | crv = sftk_doSub##mmm(context); \ |
2911 | 0 | if (crv != CKR_OK) \ |
2912 | 0 | break; \ |
2913 | 0 | goto finish_dsa; |
2914 | 0 | INIT_DSA_SIG_MECH(SHA1) |
2915 | 0 | INIT_DSA_SIG_MECH(SHA224) |
2916 | 0 | INIT_DSA_SIG_MECH(SHA256) |
2917 | 0 | INIT_DSA_SIG_MECH(SHA384) |
2918 | 0 | INIT_DSA_SIG_MECH(SHA512) |
2919 | 0 | case CKM_DSA: |
2920 | 0 | finish_dsa: |
2921 | 0 | if (key_type != CKK_DSA) { |
2922 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2923 | 0 | break; |
2924 | 0 | } |
2925 | 0 | privKey = sftk_GetPrivKey(key, CKK_DSA, &crv); |
2926 | 0 | if (privKey == NULL) { |
2927 | 0 | break; |
2928 | 0 | } |
2929 | 0 | context->cipherInfo = privKey; |
2930 | 0 | context->update = (SFTKCipher)nsc_DSA_Sign_Stub; |
2931 | 0 | context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey; |
2932 | 0 | context->maxLen = DSA_MAX_SIGNATURE_LEN; |
2933 | |
|
2934 | 0 | break; |
2935 | | |
2936 | 0 | #define INIT_ECDSA_SIG_MECH(mmm) \ |
2937 | 3 | case CKM_ECDSA_##mmm: \ |
2938 | 3 | context->multi = PR_TRUE; \ |
2939 | 3 | crv = sftk_doSub##mmm(context); \ |
2940 | 3 | if (crv != CKR_OK) \ |
2941 | 3 | break; \ |
2942 | 3 | goto finish_ecdsa; |
2943 | 0 | INIT_ECDSA_SIG_MECH(SHA1) |
2944 | 0 | INIT_ECDSA_SIG_MECH(SHA224) |
2945 | 0 | INIT_ECDSA_SIG_MECH(SHA256) |
2946 | 0 | INIT_ECDSA_SIG_MECH(SHA384) |
2947 | 0 | INIT_ECDSA_SIG_MECH(SHA512) |
2948 | 1.30k | case CKM_ECDSA: |
2949 | 1.30k | finish_ecdsa: |
2950 | 1.30k | if (key_type != CKK_EC) { |
2951 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2952 | 0 | break; |
2953 | 0 | } |
2954 | 1.30k | privKey = sftk_GetPrivKey(key, CKK_EC, &crv); |
2955 | 1.30k | if (privKey == NULL) { |
2956 | 0 | crv = CKR_HOST_MEMORY; |
2957 | 0 | break; |
2958 | 0 | } |
2959 | 1.30k | context->cipherInfo = privKey; |
2960 | 1.30k | context->update = (SFTKCipher)nsc_ECDSASignStub; |
2961 | 1.30k | context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey; |
2962 | 1.30k | context->maxLen = MAX_ECKEY_LEN * 2; |
2963 | | |
2964 | 1.30k | break; |
2965 | | |
2966 | 0 | case CKM_EDDSA: |
2967 | 0 | if (key_type != CKK_EC_EDWARDS) { |
2968 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2969 | 0 | break; |
2970 | 0 | } |
2971 | | |
2972 | 0 | if (pMechanism->pParameter) { |
2973 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
2974 | 0 | break; |
2975 | 0 | } |
2976 | | |
2977 | 0 | privKey = sftk_GetPrivKey(key, CKK_EC_EDWARDS, &crv); |
2978 | 0 | if (privKey == NULL) { |
2979 | 0 | crv = CKR_HOST_MEMORY; |
2980 | 0 | break; |
2981 | 0 | } |
2982 | 0 | context->cipherInfo = privKey; |
2983 | 0 | context->update = (SFTKCipher)nsc_EDDSASignStub; |
2984 | 0 | context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey; |
2985 | 0 | context->maxLen = MAX_ECKEY_LEN * 2; |
2986 | |
|
2987 | 0 | break; |
2988 | | |
2989 | 0 | #define INIT_HMAC_MECH(mmm) \ |
2990 | 0 | case CKM_##mmm##_HMAC_GENERAL: \ |
2991 | 0 | PORT_Assert(pMechanism->pParameter); \ |
2992 | 0 | if (!pMechanism->pParameter) { \ |
2993 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
2994 | 0 | break; \ |
2995 | 0 | } \ |
2996 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, \ |
2997 | 0 | *(CK_ULONG *)pMechanism->pParameter); \ |
2998 | 0 | break; \ |
2999 | 28.1k | case CKM_##mmm##_HMAC: \ |
3000 | 28.1k | crv = sftk_doMACInit(pMechanism->mechanism, context, key, \ |
3001 | 28.1k | mmm##_LENGTH); \ |
3002 | 28.1k | break; |
3003 | | |
3004 | 0 | INIT_HMAC_MECH(MD2) |
3005 | 0 | INIT_HMAC_MECH(MD5) |
3006 | 0 | INIT_HMAC_MECH(SHA1) |
3007 | 0 | INIT_HMAC_MECH(SHA224) |
3008 | 0 | INIT_HMAC_MECH(SHA256) |
3009 | 0 | INIT_HMAC_MECH(SHA384) |
3010 | 0 | INIT_HMAC_MECH(SHA512) |
3011 | 0 | INIT_HMAC_MECH(SHA3_224) |
3012 | 0 | INIT_HMAC_MECH(SHA3_256) |
3013 | 0 | INIT_HMAC_MECH(SHA3_384) |
3014 | 0 | INIT_HMAC_MECH(SHA3_512) |
3015 | | |
3016 | 0 | case CKM_AES_CMAC_GENERAL: |
3017 | 0 | PORT_Assert(pMechanism->pParameter); |
3018 | 0 | if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { |
3019 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3020 | 0 | break; |
3021 | 0 | } |
3022 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter); |
3023 | 0 | break; |
3024 | 0 | case CKM_AES_CMAC: |
3025 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE); |
3026 | 0 | break; |
3027 | 0 | case CKM_SSL3_MD5_MAC: |
3028 | 0 | PORT_Assert(pMechanism->pParameter); |
3029 | 0 | if (!pMechanism->pParameter) { |
3030 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3031 | 0 | break; |
3032 | 0 | } |
3033 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, |
3034 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3035 | 0 | break; |
3036 | 0 | case CKM_SSL3_SHA1_MAC: |
3037 | 0 | PORT_Assert(pMechanism->pParameter); |
3038 | 0 | if (!pMechanism->pParameter) { |
3039 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3040 | 0 | break; |
3041 | 0 | } |
3042 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, |
3043 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3044 | 0 | break; |
3045 | 0 | case CKM_TLS_PRF_GENERAL: |
3046 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); |
3047 | 0 | break; |
3048 | 11.2k | case CKM_TLS_MAC: { |
3049 | 11.2k | CK_TLS_MAC_PARAMS *tls12_mac_params; |
3050 | 11.2k | HASH_HashType tlsPrfHash; |
3051 | 11.2k | const char *label; |
3052 | | |
3053 | 11.2k | if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) { |
3054 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3055 | 0 | break; |
3056 | 0 | } |
3057 | 11.2k | tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter; |
3058 | 11.2k | if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) { |
3059 | | /* The TLS 1.0 and 1.1 PRF */ |
3060 | 6.29k | tlsPrfHash = HASH_AlgNULL; |
3061 | 6.29k | if (tls12_mac_params->ulMacLength != 12) { |
3062 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3063 | 0 | break; |
3064 | 0 | } |
3065 | 6.29k | } else { |
3066 | | /* The hash function for the TLS 1.2 PRF */ |
3067 | 4.98k | tlsPrfHash = |
3068 | 4.98k | sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism); |
3069 | 4.98k | if (tlsPrfHash == HASH_AlgNULL || |
3070 | 4.98k | tls12_mac_params->ulMacLength < 12) { |
3071 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3072 | 0 | break; |
3073 | 0 | } |
3074 | 4.98k | } |
3075 | 11.2k | if (tls12_mac_params->ulServerOrClient == 1) { |
3076 | 4.40k | label = "server finished"; |
3077 | 6.86k | } else if (tls12_mac_params->ulServerOrClient == 2) { |
3078 | 6.86k | label = "client finished"; |
3079 | 6.86k | } else { |
3080 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3081 | 0 | break; |
3082 | 0 | } |
3083 | 11.2k | crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash, |
3084 | 11.2k | tls12_mac_params->ulMacLength); |
3085 | 11.2k | if (crv == CKR_OK) { |
3086 | 11.2k | context->hashUpdate(context->hashInfo, label, 15); |
3087 | 11.2k | } |
3088 | 11.2k | break; |
3089 | 11.2k | } |
3090 | 0 | case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
3091 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); |
3092 | 0 | break; |
3093 | | |
3094 | 6.80k | case CKM_NSS_HMAC_CONSTANT_TIME: { |
3095 | 6.80k | sftk_MACConstantTimeCtx *ctx = |
3096 | 6.80k | sftk_HMACConstantTime_New(pMechanism, key); |
3097 | 6.80k | CK_ULONG *intpointer; |
3098 | | |
3099 | 6.80k | if (ctx == NULL) { |
3100 | 0 | crv = CKR_ARGUMENTS_BAD; |
3101 | 0 | break; |
3102 | 0 | } |
3103 | 6.80k | intpointer = PORT_New(CK_ULONG); |
3104 | 6.80k | if (intpointer == NULL) { |
3105 | 0 | PORT_Free(ctx); |
3106 | 0 | crv = CKR_HOST_MEMORY; |
3107 | 0 | break; |
3108 | 0 | } |
3109 | 6.80k | *intpointer = ctx->hash->length; |
3110 | | |
3111 | 6.80k | context->cipherInfo = intpointer; |
3112 | 6.80k | context->hashInfo = ctx; |
3113 | 6.80k | context->currentMech = pMechanism->mechanism; |
3114 | 6.80k | context->hashUpdate = sftk_HMACConstantTime_Update; |
3115 | 6.80k | context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
3116 | 6.80k | context->end = sftk_MACConstantTime_EndHash; |
3117 | 6.80k | context->update = (SFTKCipher)sftk_SignCopy; |
3118 | 6.80k | context->destroy = sftk_Space; |
3119 | 6.80k | context->maxLen = 64; |
3120 | 6.80k | context->multi = PR_TRUE; |
3121 | 6.80k | break; |
3122 | 6.80k | } |
3123 | | |
3124 | 0 | case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { |
3125 | 0 | sftk_MACConstantTimeCtx *ctx = |
3126 | 0 | sftk_SSLv3MACConstantTime_New(pMechanism, key); |
3127 | 0 | CK_ULONG *intpointer; |
3128 | |
|
3129 | 0 | if (ctx == NULL) { |
3130 | 0 | crv = CKR_ARGUMENTS_BAD; |
3131 | 0 | break; |
3132 | 0 | } |
3133 | 0 | intpointer = PORT_New(CK_ULONG); |
3134 | 0 | if (intpointer == NULL) { |
3135 | 0 | PORT_Free(ctx); |
3136 | 0 | crv = CKR_HOST_MEMORY; |
3137 | 0 | break; |
3138 | 0 | } |
3139 | 0 | *intpointer = ctx->hash->length; |
3140 | |
|
3141 | 0 | context->cipherInfo = intpointer; |
3142 | 0 | context->hashInfo = ctx; |
3143 | 0 | context->currentMech = pMechanism->mechanism; |
3144 | 0 | context->hashUpdate = sftk_SSLv3MACConstantTime_Update; |
3145 | 0 | context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
3146 | 0 | context->end = sftk_MACConstantTime_EndHash; |
3147 | 0 | context->update = (SFTKCipher)sftk_SignCopy; |
3148 | 0 | context->destroy = sftk_Space; |
3149 | 0 | context->maxLen = 64; |
3150 | 0 | context->multi = PR_TRUE; |
3151 | 0 | break; |
3152 | 0 | } |
3153 | | |
3154 | 0 | default: |
3155 | 0 | crv = CKR_MECHANISM_INVALID; |
3156 | 0 | break; |
3157 | 60.4k | } |
3158 | | |
3159 | 60.4k | if (crv != CKR_OK) { |
3160 | 0 | if (info) |
3161 | 0 | PORT_Free(info); |
3162 | 0 | if (pinfo) |
3163 | 0 | PORT_ZFree(pinfo, pinfo->size); |
3164 | 0 | sftk_FreeContext(context); |
3165 | 0 | sftk_FreeSession(session); |
3166 | 0 | return crv; |
3167 | 0 | } |
3168 | 60.4k | sftk_SetContextByType(session, SFTK_SIGN, context); |
3169 | 60.4k | sftk_FreeSession(session); |
3170 | 60.4k | return CKR_OK; |
3171 | 60.4k | } |
3172 | | |
3173 | | /** MAC one block of data by block cipher |
3174 | | */ |
3175 | | static CK_RV |
3176 | | sftk_MACBlock(SFTKSessionContext *ctx, void *blk) |
3177 | 0 | { |
3178 | 0 | unsigned int outlen; |
3179 | 0 | return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen, |
3180 | 0 | SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize)) |
3181 | 0 | ? CKR_OK |
3182 | 0 | : sftk_MapCryptError(PORT_GetError()); |
3183 | 0 | } |
3184 | | |
3185 | | /** MAC last (incomplete) block of data by block cipher |
3186 | | * |
3187 | | * Call once, then terminate MACing operation. |
3188 | | */ |
3189 | | static CK_RV |
3190 | | sftk_MACFinal(SFTKSessionContext *ctx) |
3191 | 0 | { |
3192 | 0 | unsigned int padLen = ctx->padDataLength; |
3193 | | /* pad and proceed the residual */ |
3194 | 0 | if (ctx->isXCBC) { |
3195 | 0 | CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize, |
3196 | 0 | ctx->k2, ctx->k3); |
3197 | 0 | if (crv != CKR_OK) |
3198 | 0 | return crv; |
3199 | 0 | return sftk_MACBlock(ctx, ctx->padBuf); |
3200 | 0 | } |
3201 | 0 | if (padLen) { |
3202 | | /* shd clr ctx->padLen to make sftk_MACFinal idempotent */ |
3203 | 0 | PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen); |
3204 | 0 | return sftk_MACBlock(ctx, ctx->padBuf); |
3205 | 0 | } else |
3206 | 0 | return CKR_OK; |
3207 | 0 | } |
3208 | | |
3209 | | /** The common implementation for {Sign,Verify}Update. (S/V only vary in their |
3210 | | * setup and final operations). |
3211 | | * |
3212 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3213 | | */ |
3214 | | static CK_RV |
3215 | | sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3216 | | CK_ULONG ulPartLen, SFTKContextType type) |
3217 | 41.2k | { |
3218 | 41.2k | SFTKSession *session; |
3219 | 41.2k | SFTKSessionContext *context; |
3220 | 41.2k | CK_RV crv; |
3221 | | |
3222 | | /* make sure we're legal */ |
3223 | 41.2k | crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session); |
3224 | 41.2k | if (crv != CKR_OK) |
3225 | 0 | return crv; |
3226 | | |
3227 | 41.2k | if (context->hashInfo) { |
3228 | 41.2k | #if (ULONG_MAX > UINT_MAX) |
3229 | 41.2k | while (ulPartLen > UINT_MAX) { |
3230 | 0 | (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX); |
3231 | 0 | pPart += UINT_MAX; |
3232 | 0 | ulPartLen -= UINT_MAX; |
3233 | 0 | } |
3234 | 41.2k | #endif |
3235 | 41.2k | (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); |
3236 | 41.2k | } else { |
3237 | | /* must be block cipher MACing */ |
3238 | |
|
3239 | 0 | unsigned int blkSize = context->blockSize; |
3240 | 0 | unsigned char *residual = /* free room in context->padBuf */ |
3241 | 0 | context->padBuf + context->padDataLength; |
3242 | 0 | unsigned int minInput = /* min input for MACing at least one block */ |
3243 | 0 | blkSize - context->padDataLength; |
3244 | | |
3245 | | /* not enough data even for one block */ |
3246 | 0 | if (ulPartLen <= minInput) { |
3247 | 0 | PORT_Memcpy(residual, pPart, ulPartLen); |
3248 | 0 | context->padDataLength += ulPartLen; |
3249 | 0 | goto cleanup; |
3250 | 0 | } |
3251 | | /* MACing residual */ |
3252 | 0 | if (context->padDataLength) { |
3253 | 0 | PORT_Memcpy(residual, pPart, minInput); |
3254 | 0 | ulPartLen -= minInput; |
3255 | 0 | pPart += minInput; |
3256 | 0 | if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf))) |
3257 | 0 | goto terminate; |
3258 | 0 | } |
3259 | | /* MACing full blocks */ |
3260 | 0 | while (ulPartLen > blkSize) { |
3261 | 0 | if (CKR_OK != (crv = sftk_MACBlock(context, pPart))) |
3262 | 0 | goto terminate; |
3263 | 0 | ulPartLen -= blkSize; |
3264 | 0 | pPart += blkSize; |
3265 | 0 | } |
3266 | | /* save the residual */ |
3267 | 0 | if ((context->padDataLength = ulPartLen)) |
3268 | 0 | PORT_Memcpy(context->padBuf, pPart, ulPartLen); |
3269 | 0 | } /* blk cipher MACing */ |
3270 | | |
3271 | 41.2k | goto cleanup; |
3272 | | |
3273 | 41.2k | terminate: |
3274 | 0 | sftk_TerminateOp(session, type, context); |
3275 | 41.2k | cleanup: |
3276 | 41.2k | sftk_FreeSession(session); |
3277 | 41.2k | return crv; |
3278 | 0 | } |
3279 | | |
3280 | | /* NSC_SignUpdate continues a multiple-part signature operation, |
3281 | | * where the signature is (will be) an appendix to the data, |
3282 | | * and plaintext cannot be recovered from the signature |
3283 | | * |
3284 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3285 | | */ |
3286 | | CK_RV |
3287 | | NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3288 | | CK_ULONG ulPartLen) |
3289 | 41.2k | { |
3290 | 41.2k | CHECK_FORK(); |
3291 | 41.2k | return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN); |
3292 | 41.2k | } |
3293 | | |
3294 | | struct SFTK_SESSION_FLAGS { |
3295 | | CK_FLAGS flag; |
3296 | | SFTKContextType type; |
3297 | | }; |
3298 | | |
3299 | | const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = { |
3300 | | { CKF_ENCRYPT, SFTK_ENCRYPT }, |
3301 | | { CKF_DECRYPT, SFTK_DECRYPT }, |
3302 | | { CKF_DIGEST, SFTK_HASH }, |
3303 | | { CKF_SIGN, SFTK_SIGN }, |
3304 | | { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER }, |
3305 | | { CKF_VERIFY, SFTK_VERIFY }, |
3306 | | { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER }, |
3307 | | { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT }, |
3308 | | { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT }, |
3309 | | { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN }, |
3310 | | { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY }, |
3311 | | }; |
3312 | | const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags); |
3313 | | |
3314 | | /* |
3315 | | * Cancel one or more operations running on the existing session. |
3316 | | */ |
3317 | | CK_RV |
3318 | | NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags) |
3319 | 0 | { |
3320 | 0 | SFTKSession *session; |
3321 | 0 | SFTKSessionContext *context; |
3322 | 0 | CK_RV gcrv = CKR_OK; |
3323 | 0 | CK_RV crv; |
3324 | 0 | int i; |
3325 | |
|
3326 | 0 | for (i = 0; i < sftk_flag_count; i++) { |
3327 | 0 | if (flags & sftk_session_flags[i].flag) { |
3328 | 0 | flags &= ~sftk_session_flags[i].flag; |
3329 | 0 | crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session); |
3330 | 0 | if (crv != CKR_OK) { |
3331 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3332 | 0 | continue; |
3333 | 0 | } |
3334 | 0 | sftk_TerminateOp(session, sftk_session_flags[i].type, context); |
3335 | 0 | } |
3336 | 0 | } |
3337 | 0 | if (flags & CKF_FIND_OBJECTS) { |
3338 | 0 | flags &= ~CKF_FIND_OBJECTS; |
3339 | 0 | crv = NSC_FindObjectsFinal(hSession); |
3340 | 0 | if (crv != CKR_OK) { |
3341 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3342 | 0 | } |
3343 | 0 | } |
3344 | 0 | if (flags) { |
3345 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3346 | 0 | } |
3347 | 0 | return gcrv; |
3348 | 0 | } |
3349 | | |
3350 | | /* NSC_SignFinal finishes a multiple-part signature operation, |
3351 | | * returning the signature. */ |
3352 | | CK_RV |
3353 | | NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, |
3354 | | CK_ULONG_PTR pulSignatureLen) |
3355 | 50.1k | { |
3356 | 50.1k | SFTKSession *session; |
3357 | 50.1k | SFTKSessionContext *context; |
3358 | 50.1k | unsigned int outlen; |
3359 | 50.1k | unsigned int maxoutlen = *pulSignatureLen; |
3360 | 50.1k | CK_RV crv; |
3361 | | |
3362 | 50.1k | CHECK_FORK(); |
3363 | | |
3364 | | /* make sure we're legal */ |
3365 | 50.1k | crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session); |
3366 | 50.1k | if (crv != CKR_OK) |
3367 | 14.6k | return crv; |
3368 | | |
3369 | 35.4k | if (context->hashInfo) { |
3370 | 35.4k | unsigned int digestLen; |
3371 | 35.4k | unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
3372 | | |
3373 | 35.4k | if (!pSignature) { |
3374 | 0 | outlen = context->maxLen; |
3375 | 0 | goto finish; |
3376 | 0 | } |
3377 | 35.4k | (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
3378 | 35.4k | if (SECSuccess != (context->update)(context->cipherInfo, pSignature, |
3379 | 35.4k | &outlen, maxoutlen, tmpbuf, digestLen)) |
3380 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3381 | | /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate. |
3382 | | * Keeping "too small" CK_RV intact is a standard violation, but allows |
3383 | | * application read EXACT signature length */ |
3384 | 35.4k | PORT_Memset(tmpbuf, 0, sizeof tmpbuf); |
3385 | 35.4k | } else { |
3386 | | /* must be block cipher MACing */ |
3387 | 0 | outlen = context->macSize; |
3388 | | /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/ |
3389 | 0 | if (!pSignature || maxoutlen < outlen) { |
3390 | 0 | if (pSignature) |
3391 | 0 | crv = CKR_BUFFER_TOO_SMALL; |
3392 | 0 | goto finish; |
3393 | 0 | } |
3394 | 0 | if (CKR_OK == (crv = sftk_MACFinal(context))) |
3395 | 0 | PORT_Memcpy(pSignature, context->macBuf, outlen); |
3396 | 0 | } |
3397 | | |
3398 | 35.4k | sftk_TerminateOp(session, SFTK_SIGN, context); |
3399 | 35.4k | finish: |
3400 | 35.4k | *pulSignatureLen = outlen; |
3401 | 35.4k | sftk_FreeSession(session); |
3402 | 35.4k | return crv; |
3403 | 35.4k | } |
3404 | | |
3405 | | /* NSC_Sign signs (encrypts with private key) data in a single part, |
3406 | | * where the signature is (will be) an appendix to the data, |
3407 | | * and plaintext cannot be recovered from the signature */ |
3408 | | CK_RV |
3409 | | NSC_Sign(CK_SESSION_HANDLE hSession, |
3410 | | CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, |
3411 | | CK_ULONG_PTR pulSignatureLen) |
3412 | 21.0k | { |
3413 | 21.0k | SFTKSession *session; |
3414 | 21.0k | SFTKSessionContext *context; |
3415 | 21.0k | CK_RV crv; |
3416 | | |
3417 | 21.0k | CHECK_FORK(); |
3418 | | |
3419 | | /* make sure we're legal */ |
3420 | 21.0k | crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session); |
3421 | 21.0k | if (crv != CKR_OK) |
3422 | 0 | return crv; |
3423 | | |
3424 | 21.0k | if (!pSignature) { |
3425 | | /* see also how C_SignUpdate implements this */ |
3426 | 0 | *pulSignatureLen = (!context->multi || context->hashInfo) |
3427 | 0 | ? context->maxLen |
3428 | 0 | : context->macSize; /* must be block cipher MACing */ |
3429 | 0 | goto finish; |
3430 | 0 | } |
3431 | | |
3432 | | /* multi part Signing are completely implemented by SignUpdate and |
3433 | | * sign Final */ |
3434 | 21.0k | if (context->multi) { |
3435 | | /* SignFinal can't follow failed SignUpdate */ |
3436 | 6.80k | if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen))) |
3437 | 6.80k | crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen); |
3438 | 14.2k | } else { |
3439 | | /* single-part PKC signature (e.g. CKM_ECDSA) */ |
3440 | 14.2k | unsigned int outlen; |
3441 | 14.2k | unsigned int maxoutlen = *pulSignatureLen; |
3442 | 14.2k | if (SECSuccess != (*context->update)(context->cipherInfo, pSignature, |
3443 | 14.2k | &outlen, maxoutlen, pData, ulDataLen)) |
3444 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3445 | 14.2k | *pulSignatureLen = (CK_ULONG)outlen; |
3446 | | /* "too small" here is certainly continuable */ |
3447 | 14.2k | if (crv != CKR_BUFFER_TOO_SMALL) |
3448 | 14.2k | sftk_TerminateOp(session, SFTK_SIGN, context); |
3449 | 14.2k | } /* single-part */ |
3450 | | |
3451 | 21.0k | finish: |
3452 | 21.0k | sftk_FreeSession(session); |
3453 | 21.0k | return crv; |
3454 | 21.0k | } |
3455 | | |
3456 | | /* |
3457 | | ************** Crypto Functions: Sign Recover ************************ |
3458 | | */ |
3459 | | /* NSC_SignRecoverInit initializes a signature operation, |
3460 | | * where the (digest) data can be recovered from the signature. |
3461 | | * E.g. encryption with the user's private key */ |
3462 | | CK_RV |
3463 | | NSC_SignRecoverInit(CK_SESSION_HANDLE hSession, |
3464 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3465 | 0 | { |
3466 | 0 | CHECK_FORK(); |
3467 | |
|
3468 | 0 | switch (pMechanism->mechanism) { |
3469 | 0 | case CKM_RSA_PKCS: |
3470 | 0 | case CKM_RSA_X_509: |
3471 | 0 | return NSC_SignInit(hSession, pMechanism, hKey); |
3472 | 0 | default: |
3473 | 0 | break; |
3474 | 0 | } |
3475 | 0 | return CKR_MECHANISM_INVALID; |
3476 | 0 | } |
3477 | | |
3478 | | /* NSC_SignRecover signs data in a single operation |
3479 | | * where the (digest) data can be recovered from the signature. |
3480 | | * E.g. encryption with the user's private key */ |
3481 | | CK_RV |
3482 | | NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
3483 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) |
3484 | 0 | { |
3485 | 0 | CHECK_FORK(); |
3486 | |
|
3487 | 0 | return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen); |
3488 | 0 | } |
3489 | | |
3490 | | /* |
3491 | | ************** Crypto Functions: verify ************************ |
3492 | | */ |
3493 | | |
3494 | | /* Handle RSA Signature formatting */ |
3495 | | static SECStatus |
3496 | | sftk_hashCheckSign(SFTKHashVerifyInfo *info, const unsigned char *sig, |
3497 | | unsigned int sigLen, const unsigned char *digest, |
3498 | | unsigned int digestLen) |
3499 | 4 | { |
3500 | 4 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
3501 | 4 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
3502 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3503 | 0 | return SECFailure; |
3504 | 0 | } |
3505 | | |
3506 | 4 | return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest, |
3507 | 4 | digestLen); |
3508 | 4 | } |
3509 | | |
3510 | | SECStatus |
3511 | | RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key, |
3512 | | const unsigned char *sig, unsigned int sigLen, |
3513 | | const unsigned char *digestData, unsigned int digestLen) |
3514 | 4 | { |
3515 | 4 | unsigned char *pkcs1DigestInfoData; |
3516 | 4 | SECItem pkcs1DigestInfo; |
3517 | 4 | SECItem digest; |
3518 | 4 | unsigned int bufferSize; |
3519 | 4 | SECStatus rv; |
3520 | | |
3521 | | /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */ |
3522 | 4 | bufferSize = key->u.rsa.modulus.len; |
3523 | 4 | pkcs1DigestInfoData = PORT_ZAlloc(bufferSize); |
3524 | 4 | if (!pkcs1DigestInfoData) { |
3525 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
3526 | 0 | return SECFailure; |
3527 | 0 | } |
3528 | | |
3529 | 4 | pkcs1DigestInfo.data = pkcs1DigestInfoData; |
3530 | 4 | pkcs1DigestInfo.len = bufferSize; |
3531 | | |
3532 | | /* decrypt the block */ |
3533 | 4 | rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data, |
3534 | 4 | &pkcs1DigestInfo.len, pkcs1DigestInfo.len, |
3535 | 4 | sig, sigLen); |
3536 | 4 | if (rv != SECSuccess) { |
3537 | 4 | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
3538 | 4 | } else { |
3539 | 0 | digest.data = (PRUint8 *)digestData; |
3540 | 0 | digest.len = digestLen; |
3541 | 0 | rv = _SGN_VerifyPKCS1DigestInfo( |
3542 | 0 | digestOid, &digest, &pkcs1DigestInfo, |
3543 | 0 | PR_FALSE /*XXX: unsafeAllowMissingParameters*/); |
3544 | 0 | } |
3545 | | |
3546 | 4 | PORT_ZFree(pkcs1DigestInfoData, bufferSize); |
3547 | 4 | return rv; |
3548 | 4 | } |
3549 | | |
3550 | | static SECStatus |
3551 | | sftk_RSACheckSign(NSSLOWKEYPublicKey *key, const unsigned char *sig, |
3552 | | unsigned int sigLen, const unsigned char *digest, |
3553 | | unsigned int digestLen) |
3554 | 673 | { |
3555 | 673 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3556 | 673 | if (key->keyType != NSSLOWKEYRSAKey) { |
3557 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3558 | 0 | return SECFailure; |
3559 | 0 | } |
3560 | | |
3561 | 673 | return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen); |
3562 | 673 | } |
3563 | | |
3564 | | static SECStatus |
3565 | | sftk_RSACheckSignRaw(NSSLOWKEYPublicKey *key, const unsigned char *sig, |
3566 | | unsigned int sigLen, const unsigned char *digest, |
3567 | | unsigned int digestLen) |
3568 | 0 | { |
3569 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3570 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
3571 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3572 | 0 | return SECFailure; |
3573 | 0 | } |
3574 | | |
3575 | 0 | return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen); |
3576 | 0 | } |
3577 | | |
3578 | | static SECStatus |
3579 | | sftk_RSACheckSignPSS(SFTKPSSVerifyInfo *info, const unsigned char *sig, |
3580 | | unsigned int sigLen, const unsigned char *digest, |
3581 | | unsigned int digestLen) |
3582 | 1.92k | { |
3583 | 1.92k | HASH_HashType hashAlg; |
3584 | 1.92k | HASH_HashType maskHashAlg; |
3585 | 1.92k | CK_RSA_PKCS_PSS_PARAMS *params = &info->params; |
3586 | | |
3587 | 1.92k | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
3588 | 1.92k | if (info->key->keyType != NSSLOWKEYRSAKey) { |
3589 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3590 | 0 | return SECFailure; |
3591 | 0 | } |
3592 | | |
3593 | 1.92k | hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg); |
3594 | 1.92k | maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf); |
3595 | | |
3596 | 1.92k | return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, |
3597 | 1.92k | params->sLen, sig, sigLen, digest, digestLen); |
3598 | 1.92k | } |
3599 | | |
3600 | | /* NSC_VerifyInit initializes a verification operation, |
3601 | | * where the signature is an appendix to the data, |
3602 | | * and plaintext cannot be recovered from the signature (e.g. DSA) */ |
3603 | | CK_RV |
3604 | | NSC_VerifyInit(CK_SESSION_HANDLE hSession, |
3605 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3606 | 3.98k | { |
3607 | 3.98k | SFTKSession *session; |
3608 | 3.98k | SFTKObject *key; |
3609 | 3.98k | SFTKSessionContext *context; |
3610 | 3.98k | CK_KEY_TYPE key_type; |
3611 | 3.98k | CK_RV crv = CKR_OK; |
3612 | 3.98k | NSSLOWKEYPublicKey *pubKey; |
3613 | 3.98k | SFTKHashVerifyInfo *info = NULL; |
3614 | 3.98k | SFTKPSSVerifyInfo *pinfo = NULL; |
3615 | | |
3616 | 3.98k | CHECK_FORK(); |
3617 | | |
3618 | | /* Block Cipher MACing Algorithms use a different Context init method..*/ |
3619 | 3.98k | crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY); |
3620 | 3.98k | if (crv != CKR_FUNCTION_NOT_SUPPORTED) |
3621 | 0 | return crv; |
3622 | | |
3623 | 3.98k | session = sftk_SessionFromHandle(hSession); |
3624 | 3.98k | if (session == NULL) |
3625 | 0 | return CKR_SESSION_HANDLE_INVALID; |
3626 | 3.98k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key, |
3627 | 3.98k | hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY); |
3628 | 3.98k | if (crv != CKR_OK) { |
3629 | 0 | sftk_FreeSession(session); |
3630 | 0 | return crv; |
3631 | 0 | } |
3632 | | |
3633 | 3.98k | context->multi = PR_FALSE; |
3634 | | |
3635 | 3.98k | #define INIT_RSA_VFY_MECH(mmm) \ |
3636 | 3.98k | case CKM_##mmm##_RSA_PKCS: \ |
3637 | 4 | context->multi = PR_TRUE; \ |
3638 | 4 | crv = sftk_doSub##mmm(context); \ |
3639 | 4 | if (crv != CKR_OK) \ |
3640 | 4 | break; \ |
3641 | 4 | context->verify = (SFTKVerify)sftk_hashCheckSign; \ |
3642 | 4 | info = PORT_New(SFTKHashVerifyInfo); \ |
3643 | 4 | if (info == NULL) { \ |
3644 | 0 | crv = CKR_HOST_MEMORY; \ |
3645 | 0 | break; \ |
3646 | 0 | } \ |
3647 | 4 | info->hashOid = SEC_OID_##mmm; \ |
3648 | 4 | goto finish_rsa; |
3649 | | |
3650 | 3.98k | switch (pMechanism->mechanism) { |
3651 | 0 | INIT_RSA_VFY_MECH(MD5) |
3652 | 0 | INIT_RSA_VFY_MECH(MD2) |
3653 | 0 | INIT_RSA_VFY_MECH(SHA1) |
3654 | 0 | INIT_RSA_VFY_MECH(SHA224) |
3655 | 8 | INIT_RSA_VFY_MECH(SHA256) |
3656 | 0 | INIT_RSA_VFY_MECH(SHA384) |
3657 | 0 | INIT_RSA_VFY_MECH(SHA512) |
3658 | | |
3659 | 673 | case CKM_RSA_PKCS: |
3660 | 673 | context->verify = (SFTKVerify)sftk_RSACheckSign; |
3661 | 673 | goto finish_rsa; |
3662 | 0 | case CKM_RSA_X_509: |
3663 | 0 | context->verify = (SFTKVerify)sftk_RSACheckSignRaw; |
3664 | 677 | finish_rsa: |
3665 | 677 | if (key_type != CKK_RSA) { |
3666 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3667 | 0 | break; |
3668 | 0 | } |
3669 | 677 | context->rsa = PR_TRUE; |
3670 | 677 | pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
3671 | 677 | if (pubKey == NULL) { |
3672 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3673 | 0 | break; |
3674 | 0 | } |
3675 | 677 | if (info) { |
3676 | 4 | info->key = pubKey; |
3677 | 4 | context->cipherInfo = info; |
3678 | 4 | context->destroy = sftk_Space; |
3679 | 673 | } else { |
3680 | 673 | context->cipherInfo = pubKey; |
3681 | 673 | context->destroy = sftk_Null; |
3682 | 673 | } |
3683 | 677 | break; |
3684 | | |
3685 | 0 | INIT_RSA_PSS_SIG_MECH(SHA1) |
3686 | 0 | INIT_RSA_PSS_SIG_MECH(SHA224) |
3687 | 0 | INIT_RSA_PSS_SIG_MECH(SHA256) |
3688 | 0 | INIT_RSA_PSS_SIG_MECH(SHA384) |
3689 | 0 | INIT_RSA_PSS_SIG_MECH(SHA512) |
3690 | 1.92k | case CKM_RSA_PKCS_PSS: |
3691 | 1.92k | finish_rsa_pss: |
3692 | 1.92k | if (key_type != CKK_RSA) { |
3693 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3694 | 0 | break; |
3695 | 0 | } |
3696 | 1.92k | context->rsa = PR_TRUE; |
3697 | 1.92k | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
3698 | 1.92k | !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { |
3699 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3700 | 0 | break; |
3701 | 0 | } |
3702 | 1.92k | pinfo = PORT_New(SFTKPSSVerifyInfo); |
3703 | 1.92k | if (pinfo == NULL) { |
3704 | 0 | crv = CKR_HOST_MEMORY; |
3705 | 0 | break; |
3706 | 0 | } |
3707 | 1.92k | pinfo->size = sizeof(SFTKPSSVerifyInfo); |
3708 | 1.92k | pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter; |
3709 | 1.92k | pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv); |
3710 | 1.92k | if (pinfo->key == NULL) { |
3711 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3712 | 0 | break; |
3713 | 0 | } |
3714 | 1.92k | context->cipherInfo = pinfo; |
3715 | 1.92k | context->destroy = (SFTKDestroy)sftk_ZSpace; |
3716 | 1.92k | context->verify = (SFTKVerify)sftk_RSACheckSignPSS; |
3717 | 1.92k | break; |
3718 | | |
3719 | 0 | INIT_DSA_SIG_MECH(SHA1) |
3720 | 0 | INIT_DSA_SIG_MECH(SHA224) |
3721 | 0 | INIT_DSA_SIG_MECH(SHA256) |
3722 | 0 | INIT_DSA_SIG_MECH(SHA384) |
3723 | 0 | INIT_DSA_SIG_MECH(SHA512) |
3724 | 10 | case CKM_DSA: |
3725 | 10 | finish_dsa: |
3726 | 10 | if (key_type != CKK_DSA) { |
3727 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3728 | 0 | break; |
3729 | 0 | } |
3730 | 10 | pubKey = sftk_GetPubKey(key, CKK_DSA, &crv); |
3731 | 10 | if (pubKey == NULL) { |
3732 | 0 | break; |
3733 | 0 | } |
3734 | 10 | context->cipherInfo = pubKey; |
3735 | 10 | context->verify = (SFTKVerify)nsc_DSA_Verify_Stub; |
3736 | 10 | context->destroy = sftk_Null; |
3737 | 10 | break; |
3738 | | |
3739 | 0 | INIT_ECDSA_SIG_MECH(SHA1) |
3740 | 0 | INIT_ECDSA_SIG_MECH(SHA224) |
3741 | 1 | INIT_ECDSA_SIG_MECH(SHA256) |
3742 | 1 | INIT_ECDSA_SIG_MECH(SHA384) |
3743 | 2 | INIT_ECDSA_SIG_MECH(SHA512) |
3744 | 1.37k | case CKM_ECDSA: |
3745 | 1.37k | finish_ecdsa: |
3746 | 1.37k | if (key_type != CKK_EC) { |
3747 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3748 | 0 | break; |
3749 | 0 | } |
3750 | 1.37k | pubKey = sftk_GetPubKey(key, CKK_EC, &crv); |
3751 | 1.37k | if (pubKey == NULL) { |
3752 | 0 | crv = CKR_HOST_MEMORY; |
3753 | 0 | break; |
3754 | 0 | } |
3755 | 1.37k | context->cipherInfo = pubKey; |
3756 | 1.37k | context->verify = (SFTKVerify)nsc_ECDSAVerifyStub; |
3757 | 1.37k | context->destroy = sftk_Null; |
3758 | 1.37k | break; |
3759 | | |
3760 | 0 | INIT_HMAC_MECH(MD2) |
3761 | 0 | INIT_HMAC_MECH(MD5) |
3762 | 0 | INIT_HMAC_MECH(SHA1) |
3763 | 0 | INIT_HMAC_MECH(SHA224) |
3764 | 0 | INIT_HMAC_MECH(SHA256) |
3765 | 0 | INIT_HMAC_MECH(SHA384) |
3766 | 0 | INIT_HMAC_MECH(SHA512) |
3767 | 0 | INIT_HMAC_MECH(SHA3_224) |
3768 | 0 | INIT_HMAC_MECH(SHA3_256) |
3769 | 0 | INIT_HMAC_MECH(SHA3_384) |
3770 | 0 | INIT_HMAC_MECH(SHA3_512) |
3771 | | |
3772 | 0 | case CKM_EDDSA: |
3773 | 0 | if (key_type != CKK_EC_EDWARDS) { |
3774 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3775 | 0 | break; |
3776 | 0 | } |
3777 | 0 | pubKey = sftk_GetPubKey(key, CKK_EC_EDWARDS, &crv); |
3778 | 0 | if (pubKey == NULL) { |
3779 | 0 | crv = CKR_HOST_MEMORY; |
3780 | 0 | break; |
3781 | 0 | } |
3782 | | |
3783 | 0 | if (pMechanism->pParameter) { |
3784 | 0 | crv = CKR_FUNCTION_NOT_SUPPORTED; |
3785 | 0 | break; |
3786 | 0 | } |
3787 | | |
3788 | 0 | context->cipherInfo = pubKey; |
3789 | 0 | context->verify = (SFTKVerify)nsc_EDDSAVerifyStub; |
3790 | 0 | context->destroy = sftk_Null; |
3791 | 0 | break; |
3792 | | |
3793 | 0 | case CKM_SSL3_MD5_MAC: |
3794 | 0 | PORT_Assert(pMechanism->pParameter); |
3795 | 0 | if (!pMechanism->pParameter) { |
3796 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3797 | 0 | break; |
3798 | 0 | } |
3799 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, |
3800 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3801 | 0 | break; |
3802 | 0 | case CKM_SSL3_SHA1_MAC: |
3803 | 0 | PORT_Assert(pMechanism->pParameter); |
3804 | 0 | if (!pMechanism->pParameter) { |
3805 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3806 | 0 | break; |
3807 | 0 | } |
3808 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, |
3809 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3810 | 0 | break; |
3811 | 0 | case CKM_TLS_PRF_GENERAL: |
3812 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); |
3813 | 0 | break; |
3814 | 0 | case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
3815 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); |
3816 | 0 | break; |
3817 | | |
3818 | 0 | default: |
3819 | 0 | crv = CKR_MECHANISM_INVALID; |
3820 | 0 | break; |
3821 | 3.98k | } |
3822 | | |
3823 | 3.98k | if (crv != CKR_OK) { |
3824 | 0 | if (info) |
3825 | 0 | PORT_Free(info); |
3826 | 0 | if (pinfo) |
3827 | 0 | PORT_ZFree(pinfo, pinfo->size); |
3828 | 0 | sftk_FreeContext(context); |
3829 | 0 | sftk_FreeSession(session); |
3830 | 0 | return crv; |
3831 | 0 | } |
3832 | 3.98k | sftk_SetContextByType(session, SFTK_VERIFY, context); |
3833 | 3.98k | sftk_FreeSession(session); |
3834 | 3.98k | return CKR_OK; |
3835 | 3.98k | } |
3836 | | |
3837 | | /* NSC_Verify verifies a signature in a single-part operation, |
3838 | | * where the signature is an appendix to the data, |
3839 | | * and plaintext cannot be recovered from the signature */ |
3840 | | CK_RV |
3841 | | NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
3842 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
3843 | 3.98k | { |
3844 | 3.98k | SFTKSession *session; |
3845 | 3.98k | SFTKSessionContext *context; |
3846 | 3.98k | CK_RV crv; |
3847 | | |
3848 | 3.98k | CHECK_FORK(); |
3849 | | |
3850 | | /* make sure we're legal */ |
3851 | 3.98k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); |
3852 | 3.98k | if (crv != CKR_OK) |
3853 | 0 | return crv; |
3854 | | |
3855 | | /* multi part Verifying are completely implemented by VerifyUpdate and |
3856 | | * VerifyFinal */ |
3857 | 3.98k | if (context->multi) { |
3858 | | /* VerifyFinal can't follow failed VerifyUpdate */ |
3859 | 7 | if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen))) |
3860 | 7 | crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen); |
3861 | 3.97k | } else { |
3862 | 3.97k | if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature, |
3863 | 3.97k | ulSignatureLen, pData, ulDataLen)) |
3864 | 3.97k | crv = sftk_MapCryptError(PORT_GetError()); |
3865 | | |
3866 | 3.97k | sftk_TerminateOp(session, SFTK_VERIFY, context); |
3867 | 3.97k | } |
3868 | 3.98k | sftk_FreeSession(session); |
3869 | 3.98k | return crv; |
3870 | 3.98k | } |
3871 | | |
3872 | | /* NSC_VerifyUpdate continues a multiple-part verification operation, |
3873 | | * where the signature is an appendix to the data, |
3874 | | * and plaintext cannot be recovered from the signature |
3875 | | * |
3876 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3877 | | */ |
3878 | | CK_RV |
3879 | | NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3880 | | CK_ULONG ulPartLen) |
3881 | 7 | { |
3882 | 7 | CHECK_FORK(); |
3883 | 7 | return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY); |
3884 | 7 | } |
3885 | | |
3886 | | /* NSC_VerifyFinal finishes a multiple-part verification operation, |
3887 | | * checking the signature. */ |
3888 | | CK_RV |
3889 | | NSC_VerifyFinal(CK_SESSION_HANDLE hSession, |
3890 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
3891 | 7 | { |
3892 | 7 | SFTKSession *session; |
3893 | 7 | SFTKSessionContext *context; |
3894 | 7 | CK_RV crv; |
3895 | | |
3896 | 7 | CHECK_FORK(); |
3897 | | |
3898 | 7 | if (!pSignature) |
3899 | 0 | return CKR_ARGUMENTS_BAD; |
3900 | | |
3901 | | /* make sure we're legal */ |
3902 | 7 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); |
3903 | 7 | if (crv != CKR_OK) |
3904 | 0 | return crv; |
3905 | | |
3906 | 7 | if (context->hashInfo) { |
3907 | 7 | unsigned int digestLen; |
3908 | 7 | unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
3909 | | |
3910 | 7 | (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
3911 | 7 | if (SECSuccess != (context->verify)(context->cipherInfo, pSignature, |
3912 | 7 | ulSignatureLen, tmpbuf, digestLen)) |
3913 | 7 | crv = sftk_MapCryptError(PORT_GetError()); |
3914 | 7 | PORT_Memset(tmpbuf, 0, sizeof tmpbuf); |
3915 | 7 | } else if (ulSignatureLen != context->macSize) { |
3916 | | /* must be block cipher MACing */ |
3917 | 0 | crv = CKR_SIGNATURE_LEN_RANGE; |
3918 | 0 | } else if (CKR_OK == (crv = sftk_MACFinal(context))) { |
3919 | 0 | if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen)) |
3920 | 0 | crv = CKR_SIGNATURE_INVALID; |
3921 | 0 | } |
3922 | | |
3923 | 7 | sftk_TerminateOp(session, SFTK_VERIFY, context); |
3924 | 7 | sftk_FreeSession(session); |
3925 | 7 | return crv; |
3926 | 7 | } |
3927 | | |
3928 | | /* |
3929 | | ************** Crypto Functions: Verify Recover ************************ |
3930 | | */ |
3931 | | static SECStatus |
3932 | | sftk_RSACheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data, |
3933 | | unsigned int *dataLen, unsigned int maxDataLen, |
3934 | | const unsigned char *sig, unsigned int sigLen) |
3935 | 804 | { |
3936 | 804 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3937 | 804 | if (key->keyType != NSSLOWKEYRSAKey) { |
3938 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3939 | 0 | return SECFailure; |
3940 | 0 | } |
3941 | | |
3942 | 804 | return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen, |
3943 | 804 | sig, sigLen); |
3944 | 804 | } |
3945 | | |
3946 | | static SECStatus |
3947 | | sftk_RSACheckSignRecoverRaw(NSSLOWKEYPublicKey *key, unsigned char *data, |
3948 | | unsigned int *dataLen, unsigned int maxDataLen, |
3949 | | const unsigned char *sig, unsigned int sigLen) |
3950 | 0 | { |
3951 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3952 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
3953 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3954 | 0 | return SECFailure; |
3955 | 0 | } |
3956 | | |
3957 | 0 | return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen, |
3958 | 0 | sig, sigLen); |
3959 | 0 | } |
3960 | | |
3961 | | /* NSC_VerifyRecoverInit initializes a signature verification operation, |
3962 | | * where the data is recovered from the signature. |
3963 | | * E.g. Decryption with the user's public key */ |
3964 | | CK_RV |
3965 | | NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, |
3966 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3967 | 804 | { |
3968 | 804 | SFTKSession *session; |
3969 | 804 | SFTKObject *key; |
3970 | 804 | SFTKSessionContext *context; |
3971 | 804 | CK_KEY_TYPE key_type; |
3972 | 804 | CK_RV crv = CKR_OK; |
3973 | 804 | NSSLOWKEYPublicKey *pubKey; |
3974 | | |
3975 | 804 | CHECK_FORK(); |
3976 | | |
3977 | 804 | session = sftk_SessionFromHandle(hSession); |
3978 | 804 | if (session == NULL) |
3979 | 0 | return CKR_SESSION_HANDLE_INVALID; |
3980 | 804 | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER, |
3981 | 804 | &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER); |
3982 | 804 | if (crv != CKR_OK) { |
3983 | 0 | sftk_FreeSession(session); |
3984 | 0 | return crv; |
3985 | 0 | } |
3986 | | |
3987 | 804 | context->multi = PR_TRUE; |
3988 | | |
3989 | 804 | switch (pMechanism->mechanism) { |
3990 | 804 | case CKM_RSA_PKCS: |
3991 | 804 | case CKM_RSA_X_509: |
3992 | 804 | if (key_type != CKK_RSA) { |
3993 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3994 | 0 | break; |
3995 | 0 | } |
3996 | 804 | context->multi = PR_FALSE; |
3997 | 804 | context->rsa = PR_TRUE; |
3998 | 804 | pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
3999 | 804 | if (pubKey == NULL) { |
4000 | 0 | break; |
4001 | 0 | } |
4002 | 804 | context->cipherInfo = pubKey; |
4003 | 804 | context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509 |
4004 | 804 | ? sftk_RSACheckSignRecoverRaw |
4005 | 804 | : sftk_RSACheckSignRecover); |
4006 | 804 | context->destroy = sftk_Null; |
4007 | 804 | break; |
4008 | 0 | default: |
4009 | 0 | crv = CKR_MECHANISM_INVALID; |
4010 | 0 | break; |
4011 | 804 | } |
4012 | | |
4013 | 804 | if (crv != CKR_OK) { |
4014 | 0 | PORT_Free(context); |
4015 | 0 | sftk_FreeSession(session); |
4016 | 0 | return crv; |
4017 | 0 | } |
4018 | 804 | sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context); |
4019 | 804 | sftk_FreeSession(session); |
4020 | 804 | return CKR_OK; |
4021 | 804 | } |
4022 | | |
4023 | | /* NSC_VerifyRecover verifies a signature in a single-part operation, |
4024 | | * where the data is recovered from the signature. |
4025 | | * E.g. Decryption with the user's public key */ |
4026 | | CK_RV |
4027 | | NSC_VerifyRecover(CK_SESSION_HANDLE hSession, |
4028 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, |
4029 | | CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
4030 | 804 | { |
4031 | 804 | SFTKSession *session; |
4032 | 804 | SFTKSessionContext *context; |
4033 | 804 | unsigned int outlen; |
4034 | 804 | unsigned int maxoutlen = *pulDataLen; |
4035 | 804 | CK_RV crv; |
4036 | 804 | SECStatus rv; |
4037 | | |
4038 | 804 | CHECK_FORK(); |
4039 | | |
4040 | | /* make sure we're legal */ |
4041 | 804 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER, |
4042 | 804 | PR_FALSE, &session); |
4043 | 804 | if (crv != CKR_OK) |
4044 | 0 | return crv; |
4045 | 804 | if (pData == NULL) { |
4046 | | /* to return the actual size, we need to do the decrypt, just return |
4047 | | * the max size, which is the size of the input signature. */ |
4048 | 0 | *pulDataLen = ulSignatureLen; |
4049 | 0 | rv = SECSuccess; |
4050 | 0 | goto finish; |
4051 | 0 | } |
4052 | | |
4053 | 804 | rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
4054 | 804 | pSignature, ulSignatureLen); |
4055 | 804 | *pulDataLen = (CK_ULONG)outlen; |
4056 | | |
4057 | 804 | sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context); |
4058 | 804 | finish: |
4059 | 804 | sftk_FreeSession(session); |
4060 | 804 | return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError()); |
4061 | 804 | } |
4062 | | |
4063 | | /* |
4064 | | **************************** Random Functions: ************************ |
4065 | | */ |
4066 | | |
4067 | | /* NSC_SeedRandom mixes additional seed material into the token's random number |
4068 | | * generator. */ |
4069 | | CK_RV |
4070 | | NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, |
4071 | | CK_ULONG ulSeedLen) |
4072 | 0 | { |
4073 | 0 | SECStatus rv; |
4074 | |
|
4075 | 0 | CHECK_FORK(); |
4076 | |
|
4077 | 0 | rv = RNG_RandomUpdate(pSeed, ulSeedLen); |
4078 | 0 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
4079 | 0 | } |
4080 | | |
4081 | | /* NSC_GenerateRandom generates random data. */ |
4082 | | CK_RV |
4083 | | NSC_GenerateRandom(CK_SESSION_HANDLE hSession, |
4084 | | CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) |
4085 | 81.2k | { |
4086 | 81.2k | SECStatus rv; |
4087 | | |
4088 | 81.2k | CHECK_FORK(); |
4089 | | |
4090 | 81.2k | rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen); |
4091 | | /* |
4092 | | * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't |
4093 | | * seeded with enough entropy. |
4094 | | */ |
4095 | 81.2k | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
4096 | 81.2k | } |
4097 | | |
4098 | | /* |
4099 | | **************************** Key Functions: ************************ |
4100 | | */ |
4101 | | |
4102 | | /* |
4103 | | * generate a password based encryption key. This code uses |
4104 | | * PKCS5 to do the work. |
4105 | | */ |
4106 | | static CK_RV |
4107 | | nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, |
4108 | | void *buf, CK_ULONG *key_length, PRBool faulty3DES) |
4109 | 0 | { |
4110 | 0 | SECItem *pbe_key = NULL, iv, pwitem; |
4111 | 0 | CK_PBE_PARAMS *pbe_params = NULL; |
4112 | 0 | CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; |
4113 | |
|
4114 | 0 | *key_length = 0; |
4115 | 0 | iv.data = NULL; |
4116 | 0 | iv.len = 0; |
4117 | |
|
4118 | 0 | if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
4119 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) { |
4120 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4121 | 0 | } |
4122 | 0 | pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; |
4123 | 0 | pwitem.data = (unsigned char *)pbkd2_params->pPassword; |
4124 | | /* was this a typo in the PKCS #11 spec? */ |
4125 | 0 | pwitem.len = *pbkd2_params->ulPasswordLen; |
4126 | 0 | } else { |
4127 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4128 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4129 | 0 | } |
4130 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4131 | 0 | pwitem.data = (unsigned char *)pbe_params->pPassword; |
4132 | 0 | pwitem.len = pbe_params->ulPasswordLen; |
4133 | 0 | } |
4134 | 0 | pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); |
4135 | 0 | if (pbe_key == NULL) { |
4136 | 0 | return CKR_HOST_MEMORY; |
4137 | 0 | } |
4138 | | |
4139 | 0 | PORT_Memcpy(buf, pbe_key->data, pbe_key->len); |
4140 | 0 | *key_length = pbe_key->len; |
4141 | 0 | SECITEM_ZfreeItem(pbe_key, PR_TRUE); |
4142 | 0 | pbe_key = NULL; |
4143 | |
|
4144 | 0 | if (iv.data) { |
4145 | 0 | if (pbe_params && pbe_params->pInitVector != NULL) { |
4146 | 0 | PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); |
4147 | 0 | } |
4148 | 0 | PORT_Free(iv.data); |
4149 | 0 | } |
4150 | |
|
4151 | 0 | return CKR_OK; |
4152 | 0 | } |
4153 | | |
4154 | | /* |
4155 | | * this is coded for "full" support. These selections will be limitted to |
4156 | | * the official subset by freebl. |
4157 | | */ |
4158 | | static unsigned int |
4159 | | sftk_GetSubPrimeFromPrime(unsigned int primeBits) |
4160 | 0 | { |
4161 | 0 | if (primeBits <= 1024) { |
4162 | 0 | return 160; |
4163 | 0 | } else if (primeBits <= 2048) { |
4164 | 0 | return 224; |
4165 | 0 | } else if (primeBits <= 3072) { |
4166 | 0 | return 256; |
4167 | 0 | } else if (primeBits <= 7680) { |
4168 | 0 | return 384; |
4169 | 0 | } else { |
4170 | 0 | return 512; |
4171 | 0 | } |
4172 | 0 | } |
4173 | | |
4174 | | static CK_RV |
4175 | | nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) |
4176 | 0 | { |
4177 | 0 | SFTKAttribute *attribute; |
4178 | 0 | CK_ULONG counter; |
4179 | 0 | unsigned int seedBits = 0; |
4180 | 0 | unsigned int subprimeBits = 0; |
4181 | 0 | unsigned int primeBits; |
4182 | 0 | unsigned int j = 8; /* default to 1024 bits */ |
4183 | 0 | CK_RV crv = CKR_OK; |
4184 | 0 | PQGParams *params = NULL; |
4185 | 0 | PQGVerify *vfy = NULL; |
4186 | 0 | SECStatus rv; |
4187 | |
|
4188 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME_BITS); |
4189 | 0 | if (attribute == NULL) { |
4190 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME); |
4191 | 0 | if (attribute == NULL) { |
4192 | 0 | return CKR_TEMPLATE_INCOMPLETE; |
4193 | 0 | } else { |
4194 | 0 | primeBits = attribute->attrib.ulValueLen; |
4195 | 0 | sftk_FreeAttribute(attribute); |
4196 | 0 | } |
4197 | 0 | } else { |
4198 | 0 | primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4199 | 0 | sftk_FreeAttribute(attribute); |
4200 | 0 | } |
4201 | 0 | if (primeBits < 1024) { |
4202 | 0 | j = PQG_PBITS_TO_INDEX(primeBits); |
4203 | 0 | if (j == (unsigned int)-1) { |
4204 | 0 | return CKR_ATTRIBUTE_VALUE_INVALID; |
4205 | 0 | } |
4206 | 0 | } |
4207 | | |
4208 | 0 | attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS); |
4209 | 0 | if (attribute != NULL) { |
4210 | 0 | seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4211 | 0 | sftk_FreeAttribute(attribute); |
4212 | 0 | } |
4213 | |
|
4214 | 0 | attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS); |
4215 | 0 | if (attribute != NULL) { |
4216 | 0 | subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4217 | 0 | sftk_FreeAttribute(attribute); |
4218 | 0 | } |
4219 | | |
4220 | | /* if P and Q are supplied, we want to generate a new G */ |
4221 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME); |
4222 | 0 | if (attribute != NULL) { |
4223 | 0 | PLArenaPool *arena; |
4224 | |
|
4225 | 0 | sftk_FreeAttribute(attribute); |
4226 | 0 | arena = PORT_NewArena(1024); |
4227 | 0 | if (arena == NULL) { |
4228 | 0 | crv = CKR_HOST_MEMORY; |
4229 | 0 | goto loser; |
4230 | 0 | } |
4231 | 0 | params = PORT_ArenaAlloc(arena, sizeof(*params)); |
4232 | 0 | if (params == NULL) { |
4233 | 0 | crv = CKR_HOST_MEMORY; |
4234 | 0 | goto loser; |
4235 | 0 | } |
4236 | 0 | params->arena = arena; |
4237 | 0 | crv = sftk_Attribute2SSecItem(arena, ¶ms->prime, key, CKA_PRIME); |
4238 | 0 | if (crv != CKR_OK) { |
4239 | 0 | goto loser; |
4240 | 0 | } |
4241 | 0 | crv = sftk_Attribute2SSecItem(arena, ¶ms->subPrime, |
4242 | 0 | key, CKA_SUBPRIME); |
4243 | 0 | if (crv != CKR_OK) { |
4244 | 0 | goto loser; |
4245 | 0 | } |
4246 | | |
4247 | 0 | arena = PORT_NewArena(1024); |
4248 | 0 | if (arena == NULL) { |
4249 | 0 | crv = CKR_HOST_MEMORY; |
4250 | 0 | goto loser; |
4251 | 0 | } |
4252 | 0 | vfy = PORT_ArenaAlloc(arena, sizeof(*vfy)); |
4253 | 0 | if (vfy == NULL) { |
4254 | 0 | crv = CKR_HOST_MEMORY; |
4255 | 0 | goto loser; |
4256 | 0 | } |
4257 | 0 | vfy->arena = arena; |
4258 | 0 | crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED); |
4259 | 0 | if (crv != CKR_OK) { |
4260 | 0 | goto loser; |
4261 | 0 | } |
4262 | 0 | crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H); |
4263 | 0 | if (crv != CKR_OK) { |
4264 | 0 | goto loser; |
4265 | 0 | } |
4266 | 0 | sftk_DeleteAttributeType(key, CKA_PRIME); |
4267 | 0 | sftk_DeleteAttributeType(key, CKA_SUBPRIME); |
4268 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED); |
4269 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_H); |
4270 | 0 | } |
4271 | | |
4272 | 0 | sftk_DeleteAttributeType(key, CKA_PRIME_BITS); |
4273 | 0 | sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS); |
4274 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS); |
4275 | | |
4276 | | /* use the old PQG interface if we have old input data */ |
4277 | 0 | if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) { |
4278 | 0 | if (seedBits == 0) { |
4279 | 0 | rv = PQG_ParamGen(j, ¶ms, &vfy); |
4280 | 0 | } else { |
4281 | 0 | rv = PQG_ParamGenSeedLen(j, seedBits / 8, ¶ms, &vfy); |
4282 | 0 | } |
4283 | 0 | } else { |
4284 | 0 | if (subprimeBits == 0) { |
4285 | 0 | subprimeBits = sftk_GetSubPrimeFromPrime(primeBits); |
4286 | 0 | } |
4287 | 0 | if (seedBits == 0) { |
4288 | 0 | seedBits = primeBits; |
4289 | 0 | } |
4290 | 0 | rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, ¶ms, &vfy); |
4291 | 0 | } |
4292 | |
|
4293 | 0 | if (rv != SECSuccess) { |
4294 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
4295 | 0 | sftk_fatalError = PR_TRUE; |
4296 | 0 | } |
4297 | 0 | return sftk_MapCryptError(PORT_GetError()); |
4298 | 0 | } |
4299 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME, |
4300 | 0 | params->prime.data, params->prime.len); |
4301 | 0 | if (crv != CKR_OK) |
4302 | 0 | goto loser; |
4303 | 0 | crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
4304 | 0 | params->subPrime.data, params->subPrime.len); |
4305 | 0 | if (crv != CKR_OK) |
4306 | 0 | goto loser; |
4307 | 0 | crv = sftk_AddAttributeType(key, CKA_BASE, |
4308 | 0 | params->base.data, params->base.len); |
4309 | 0 | if (crv != CKR_OK) |
4310 | 0 | goto loser; |
4311 | 0 | counter = vfy->counter; |
4312 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER, |
4313 | 0 | &counter, sizeof(counter)); |
4314 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED, |
4315 | 0 | vfy->seed.data, vfy->seed.len); |
4316 | 0 | if (crv != CKR_OK) |
4317 | 0 | goto loser; |
4318 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H, |
4319 | 0 | vfy->h.data, vfy->h.len); |
4320 | 0 | if (crv != CKR_OK) |
4321 | 0 | goto loser; |
4322 | | |
4323 | 0 | loser: |
4324 | 0 | if (params) { |
4325 | 0 | PQG_DestroyParams(params); |
4326 | 0 | } |
4327 | |
|
4328 | 0 | if (vfy) { |
4329 | 0 | PQG_DestroyVerify(vfy); |
4330 | 0 | } |
4331 | 0 | return crv; |
4332 | 0 | } |
4333 | | |
4334 | | static CK_RV |
4335 | | nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, |
4336 | | CK_ULONG *key_length) |
4337 | 289 | { |
4338 | 289 | CK_RV crv = CKR_OK; |
4339 | | |
4340 | 289 | switch (mechanism) { |
4341 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4342 | 0 | case CKM_RC2_KEY_GEN: |
4343 | 0 | *key_type = CKK_RC2; |
4344 | 0 | if (*key_length == 0) |
4345 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4346 | 0 | break; |
4347 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
4348 | | #if NSS_SOFTOKEN_DOES_RC5 |
4349 | | case CKM_RC5_KEY_GEN: |
4350 | | *key_type = CKK_RC5; |
4351 | | if (*key_length == 0) |
4352 | | crv = CKR_TEMPLATE_INCOMPLETE; |
4353 | | break; |
4354 | | #endif |
4355 | 0 | case CKM_RC4_KEY_GEN: |
4356 | 0 | *key_type = CKK_RC4; |
4357 | 0 | if (*key_length == 0) |
4358 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4359 | 0 | break; |
4360 | 2 | case CKM_GENERIC_SECRET_KEY_GEN: |
4361 | 2 | *key_type = CKK_GENERIC_SECRET; |
4362 | 2 | if (*key_length == 0) |
4363 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4364 | 2 | break; |
4365 | 0 | case CKM_CDMF_KEY_GEN: |
4366 | 0 | *key_type = CKK_CDMF; |
4367 | 0 | *key_length = 8; |
4368 | 0 | break; |
4369 | 0 | case CKM_DES_KEY_GEN: |
4370 | 0 | *key_type = CKK_DES; |
4371 | 0 | *key_length = 8; |
4372 | 0 | break; |
4373 | 0 | case CKM_DES2_KEY_GEN: |
4374 | 0 | *key_type = CKK_DES2; |
4375 | 0 | *key_length = 16; |
4376 | 0 | break; |
4377 | 285 | case CKM_DES3_KEY_GEN: |
4378 | 285 | *key_type = CKK_DES3; |
4379 | 285 | *key_length = 24; |
4380 | 285 | break; |
4381 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
4382 | 0 | case CKM_SEED_KEY_GEN: |
4383 | 0 | *key_type = CKK_SEED; |
4384 | 0 | *key_length = 16; |
4385 | 0 | break; |
4386 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
4387 | 0 | case CKM_CAMELLIA_KEY_GEN: |
4388 | 0 | *key_type = CKK_CAMELLIA; |
4389 | 0 | if (*key_length == 0) |
4390 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4391 | 0 | break; |
4392 | 2 | case CKM_AES_KEY_GEN: |
4393 | 2 | *key_type = CKK_AES; |
4394 | 2 | if (*key_length == 0) |
4395 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4396 | 2 | break; |
4397 | 0 | case CKM_NSS_CHACHA20_KEY_GEN: |
4398 | 0 | *key_type = CKK_NSS_CHACHA20; |
4399 | 0 | *key_length = 32; |
4400 | 0 | break; |
4401 | 0 | case CKM_CHACHA20_KEY_GEN: |
4402 | 0 | *key_type = CKK_CHACHA20; |
4403 | 0 | *key_length = 32; |
4404 | 0 | break; |
4405 | 0 | case CKM_HKDF_KEY_GEN: |
4406 | 0 | *key_type = CKK_HKDF; |
4407 | 0 | if (*key_length == 0) |
4408 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4409 | 0 | break; |
4410 | 0 | default: |
4411 | 0 | PORT_Assert(0); |
4412 | 0 | crv = CKR_MECHANISM_INVALID; |
4413 | 0 | break; |
4414 | 289 | } |
4415 | | |
4416 | 289 | return crv; |
4417 | 289 | } |
4418 | | |
4419 | | CK_RV |
4420 | | nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) |
4421 | 0 | { |
4422 | 0 | SECItem salt; |
4423 | 0 | CK_PBE_PARAMS *pbe_params = NULL; |
4424 | 0 | NSSPKCS5PBEParameter *params; |
4425 | 0 | PLArenaPool *arena = NULL; |
4426 | 0 | SECStatus rv; |
4427 | |
|
4428 | 0 | *pbe = NULL; |
4429 | |
|
4430 | 0 | arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); |
4431 | 0 | if (arena == NULL) { |
4432 | 0 | return CKR_HOST_MEMORY; |
4433 | 0 | } |
4434 | | |
4435 | 0 | params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena, |
4436 | 0 | sizeof(NSSPKCS5PBEParameter)); |
4437 | 0 | if (params == NULL) { |
4438 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4439 | 0 | return CKR_HOST_MEMORY; |
4440 | 0 | } |
4441 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4442 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4443 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4444 | 0 | } |
4445 | | |
4446 | 0 | params->poolp = arena; |
4447 | 0 | params->ivLen = 0; |
4448 | 0 | params->pbeType = NSSPKCS5_PKCS12_V2; |
4449 | 0 | params->hashType = HASH_AlgSHA1; |
4450 | 0 | params->encAlg = SEC_OID_SHA1; /* any invalid value */ |
4451 | 0 | params->is2KeyDES = PR_FALSE; |
4452 | 0 | params->keyID = pbeBitGenIntegrityKey; |
4453 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4454 | 0 | params->iter = pbe_params->ulIteration; |
4455 | |
|
4456 | 0 | salt.data = (unsigned char *)pbe_params->pSalt; |
4457 | 0 | salt.len = (unsigned int)pbe_params->ulSaltLen; |
4458 | 0 | salt.type = siBuffer; |
4459 | 0 | rv = SECITEM_CopyItem(arena, ¶ms->salt, &salt); |
4460 | 0 | if (rv != SECSuccess) { |
4461 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4462 | 0 | return CKR_HOST_MEMORY; |
4463 | 0 | } |
4464 | 0 | switch (pMechanism->mechanism) { |
4465 | 0 | case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN: |
4466 | 0 | case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
4467 | 0 | params->hashType = HASH_AlgSHA1; |
4468 | 0 | params->keyLen = 20; |
4469 | 0 | break; |
4470 | 0 | case CKM_NSS_PBE_MD5_HMAC_KEY_GEN: |
4471 | 0 | params->hashType = HASH_AlgMD5; |
4472 | 0 | params->keyLen = 16; |
4473 | 0 | break; |
4474 | 0 | case CKM_NSS_PBE_MD2_HMAC_KEY_GEN: |
4475 | 0 | params->hashType = HASH_AlgMD2; |
4476 | 0 | params->keyLen = 16; |
4477 | 0 | break; |
4478 | 0 | case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: |
4479 | 0 | params->hashType = HASH_AlgSHA224; |
4480 | 0 | params->keyLen = 28; |
4481 | 0 | break; |
4482 | 0 | case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: |
4483 | 0 | params->hashType = HASH_AlgSHA256; |
4484 | 0 | params->keyLen = 32; |
4485 | 0 | break; |
4486 | 0 | case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: |
4487 | 0 | params->hashType = HASH_AlgSHA384; |
4488 | 0 | params->keyLen = 48; |
4489 | 0 | break; |
4490 | 0 | case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: |
4491 | 0 | params->hashType = HASH_AlgSHA512; |
4492 | 0 | params->keyLen = 64; |
4493 | 0 | break; |
4494 | 0 | default: |
4495 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4496 | 0 | return CKR_MECHANISM_INVALID; |
4497 | 0 | } |
4498 | 0 | *pbe = params; |
4499 | 0 | return CKR_OK; |
4500 | 0 | } |
4501 | | |
4502 | | /* maybe this should be table driven? */ |
4503 | | static CK_RV |
4504 | | nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, |
4505 | | CK_KEY_TYPE *key_type, CK_ULONG *key_length) |
4506 | 0 | { |
4507 | 0 | CK_RV crv = CKR_OK; |
4508 | 0 | SECOidData *oid; |
4509 | 0 | CK_PBE_PARAMS *pbe_params = NULL; |
4510 | 0 | NSSPKCS5PBEParameter *params = NULL; |
4511 | 0 | HASH_HashType hashType = HASH_AlgSHA1; |
4512 | 0 | CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; |
4513 | 0 | SECItem salt; |
4514 | 0 | CK_ULONG iteration = 0; |
4515 | |
|
4516 | 0 | *pbe = NULL; |
4517 | |
|
4518 | 0 | oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); |
4519 | 0 | if (oid == NULL) { |
4520 | 0 | return CKR_MECHANISM_INVALID; |
4521 | 0 | } |
4522 | | |
4523 | 0 | if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
4524 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) { |
4525 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4526 | 0 | } |
4527 | 0 | pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; |
4528 | 0 | switch (pbkd2_params->prf) { |
4529 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA1: |
4530 | 0 | hashType = HASH_AlgSHA1; |
4531 | 0 | break; |
4532 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA224: |
4533 | 0 | hashType = HASH_AlgSHA224; |
4534 | 0 | break; |
4535 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA256: |
4536 | 0 | hashType = HASH_AlgSHA256; |
4537 | 0 | break; |
4538 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA384: |
4539 | 0 | hashType = HASH_AlgSHA384; |
4540 | 0 | break; |
4541 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA512: |
4542 | 0 | hashType = HASH_AlgSHA512; |
4543 | 0 | break; |
4544 | 0 | default: |
4545 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4546 | 0 | } |
4547 | 0 | if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) { |
4548 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4549 | 0 | } |
4550 | 0 | salt.data = (unsigned char *)pbkd2_params->pSaltSourceData; |
4551 | 0 | salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen; |
4552 | 0 | iteration = pbkd2_params->iterations; |
4553 | 0 | } else { |
4554 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4555 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4556 | 0 | } |
4557 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4558 | 0 | salt.data = (unsigned char *)pbe_params->pSalt; |
4559 | 0 | salt.len = (unsigned int)pbe_params->ulSaltLen; |
4560 | 0 | iteration = pbe_params->ulIteration; |
4561 | 0 | } |
4562 | 0 | params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration); |
4563 | 0 | if (params == NULL) { |
4564 | 0 | return CKR_MECHANISM_INVALID; |
4565 | 0 | } |
4566 | | |
4567 | 0 | switch (params->encAlg) { |
4568 | 0 | case SEC_OID_DES_CBC: |
4569 | 0 | *key_type = CKK_DES; |
4570 | 0 | *key_length = params->keyLen; |
4571 | 0 | break; |
4572 | 0 | case SEC_OID_DES_EDE3_CBC: |
4573 | 0 | *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; |
4574 | 0 | *key_length = params->keyLen; |
4575 | 0 | break; |
4576 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4577 | 0 | case SEC_OID_RC2_CBC: |
4578 | 0 | *key_type = CKK_RC2; |
4579 | 0 | *key_length = params->keyLen; |
4580 | 0 | break; |
4581 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
4582 | 0 | case SEC_OID_RC4: |
4583 | 0 | *key_type = CKK_RC4; |
4584 | 0 | *key_length = params->keyLen; |
4585 | 0 | break; |
4586 | 0 | case SEC_OID_PKCS5_PBKDF2: |
4587 | | /* key type must already be set */ |
4588 | 0 | if (*key_type == CKK_INVALID_KEY_TYPE) { |
4589 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4590 | 0 | break; |
4591 | 0 | } |
4592 | | /* PBKDF2 needs to calculate the key length from the other parameters |
4593 | | */ |
4594 | 0 | if (*key_length == 0) { |
4595 | 0 | *key_length = sftk_MapKeySize(*key_type); |
4596 | 0 | } |
4597 | 0 | if (*key_length == 0) { |
4598 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4599 | 0 | break; |
4600 | 0 | } |
4601 | 0 | params->keyLen = *key_length; |
4602 | 0 | break; |
4603 | 0 | default: |
4604 | 0 | crv = CKR_MECHANISM_INVALID; |
4605 | 0 | break; |
4606 | 0 | } |
4607 | 0 | if (crv == CKR_OK) { |
4608 | 0 | *pbe = params; |
4609 | 0 | } else { |
4610 | 0 | nsspkcs5_DestroyPBEParameter(params); |
4611 | 0 | } |
4612 | 0 | return crv; |
4613 | 0 | } |
4614 | | |
4615 | | /* NSC_GenerateKey generates a secret key, creating a new key object. */ |
4616 | | CK_RV |
4617 | | NSC_GenerateKey(CK_SESSION_HANDLE hSession, |
4618 | | CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, |
4619 | | CK_OBJECT_HANDLE_PTR phKey) |
4620 | 5.52k | { |
4621 | 5.52k | SFTKObject *key; |
4622 | 5.52k | SFTKSession *session; |
4623 | 5.52k | PRBool checkWeak = PR_FALSE; |
4624 | 5.52k | CK_ULONG key_length = 0; |
4625 | 5.52k | CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE; |
4626 | 5.52k | CK_OBJECT_CLASS objclass = CKO_SECRET_KEY; |
4627 | 5.52k | CK_RV crv = CKR_OK; |
4628 | 5.52k | CK_BBOOL cktrue = CK_TRUE; |
4629 | 5.52k | NSSPKCS5PBEParameter *pbe_param = NULL; |
4630 | 5.52k | int i; |
4631 | 5.52k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
4632 | 5.52k | unsigned char buf[MAX_KEY_LEN]; |
4633 | 5.52k | enum { nsc_pbe, |
4634 | 5.52k | nsc_ssl, |
4635 | 5.52k | nsc_bulk, |
4636 | 5.52k | nsc_param, |
4637 | 5.52k | nsc_jpake } key_gen_type; |
4638 | 5.52k | SSL3RSAPreMasterSecret *rsa_pms; |
4639 | 5.52k | CK_VERSION *version; |
4640 | | /* in very old versions of NSS, there were implementation errors with key |
4641 | | * generation methods. We want to beable to read these, but not |
4642 | | * produce them any more. The affected algorithm was 3DES. |
4643 | | */ |
4644 | 5.52k | PRBool faultyPBE3DES = PR_FALSE; |
4645 | 5.52k | HASH_HashType hashType = HASH_AlgNULL; |
4646 | | |
4647 | 5.52k | CHECK_FORK(); |
4648 | | |
4649 | 5.52k | if (!slot) { |
4650 | 0 | return CKR_SESSION_HANDLE_INVALID; |
4651 | 0 | } |
4652 | | /* |
4653 | | * now lets create an object to hang the attributes off of |
4654 | | */ |
4655 | 5.52k | key = sftk_NewObject(slot); /* fill in the handle later */ |
4656 | 5.52k | if (key == NULL) { |
4657 | 0 | return CKR_HOST_MEMORY; |
4658 | 0 | } |
4659 | | |
4660 | | /* |
4661 | | * load the template values into the object |
4662 | | */ |
4663 | 16.5k | for (i = 0; i < (int)ulCount; i++) { |
4664 | 11.0k | if (pTemplate[i].type == CKA_VALUE_LEN) { |
4665 | 4 | key_length = *(CK_ULONG *)pTemplate[i].pValue; |
4666 | 4 | continue; |
4667 | 4 | } |
4668 | | /* some algorithms need keytype specified */ |
4669 | 11.0k | if (pTemplate[i].type == CKA_KEY_TYPE) { |
4670 | 0 | key_type = *(CK_ULONG *)pTemplate[i].pValue; |
4671 | 0 | continue; |
4672 | 0 | } |
4673 | | |
4674 | 11.0k | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
4675 | 11.0k | if (crv != CKR_OK) { |
4676 | 0 | break; |
4677 | 0 | } |
4678 | 11.0k | } |
4679 | 5.52k | if (crv != CKR_OK) { |
4680 | 0 | goto loser; |
4681 | 0 | } |
4682 | | |
4683 | | /* make sure we don't have any class, key_type, or value fields */ |
4684 | 5.52k | sftk_DeleteAttributeType(key, CKA_CLASS); |
4685 | 5.52k | sftk_DeleteAttributeType(key, CKA_KEY_TYPE); |
4686 | 5.52k | sftk_DeleteAttributeType(key, CKA_VALUE); |
4687 | | |
4688 | | /* Now Set up the parameters to generate the key (based on mechanism) */ |
4689 | 5.52k | key_gen_type = nsc_bulk; /* bulk key by default */ |
4690 | 5.52k | switch (pMechanism->mechanism) { |
4691 | 0 | case CKM_CDMF_KEY_GEN: |
4692 | 0 | case CKM_DES_KEY_GEN: |
4693 | 0 | case CKM_DES2_KEY_GEN: |
4694 | 285 | case CKM_DES3_KEY_GEN: |
4695 | 285 | checkWeak = PR_TRUE; |
4696 | | /* fall through */ |
4697 | 285 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4698 | 285 | case CKM_RC2_KEY_GEN: |
4699 | 285 | #endif |
4700 | 285 | case CKM_RC4_KEY_GEN: |
4701 | 287 | case CKM_GENERIC_SECRET_KEY_GEN: |
4702 | 287 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
4703 | 287 | case CKM_SEED_KEY_GEN: |
4704 | 287 | #endif |
4705 | 287 | case CKM_CAMELLIA_KEY_GEN: |
4706 | 289 | case CKM_AES_KEY_GEN: |
4707 | 289 | case CKM_NSS_CHACHA20_KEY_GEN: |
4708 | 289 | case CKM_CHACHA20_KEY_GEN: |
4709 | | #if NSS_SOFTOKEN_DOES_RC5 |
4710 | | case CKM_RC5_KEY_GEN: |
4711 | | #endif |
4712 | 289 | crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length); |
4713 | 289 | break; |
4714 | 5.23k | case CKM_SSL3_PRE_MASTER_KEY_GEN: |
4715 | 5.23k | key_type = CKK_GENERIC_SECRET; |
4716 | 5.23k | key_length = 48; |
4717 | 5.23k | key_gen_type = nsc_ssl; |
4718 | 5.23k | break; |
4719 | 0 | case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
4720 | 0 | case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN: |
4721 | 0 | case CKM_NSS_PBE_MD5_HMAC_KEY_GEN: |
4722 | 0 | case CKM_NSS_PBE_MD2_HMAC_KEY_GEN: |
4723 | 0 | case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: |
4724 | 0 | case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: |
4725 | 0 | case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: |
4726 | 0 | case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: |
4727 | 0 | key_gen_type = nsc_pbe; |
4728 | 0 | key_type = CKK_GENERIC_SECRET; |
4729 | 0 | crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); |
4730 | 0 | break; |
4731 | 0 | case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC: |
4732 | 0 | faultyPBE3DES = PR_TRUE; |
4733 | | /* fall through */ |
4734 | 0 | case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC: |
4735 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4736 | 0 | case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC: |
4737 | 0 | case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC: |
4738 | 0 | case CKM_PBE_SHA1_RC2_128_CBC: |
4739 | 0 | case CKM_PBE_SHA1_RC2_40_CBC: |
4740 | 0 | #endif |
4741 | 0 | case CKM_NSS_PBE_SHA1_DES_CBC: |
4742 | 0 | case CKM_NSS_PBE_SHA1_40_BIT_RC4: |
4743 | 0 | case CKM_NSS_PBE_SHA1_128_BIT_RC4: |
4744 | 0 | case CKM_PBE_SHA1_DES3_EDE_CBC: |
4745 | 0 | case CKM_PBE_SHA1_DES2_EDE_CBC: |
4746 | 0 | case CKM_PBE_SHA1_RC4_128: |
4747 | 0 | case CKM_PBE_SHA1_RC4_40: |
4748 | 0 | case CKM_PBE_MD5_DES_CBC: |
4749 | 0 | case CKM_PBE_MD2_DES_CBC: |
4750 | 0 | case CKM_PKCS5_PBKD2: |
4751 | 0 | key_gen_type = nsc_pbe; |
4752 | 0 | crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length); |
4753 | 0 | break; |
4754 | 0 | case CKM_DSA_PARAMETER_GEN: |
4755 | 0 | key_gen_type = nsc_param; |
4756 | 0 | key_type = CKK_DSA; |
4757 | 0 | objclass = CKO_DOMAIN_PARAMETERS; |
4758 | 0 | crv = CKR_OK; |
4759 | 0 | break; |
4760 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA1: |
4761 | 0 | hashType = HASH_AlgSHA1; |
4762 | 0 | goto jpake1; |
4763 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA256: |
4764 | 0 | hashType = HASH_AlgSHA256; |
4765 | 0 | goto jpake1; |
4766 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA384: |
4767 | 0 | hashType = HASH_AlgSHA384; |
4768 | 0 | goto jpake1; |
4769 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA512: |
4770 | 0 | hashType = HASH_AlgSHA512; |
4771 | 0 | goto jpake1; |
4772 | 0 | jpake1: |
4773 | 0 | key_gen_type = nsc_jpake; |
4774 | 0 | key_type = CKK_NSS_JPAKE_ROUND1; |
4775 | 0 | objclass = CKO_PRIVATE_KEY; |
4776 | 0 | if (pMechanism->pParameter == NULL || |
4777 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) { |
4778 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4779 | 0 | break; |
4780 | 0 | } |
4781 | 0 | if (sftk_isTrue(key, CKA_TOKEN)) { |
4782 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
4783 | 0 | break; |
4784 | 0 | } |
4785 | 0 | crv = CKR_OK; |
4786 | 0 | break; |
4787 | 0 | default: |
4788 | 0 | crv = CKR_MECHANISM_INVALID; |
4789 | 0 | break; |
4790 | 5.52k | } |
4791 | | |
4792 | | /* make sure we aren't going to overflow the buffer */ |
4793 | 5.52k | if (sizeof(buf) < key_length) { |
4794 | | /* someone is getting pretty optimistic about how big their key can |
4795 | | * be... */ |
4796 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
4797 | 0 | } |
4798 | | |
4799 | 5.52k | if (crv != CKR_OK) { |
4800 | 0 | if (pbe_param) { |
4801 | 0 | nsspkcs5_DestroyPBEParameter(pbe_param); |
4802 | 0 | } |
4803 | 0 | goto loser; |
4804 | 0 | } |
4805 | | |
4806 | | /* if there was no error, |
4807 | | * key_type *MUST* be set in the switch statement above */ |
4808 | 5.52k | PORT_Assert(key_type != CKK_INVALID_KEY_TYPE); |
4809 | | |
4810 | | /* |
4811 | | * now to the actual key gen. |
4812 | | */ |
4813 | 5.52k | switch (key_gen_type) { |
4814 | 0 | case nsc_pbe: |
4815 | 0 | crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, |
4816 | 0 | faultyPBE3DES); |
4817 | 0 | nsspkcs5_DestroyPBEParameter(pbe_param); |
4818 | 0 | break; |
4819 | 5.23k | case nsc_ssl: |
4820 | 5.23k | rsa_pms = (SSL3RSAPreMasterSecret *)buf; |
4821 | 5.23k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) { |
4822 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4823 | 0 | goto loser; |
4824 | 0 | } |
4825 | 5.23k | version = (CK_VERSION *)pMechanism->pParameter; |
4826 | 5.23k | rsa_pms->client_version[0] = version->major; |
4827 | 5.23k | rsa_pms->client_version[1] = version->minor; |
4828 | 5.23k | crv = |
4829 | 5.23k | NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random)); |
4830 | 5.23k | break; |
4831 | 289 | case nsc_bulk: |
4832 | | /* get the key, check for weak keys and repeat if found */ |
4833 | 289 | do { |
4834 | 289 | crv = NSC_GenerateRandom(0, buf, key_length); |
4835 | 289 | } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type)); |
4836 | 289 | break; |
4837 | 0 | case nsc_param: |
4838 | | /* generate parameters */ |
4839 | 0 | *buf = 0; |
4840 | 0 | crv = nsc_parameter_gen(key_type, key); |
4841 | 0 | break; |
4842 | 0 | case nsc_jpake: |
4843 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) { |
4844 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4845 | 0 | goto loser; |
4846 | 0 | } |
4847 | 0 | crv = jpake_Round1(hashType, |
4848 | 0 | (CK_NSS_JPAKERound1Params *)pMechanism->pParameter, |
4849 | 0 | key); |
4850 | 0 | break; |
4851 | 5.52k | } |
4852 | | |
4853 | 5.52k | if (crv != CKR_OK) { |
4854 | 0 | goto loser; |
4855 | 0 | } |
4856 | | |
4857 | | /* Add the class, key_type, and value */ |
4858 | 5.52k | crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS)); |
4859 | 5.52k | if (crv != CKR_OK) { |
4860 | 0 | goto loser; |
4861 | 0 | } |
4862 | 5.52k | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)); |
4863 | 5.52k | if (crv != CKR_OK) { |
4864 | 0 | goto loser; |
4865 | 0 | } |
4866 | 5.52k | if (key_length != 0) { |
4867 | 5.52k | crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); |
4868 | 5.52k | if (crv != CKR_OK) { |
4869 | 0 | goto loser; |
4870 | 0 | } |
4871 | 5.52k | } |
4872 | | |
4873 | | /* get the session */ |
4874 | 5.52k | session = sftk_SessionFromHandle(hSession); |
4875 | 5.52k | if (session == NULL) { |
4876 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
4877 | 0 | goto loser; |
4878 | 0 | } |
4879 | | |
4880 | | /* |
4881 | | * handle the base object stuff |
4882 | | */ |
4883 | 5.52k | crv = sftk_handleObject(key, session); |
4884 | 5.52k | sftk_FreeSession(session); |
4885 | 5.52k | if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) { |
4886 | 0 | crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL)); |
4887 | 0 | } |
4888 | 5.52k | if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) { |
4889 | 0 | crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL)); |
4890 | 0 | } |
4891 | 5.52k | if (crv == CKR_OK) { |
4892 | 5.52k | *phKey = key->handle; |
4893 | 5.52k | } |
4894 | 5.52k | loser: |
4895 | 5.52k | PORT_Memset(buf, 0, sizeof buf); |
4896 | 5.52k | sftk_FreeObject(key); |
4897 | 5.52k | return crv; |
4898 | 5.52k | } |
4899 | | |
4900 | 40.3k | #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ |
4901 | 0 | #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ |
4902 | | |
4903 | | /* |
4904 | | * FIPS 140-2 pairwise consistency check utilized to validate key pair. |
4905 | | * |
4906 | | * This function returns |
4907 | | * CKR_OK if pairwise consistency check passed |
4908 | | * CKR_GENERAL_ERROR if pairwise consistency check failed |
4909 | | * other error codes if paiswise consistency check could not be |
4910 | | * performed, for example, CKR_HOST_MEMORY. |
4911 | | */ |
4912 | | static CK_RV |
4913 | | sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot, |
4914 | | SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) |
4915 | 40.3k | { |
4916 | | /* |
4917 | | * Key type Mechanism type |
4918 | | * -------------------------------- |
4919 | | * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS |
4920 | | * others => CKM_INVALID_MECHANISM |
4921 | | * |
4922 | | * For sign/verify: CKK_RSA => CKM_RSA_PKCS |
4923 | | * CKK_DSA => CKM_DSA |
4924 | | * CKK_EC => CKM_ECDSA |
4925 | | * others => CKM_INVALID_MECHANISM |
4926 | | * |
4927 | | * None of these mechanisms has a parameter. |
4928 | | * |
4929 | | * For derive CKK_DH => CKM_DH_PKCS_DERIVE |
4930 | | * CKK_EC => CKM_ECDH1_DERIVE |
4931 | | * others => CKM_INVALID_MECHANISM |
4932 | | * |
4933 | | * The parameters for these mechanisms is the public key. |
4934 | | */ |
4935 | 40.3k | CK_MECHANISM mech = { 0, NULL, 0 }; |
4936 | | |
4937 | 40.3k | CK_ULONG modulusLen = 0; |
4938 | 40.3k | CK_ULONG subPrimeLen = 0; |
4939 | 40.3k | PRBool isEncryptable = PR_FALSE; |
4940 | 40.3k | PRBool canSignVerify = PR_FALSE; |
4941 | 40.3k | PRBool isDerivable = PR_FALSE; |
4942 | 40.3k | CK_RV crv; |
4943 | | |
4944 | | /* Variables used for Encrypt/Decrypt functions. */ |
4945 | 40.3k | unsigned char *known_message = (unsigned char *)"Known Crypto Message"; |
4946 | 40.3k | unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; |
4947 | 40.3k | CK_ULONG bytes_decrypted; |
4948 | 40.3k | unsigned char *ciphertext; |
4949 | 40.3k | unsigned char *text_compared; |
4950 | 40.3k | CK_ULONG bytes_encrypted; |
4951 | 40.3k | CK_ULONG bytes_compared; |
4952 | 40.3k | CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH; |
4953 | | |
4954 | | /* Variables used for Signature/Verification functions. */ |
4955 | | /* Must be at least 256 bits for DSA2 digest */ |
4956 | 40.3k | unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!"; |
4957 | 40.3k | unsigned char *signature; |
4958 | 40.3k | CK_ULONG signature_length; |
4959 | | |
4960 | 40.3k | if (keyType == CKK_RSA) { |
4961 | 0 | SFTKAttribute *attribute; |
4962 | | |
4963 | | /* Get modulus length of private key. */ |
4964 | 0 | attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); |
4965 | 0 | if (attribute == NULL) { |
4966 | 0 | return CKR_DEVICE_ERROR; |
4967 | 0 | } |
4968 | 0 | modulusLen = attribute->attrib.ulValueLen; |
4969 | 0 | if (*(unsigned char *)attribute->attrib.pValue == 0) { |
4970 | 0 | modulusLen--; |
4971 | 0 | } |
4972 | 0 | sftk_FreeAttribute(attribute); |
4973 | 40.3k | } else if (keyType == CKK_DSA) { |
4974 | 0 | SFTKAttribute *attribute; |
4975 | | |
4976 | | /* Get subprime length of private key. */ |
4977 | 0 | attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME); |
4978 | 0 | if (attribute == NULL) { |
4979 | 0 | return CKR_DEVICE_ERROR; |
4980 | 0 | } |
4981 | 0 | subPrimeLen = attribute->attrib.ulValueLen; |
4982 | 0 | if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) { |
4983 | 0 | subPrimeLen--; |
4984 | 0 | } |
4985 | 0 | sftk_FreeAttribute(attribute); |
4986 | 0 | } |
4987 | | |
4988 | | /**************************************************/ |
4989 | | /* Pairwise Consistency Check of Encrypt/Decrypt. */ |
4990 | | /**************************************************/ |
4991 | | |
4992 | 40.3k | isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); |
4993 | | |
4994 | | /* |
4995 | | * If the decryption attribute is set, attempt to encrypt |
4996 | | * with the public key and decrypt with the private key. |
4997 | | */ |
4998 | 40.3k | if (isEncryptable) { |
4999 | 0 | if (keyType != CKK_RSA) { |
5000 | 0 | return CKR_DEVICE_ERROR; |
5001 | 0 | } |
5002 | 0 | bytes_encrypted = modulusLen; |
5003 | 0 | mech.mechanism = CKM_RSA_PKCS; |
5004 | | |
5005 | | /* Allocate space for ciphertext. */ |
5006 | 0 | ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted); |
5007 | 0 | if (ciphertext == NULL) { |
5008 | 0 | return CKR_HOST_MEMORY; |
5009 | 0 | } |
5010 | | |
5011 | | /* Prepare for encryption using the public key. */ |
5012 | 0 | crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); |
5013 | 0 | if (crv != CKR_OK) { |
5014 | 0 | PORT_Free(ciphertext); |
5015 | 0 | return crv; |
5016 | 0 | } |
5017 | | |
5018 | | /* Encrypt using the public key. */ |
5019 | 0 | crv = NSC_Encrypt(hSession, |
5020 | 0 | known_message, |
5021 | 0 | PAIRWISE_MESSAGE_LENGTH, |
5022 | 0 | ciphertext, |
5023 | 0 | &bytes_encrypted); |
5024 | 0 | if (crv != CKR_OK) { |
5025 | 0 | PORT_Free(ciphertext); |
5026 | 0 | return crv; |
5027 | 0 | } |
5028 | | |
5029 | | /* Always use the smaller of these two values . . . */ |
5030 | 0 | bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); |
5031 | | |
5032 | | /* |
5033 | | * If there was a failure, the plaintext |
5034 | | * goes at the end, therefore . . . |
5035 | | */ |
5036 | 0 | text_compared = ciphertext + bytes_encrypted - bytes_compared; |
5037 | | |
5038 | | /* |
5039 | | * Check to ensure that ciphertext does |
5040 | | * NOT EQUAL known input message text |
5041 | | * per FIPS PUB 140-2 directive. |
5042 | | */ |
5043 | 0 | if (PORT_Memcmp(text_compared, known_message, |
5044 | 0 | bytes_compared) == 0) { |
5045 | | /* Set error to Invalid PRIVATE Key. */ |
5046 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
5047 | 0 | PORT_Free(ciphertext); |
5048 | 0 | return CKR_GENERAL_ERROR; |
5049 | 0 | } |
5050 | | |
5051 | | /* Prepare for decryption using the private key. */ |
5052 | 0 | crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); |
5053 | 0 | if (crv != CKR_OK) { |
5054 | 0 | PORT_Free(ciphertext); |
5055 | 0 | return crv; |
5056 | 0 | } |
5057 | | |
5058 | 0 | memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); |
5059 | | |
5060 | | /* |
5061 | | * Initialize bytes decrypted to be the |
5062 | | * expected PAIRWISE_MESSAGE_LENGTH. |
5063 | | */ |
5064 | 0 | bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; |
5065 | | |
5066 | | /* |
5067 | | * Decrypt using the private key. |
5068 | | * NOTE: No need to reset the |
5069 | | * value of bytes_encrypted. |
5070 | | */ |
5071 | 0 | crv = NSC_Decrypt(hSession, |
5072 | 0 | ciphertext, |
5073 | 0 | bytes_encrypted, |
5074 | 0 | plaintext, |
5075 | 0 | &bytes_decrypted); |
5076 | | |
5077 | | /* Finished with ciphertext; free it. */ |
5078 | 0 | PORT_Free(ciphertext); |
5079 | |
|
5080 | 0 | if (crv != CKR_OK) { |
5081 | 0 | return crv; |
5082 | 0 | } |
5083 | | |
5084 | | /* |
5085 | | * Check to ensure that the output plaintext |
5086 | | * does EQUAL known input message text. |
5087 | | */ |
5088 | 0 | if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || |
5089 | 0 | (PORT_Memcmp(plaintext, known_message, |
5090 | 0 | PAIRWISE_MESSAGE_LENGTH) != 0)) { |
5091 | | /* Set error to Bad PUBLIC Key. */ |
5092 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
5093 | 0 | return CKR_GENERAL_ERROR; |
5094 | 0 | } |
5095 | 0 | } |
5096 | | |
5097 | | /**********************************************/ |
5098 | | /* Pairwise Consistency Check of Sign/Verify. */ |
5099 | | /**********************************************/ |
5100 | | |
5101 | 40.3k | canSignVerify = sftk_isTrue(privateKey, CKA_SIGN); |
5102 | | /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the |
5103 | | * actual curve to determine if we can do sign/verify. */ |
5104 | 40.3k | if (canSignVerify && keyType == CKK_EC) { |
5105 | 0 | NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv); |
5106 | 0 | if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) { |
5107 | 0 | canSignVerify = PR_FALSE; |
5108 | 0 | } |
5109 | 0 | } |
5110 | | |
5111 | 40.3k | if (canSignVerify) { |
5112 | | /* Determine length of signature. */ |
5113 | 0 | switch (keyType) { |
5114 | 0 | case CKK_RSA: |
5115 | 0 | signature_length = modulusLen; |
5116 | 0 | mech.mechanism = CKM_RSA_PKCS; |
5117 | 0 | break; |
5118 | 0 | case CKK_DSA: |
5119 | 0 | signature_length = DSA_MAX_SIGNATURE_LEN; |
5120 | 0 | pairwise_digest_length = subPrimeLen; |
5121 | 0 | mech.mechanism = CKM_DSA; |
5122 | 0 | break; |
5123 | 0 | case CKK_EC: |
5124 | 0 | signature_length = MAX_ECKEY_LEN * 2; |
5125 | 0 | mech.mechanism = CKM_ECDSA; |
5126 | 0 | break; |
5127 | 0 | case CKK_EC_EDWARDS: |
5128 | 0 | signature_length = ED25519_SIGN_LEN; |
5129 | 0 | mech.mechanism = CKM_EDDSA; |
5130 | 0 | break; |
5131 | 0 | default: |
5132 | 0 | return CKR_DEVICE_ERROR; |
5133 | 0 | } |
5134 | | |
5135 | | /* Allocate space for signature data. */ |
5136 | 0 | signature = (unsigned char *)PORT_ZAlloc(signature_length); |
5137 | 0 | if (signature == NULL) { |
5138 | 0 | return CKR_HOST_MEMORY; |
5139 | 0 | } |
5140 | | |
5141 | | /* Sign the known hash using the private key. */ |
5142 | 0 | crv = NSC_SignInit(hSession, &mech, privateKey->handle); |
5143 | 0 | if (crv != CKR_OK) { |
5144 | 0 | PORT_Free(signature); |
5145 | 0 | return crv; |
5146 | 0 | } |
5147 | | |
5148 | 0 | crv = NSC_Sign(hSession, |
5149 | 0 | known_digest, |
5150 | 0 | pairwise_digest_length, |
5151 | 0 | signature, |
5152 | 0 | &signature_length); |
5153 | 0 | if (crv != CKR_OK) { |
5154 | 0 | PORT_Free(signature); |
5155 | 0 | return crv; |
5156 | 0 | } |
5157 | | |
5158 | | /* detect trivial signing transforms */ |
5159 | 0 | if ((signature_length >= pairwise_digest_length) && |
5160 | 0 | (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) { |
5161 | 0 | PORT_Free(signature); |
5162 | 0 | return CKR_DEVICE_ERROR; |
5163 | 0 | } |
5164 | | |
5165 | | /* Verify the known hash using the public key. */ |
5166 | 0 | crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); |
5167 | 0 | if (crv != CKR_OK) { |
5168 | 0 | PORT_Free(signature); |
5169 | 0 | return crv; |
5170 | 0 | } |
5171 | | |
5172 | 0 | crv = NSC_Verify(hSession, |
5173 | 0 | known_digest, |
5174 | 0 | pairwise_digest_length, |
5175 | 0 | signature, |
5176 | 0 | signature_length); |
5177 | | |
5178 | | /* Free signature data. */ |
5179 | 0 | PORT_Free(signature); |
5180 | |
|
5181 | 0 | if ((crv == CKR_SIGNATURE_LEN_RANGE) || |
5182 | 0 | (crv == CKR_SIGNATURE_INVALID)) { |
5183 | 0 | return CKR_GENERAL_ERROR; |
5184 | 0 | } |
5185 | 0 | if (crv != CKR_OK) { |
5186 | 0 | return crv; |
5187 | 0 | } |
5188 | 0 | } |
5189 | | |
5190 | | /**********************************************/ |
5191 | | /* Pairwise Consistency Check for Derivation */ |
5192 | | /**********************************************/ |
5193 | | |
5194 | 40.3k | isDerivable = sftk_isTrue(privateKey, CKA_DERIVE); |
5195 | | |
5196 | 40.3k | if (isDerivable) { |
5197 | 40.3k | SFTKAttribute *pubAttribute = NULL; |
5198 | 40.3k | CK_OBJECT_HANDLE newKey; |
5199 | 40.3k | PRBool isFIPS = sftk_isFIPS(slot->slotID); |
5200 | 40.3k | CK_RV crv2; |
5201 | 40.3k | CK_OBJECT_CLASS secret = CKO_SECRET_KEY; |
5202 | 40.3k | CK_KEY_TYPE generic = CKK_GENERIC_SECRET; |
5203 | 40.3k | CK_ULONG keyLen = 128; |
5204 | 40.3k | CK_BBOOL ckTrue = CK_TRUE; |
5205 | 40.3k | CK_ATTRIBUTE template[] = { |
5206 | 40.3k | { CKA_CLASS, &secret, sizeof(secret) }, |
5207 | 40.3k | { CKA_KEY_TYPE, &generic, sizeof(generic) }, |
5208 | 40.3k | { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, |
5209 | 40.3k | { CKA_DERIVE, &ckTrue, sizeof(ckTrue) } |
5210 | 40.3k | }; |
5211 | 40.3k | CK_ULONG templateCount = PR_ARRAY_SIZE(template); |
5212 | 40.3k | CK_ECDH1_DERIVE_PARAMS ecParams; |
5213 | | |
5214 | 40.3k | crv = CKR_OK; /*paranoia, already get's set before we drop to the end */ |
5215 | | /* FIPS 140-2 requires we verify that the resulting key is a valid key. |
5216 | | * The easiest way to do this is to do a derive operation, which checks |
5217 | | * the validity of the key */ |
5218 | | |
5219 | 40.3k | switch (keyType) { |
5220 | 5.53k | case CKK_DH: |
5221 | 5.53k | mech.mechanism = CKM_DH_PKCS_DERIVE; |
5222 | 5.53k | pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE); |
5223 | 5.53k | if (pubAttribute == NULL) { |
5224 | 0 | return CKR_DEVICE_ERROR; |
5225 | 0 | } |
5226 | 5.53k | mech.pParameter = pubAttribute->attrib.pValue; |
5227 | 5.53k | mech.ulParameterLen = pubAttribute->attrib.ulValueLen; |
5228 | 5.53k | break; |
5229 | 34.8k | case CKK_EC: |
5230 | 34.8k | mech.mechanism = CKM_ECDH1_DERIVE; |
5231 | 34.8k | pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT); |
5232 | 34.8k | if (pubAttribute == NULL) { |
5233 | 0 | return CKR_DEVICE_ERROR; |
5234 | 0 | } |
5235 | 34.8k | ecParams.kdf = CKD_NULL; |
5236 | 34.8k | ecParams.ulSharedDataLen = 0; |
5237 | 34.8k | ecParams.pSharedData = NULL; |
5238 | 34.8k | ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen; |
5239 | 34.8k | ecParams.pPublicData = pubAttribute->attrib.pValue; |
5240 | 34.8k | mech.pParameter = &ecParams; |
5241 | 34.8k | mech.ulParameterLen = sizeof(ecParams); |
5242 | 34.8k | break; |
5243 | 0 | default: |
5244 | 0 | return CKR_DEVICE_ERROR; |
5245 | 40.3k | } |
5246 | | |
5247 | 40.3k | crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey); |
5248 | 40.3k | if (crv != CKR_OK) { |
5249 | 0 | sftk_FreeAttribute(pubAttribute); |
5250 | 0 | return crv; |
5251 | 0 | } |
5252 | | /* FIPS requires full validation, but in fipx mode NSC_Derive |
5253 | | * only does partial validation with approved primes, now handle |
5254 | | * full validation */ |
5255 | 40.3k | if (isFIPS && keyType == CKK_DH) { |
5256 | 0 | SECItem pubKey; |
5257 | 0 | SECItem prime; |
5258 | 0 | SECItem subPrime; |
5259 | 0 | const SECItem *subPrimePtr = &subPrime; |
5260 | |
|
5261 | 0 | pubKey.data = pubAttribute->attrib.pValue; |
5262 | 0 | pubKey.len = pubAttribute->attrib.ulValueLen; |
5263 | 0 | prime.data = subPrime.data = NULL; |
5264 | 0 | prime.len = subPrime.len = 0; |
5265 | 0 | crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME); |
5266 | 0 | if (crv != CKR_OK) { |
5267 | 0 | goto done; |
5268 | 0 | } |
5269 | 0 | crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME); |
5270 | | /* we ignore the return code an only look at the length */ |
5271 | 0 | if (subPrime.len == 0) { |
5272 | | /* subprime not supplied, In this case look it up. |
5273 | | * This only works with approved primes, but in FIPS mode |
5274 | | * that's the only kine of prime that will get here */ |
5275 | 0 | subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS); |
5276 | 0 | if (subPrimePtr == NULL) { |
5277 | 0 | crv = CKR_GENERAL_ERROR; |
5278 | 0 | goto done; |
5279 | 0 | } |
5280 | 0 | } |
5281 | 0 | if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) { |
5282 | 0 | crv = CKR_GENERAL_ERROR; |
5283 | 0 | } |
5284 | 0 | done: |
5285 | 0 | SECITEM_ZfreeItem(&subPrime, PR_FALSE); |
5286 | 0 | SECITEM_ZfreeItem(&prime, PR_FALSE); |
5287 | 0 | } |
5288 | | /* clean up before we return */ |
5289 | 40.3k | sftk_FreeAttribute(pubAttribute); |
5290 | 40.3k | crv2 = NSC_DestroyObject(hSession, newKey); |
5291 | 40.3k | if (crv != CKR_OK) { |
5292 | 0 | return crv; |
5293 | 0 | } |
5294 | 40.3k | if (crv2 != CKR_OK) { |
5295 | 0 | return crv2; |
5296 | 0 | } |
5297 | 40.3k | } |
5298 | | |
5299 | 40.3k | return CKR_OK; |
5300 | 40.3k | } |
5301 | | |
5302 | | /* NSC_GenerateKeyPair generates a public-key/private-key pair, |
5303 | | * creating new key objects. */ |
5304 | | CK_RV |
5305 | | NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession, |
5306 | | CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, |
5307 | | CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, |
5308 | | CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, |
5309 | | CK_OBJECT_HANDLE_PTR phPrivateKey) |
5310 | 40.8k | { |
5311 | 40.8k | SFTKObject *publicKey, *privateKey; |
5312 | 40.8k | SFTKSession *session; |
5313 | 40.8k | CK_KEY_TYPE key_type; |
5314 | 40.8k | CK_RV crv = CKR_OK; |
5315 | 40.8k | CK_BBOOL cktrue = CK_TRUE; |
5316 | 40.8k | SECStatus rv; |
5317 | 40.8k | CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; |
5318 | 40.8k | CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; |
5319 | 40.8k | int i; |
5320 | 40.8k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
5321 | 40.8k | unsigned int bitSize; |
5322 | | |
5323 | | /* RSA */ |
5324 | 40.8k | int public_modulus_bits = 0; |
5325 | 40.8k | SECItem pubExp; |
5326 | 40.8k | RSAPrivateKey *rsaPriv; |
5327 | | |
5328 | | /* DSA */ |
5329 | 40.8k | PQGParams pqgParam; |
5330 | 40.8k | DHParams dhParam; |
5331 | 40.8k | DSAPrivateKey *dsaPriv; |
5332 | | |
5333 | | /* Diffie Hellman */ |
5334 | 40.8k | DHPrivateKey *dhPriv; |
5335 | | |
5336 | | /* Elliptic Curve Cryptography */ |
5337 | 40.8k | SECItem ecEncodedParams; /* DER Encoded parameters */ |
5338 | 40.8k | ECPrivateKey *ecPriv; |
5339 | 40.8k | ECParams *ecParams; |
5340 | | |
5341 | | /* Kyber */ |
5342 | 40.8k | CK_NSS_KEM_PARAMETER_SET_TYPE ckKyberParamSet; |
5343 | | |
5344 | 40.8k | CHECK_FORK(); |
5345 | | |
5346 | 40.8k | if (!slot) { |
5347 | 0 | return CKR_SESSION_HANDLE_INVALID; |
5348 | 0 | } |
5349 | | /* |
5350 | | * now lets create an object to hang the attributes off of |
5351 | | */ |
5352 | 40.8k | publicKey = sftk_NewObject(slot); /* fill in the handle later */ |
5353 | 40.8k | if (publicKey == NULL) { |
5354 | 0 | return CKR_HOST_MEMORY; |
5355 | 0 | } |
5356 | | |
5357 | | /* |
5358 | | * load the template values into the publicKey |
5359 | | */ |
5360 | 332k | for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) { |
5361 | 291k | if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) { |
5362 | 0 | public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; |
5363 | 0 | continue; |
5364 | 0 | } |
5365 | | |
5366 | 291k | if (pPublicKeyTemplate[i].type == CKA_NSS_PARAMETER_SET) { |
5367 | 0 | ckKyberParamSet = *(CK_NSS_KEM_PARAMETER_SET_TYPE *)pPublicKeyTemplate[i].pValue; |
5368 | 0 | continue; |
5369 | 0 | } |
5370 | | |
5371 | 291k | crv = sftk_AddAttributeType(publicKey, |
5372 | 291k | sftk_attr_expand(&pPublicKeyTemplate[i])); |
5373 | 291k | if (crv != CKR_OK) |
5374 | 0 | break; |
5375 | 291k | } |
5376 | | |
5377 | 40.8k | if (crv != CKR_OK) { |
5378 | 0 | sftk_FreeObject(publicKey); |
5379 | 0 | return CKR_HOST_MEMORY; |
5380 | 0 | } |
5381 | | |
5382 | 40.8k | privateKey = sftk_NewObject(slot); /* fill in the handle later */ |
5383 | 40.8k | if (privateKey == NULL) { |
5384 | 0 | sftk_FreeObject(publicKey); |
5385 | 0 | return CKR_HOST_MEMORY; |
5386 | 0 | } |
5387 | | /* |
5388 | | * now load the private key template |
5389 | | */ |
5390 | 327k | for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) { |
5391 | 286k | if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) { |
5392 | 0 | continue; |
5393 | 0 | } |
5394 | | |
5395 | 286k | crv = sftk_AddAttributeType(privateKey, |
5396 | 286k | sftk_attr_expand(&pPrivateKeyTemplate[i])); |
5397 | 286k | if (crv != CKR_OK) |
5398 | 0 | break; |
5399 | 286k | } |
5400 | | |
5401 | 40.8k | if (crv != CKR_OK) { |
5402 | 0 | sftk_FreeObject(publicKey); |
5403 | 0 | sftk_FreeObject(privateKey); |
5404 | 0 | return CKR_HOST_MEMORY; |
5405 | 0 | } |
5406 | 40.8k | sftk_DeleteAttributeType(privateKey, CKA_CLASS); |
5407 | 40.8k | sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE); |
5408 | 40.8k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
5409 | 40.8k | sftk_DeleteAttributeType(publicKey, CKA_CLASS); |
5410 | 40.8k | sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE); |
5411 | 40.8k | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
5412 | | |
5413 | | /* Now Set up the parameters to generate the key (based on mechanism) */ |
5414 | 40.8k | switch (pMechanism->mechanism) { |
5415 | 0 | case CKM_RSA_PKCS_KEY_PAIR_GEN: |
5416 | | /* format the keys */ |
5417 | 0 | sftk_DeleteAttributeType(publicKey, CKA_MODULUS); |
5418 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5419 | 0 | sftk_DeleteAttributeType(privateKey, CKA_MODULUS); |
5420 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT); |
5421 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT); |
5422 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME_1); |
5423 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME_2); |
5424 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1); |
5425 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2); |
5426 | 0 | sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT); |
5427 | 0 | key_type = CKK_RSA; |
5428 | 0 | if (public_modulus_bits == 0) { |
5429 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5430 | 0 | break; |
5431 | 0 | } |
5432 | 0 | if (public_modulus_bits < RSA_MIN_MODULUS_BITS) { |
5433 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5434 | 0 | break; |
5435 | 0 | } |
5436 | 0 | if (public_modulus_bits % 2 != 0) { |
5437 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5438 | 0 | break; |
5439 | 0 | } |
5440 | | |
5441 | | /* extract the exponent */ |
5442 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT); |
5443 | 0 | if (crv != CKR_OK) |
5444 | 0 | break; |
5445 | 0 | bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len); |
5446 | 0 | if (bitSize < 2) { |
5447 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5448 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
5449 | 0 | break; |
5450 | 0 | } |
5451 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT, |
5452 | 0 | sftk_item_expand(&pubExp)); |
5453 | 0 | if (crv != CKR_OK) { |
5454 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
5455 | 0 | break; |
5456 | 0 | } |
5457 | | |
5458 | 0 | rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); |
5459 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
5460 | 0 | if (rsaPriv == NULL) { |
5461 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5462 | 0 | sftk_fatalError = PR_TRUE; |
5463 | 0 | } |
5464 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5465 | 0 | break; |
5466 | 0 | } |
5467 | | /* now fill in the RSA dependent paramenters in the public key */ |
5468 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_MODULUS, |
5469 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
5470 | 0 | if (crv != CKR_OK) |
5471 | 0 | goto kpg_done; |
5472 | | /* now fill in the RSA dependent paramenters in the private key */ |
5473 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5474 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
5475 | 0 | if (crv != CKR_OK) |
5476 | 0 | goto kpg_done; |
5477 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_MODULUS, |
5478 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
5479 | 0 | if (crv != CKR_OK) |
5480 | 0 | goto kpg_done; |
5481 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT, |
5482 | 0 | sftk_item_expand(&rsaPriv->privateExponent)); |
5483 | 0 | if (crv != CKR_OK) |
5484 | 0 | goto kpg_done; |
5485 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1, |
5486 | 0 | sftk_item_expand(&rsaPriv->prime1)); |
5487 | 0 | if (crv != CKR_OK) |
5488 | 0 | goto kpg_done; |
5489 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2, |
5490 | 0 | sftk_item_expand(&rsaPriv->prime2)); |
5491 | 0 | if (crv != CKR_OK) |
5492 | 0 | goto kpg_done; |
5493 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1, |
5494 | 0 | sftk_item_expand(&rsaPriv->exponent1)); |
5495 | 0 | if (crv != CKR_OK) |
5496 | 0 | goto kpg_done; |
5497 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2, |
5498 | 0 | sftk_item_expand(&rsaPriv->exponent2)); |
5499 | 0 | if (crv != CKR_OK) |
5500 | 0 | goto kpg_done; |
5501 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT, |
5502 | 0 | sftk_item_expand(&rsaPriv->coefficient)); |
5503 | 0 | kpg_done: |
5504 | | /* Should zeroize the contents first, since this func doesn't. */ |
5505 | 0 | PORT_FreeArena(rsaPriv->arena, PR_TRUE); |
5506 | 0 | break; |
5507 | 0 | case CKM_DSA_KEY_PAIR_GEN: |
5508 | 0 | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
5509 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5510 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME); |
5511 | 0 | sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME); |
5512 | 0 | sftk_DeleteAttributeType(privateKey, CKA_BASE); |
5513 | 0 | key_type = CKK_DSA; |
5514 | | |
5515 | | /* extract the necessary parameters and copy them to the private key */ |
5516 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME); |
5517 | 0 | if (crv != CKR_OK) |
5518 | 0 | break; |
5519 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey, |
5520 | 0 | CKA_SUBPRIME); |
5521 | 0 | if (crv != CKR_OK) { |
5522 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5523 | 0 | break; |
5524 | 0 | } |
5525 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE); |
5526 | 0 | if (crv != CKR_OK) { |
5527 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5528 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5529 | 0 | break; |
5530 | 0 | } |
5531 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
5532 | 0 | sftk_item_expand(&pqgParam.prime)); |
5533 | 0 | if (crv != CKR_OK) { |
5534 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5535 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5536 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5537 | 0 | break; |
5538 | 0 | } |
5539 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME, |
5540 | 0 | sftk_item_expand(&pqgParam.subPrime)); |
5541 | 0 | if (crv != CKR_OK) { |
5542 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5543 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5544 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5545 | 0 | break; |
5546 | 0 | } |
5547 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
5548 | 0 | sftk_item_expand(&pqgParam.base)); |
5549 | 0 | if (crv != CKR_OK) { |
5550 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5551 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5552 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5553 | 0 | break; |
5554 | 0 | } |
5555 | | |
5556 | | /* |
5557 | | * these are checked by DSA_NewKey |
5558 | | */ |
5559 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data, |
5560 | 0 | pqgParam.subPrime.len); |
5561 | 0 | if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) { |
5562 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5563 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5564 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5565 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5566 | 0 | break; |
5567 | 0 | } |
5568 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len); |
5569 | 0 | if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) { |
5570 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5571 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5572 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5573 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5574 | 0 | break; |
5575 | 0 | } |
5576 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len); |
5577 | 0 | if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) { |
5578 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5579 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5580 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5581 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5582 | 0 | break; |
5583 | 0 | } |
5584 | | |
5585 | | /* Generate the key */ |
5586 | 0 | rv = DSA_NewKey(&pqgParam, &dsaPriv); |
5587 | |
|
5588 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5589 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5590 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5591 | |
|
5592 | 0 | if (rv != SECSuccess) { |
5593 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5594 | 0 | sftk_fatalError = PR_TRUE; |
5595 | 0 | } |
5596 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5597 | 0 | break; |
5598 | 0 | } |
5599 | | |
5600 | | /* store the generated key into the attributes */ |
5601 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
5602 | 0 | sftk_item_expand(&dsaPriv->publicValue)); |
5603 | 0 | if (crv != CKR_OK) |
5604 | 0 | goto dsagn_done; |
5605 | | |
5606 | | /* now fill in the RSA dependent paramenters in the private key */ |
5607 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5608 | 0 | sftk_item_expand(&dsaPriv->publicValue)); |
5609 | 0 | if (crv != CKR_OK) |
5610 | 0 | goto dsagn_done; |
5611 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5612 | 0 | sftk_item_expand(&dsaPriv->privateValue)); |
5613 | |
|
5614 | 0 | dsagn_done: |
5615 | | /* should zeroize, since this function doesn't. */ |
5616 | 0 | PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); |
5617 | 0 | break; |
5618 | | |
5619 | 5.53k | case CKM_DH_PKCS_KEY_PAIR_GEN: |
5620 | 5.53k | sftk_DeleteAttributeType(privateKey, CKA_PRIME); |
5621 | 5.53k | sftk_DeleteAttributeType(privateKey, CKA_BASE); |
5622 | 5.53k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
5623 | 5.53k | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5624 | 5.53k | key_type = CKK_DH; |
5625 | | |
5626 | | /* extract the necessary parameters and copy them to private keys */ |
5627 | 5.53k | crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, |
5628 | 5.53k | CKA_PRIME); |
5629 | 5.53k | if (crv != CKR_OK) |
5630 | 0 | break; |
5631 | 5.53k | crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE); |
5632 | 5.53k | if (crv != CKR_OK) { |
5633 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5634 | 0 | break; |
5635 | 0 | } |
5636 | 5.53k | crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
5637 | 5.53k | sftk_item_expand(&dhParam.prime)); |
5638 | 5.53k | if (crv != CKR_OK) { |
5639 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5640 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5641 | 0 | break; |
5642 | 0 | } |
5643 | 5.53k | crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
5644 | 5.53k | sftk_item_expand(&dhParam.base)); |
5645 | 5.53k | if (crv != CKR_OK) { |
5646 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5647 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5648 | 0 | break; |
5649 | 0 | } |
5650 | 5.53k | bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len); |
5651 | 5.53k | if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) { |
5652 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5653 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5654 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5655 | 0 | break; |
5656 | 0 | } |
5657 | 5.53k | bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len); |
5658 | 5.53k | if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) { |
5659 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5660 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5661 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5662 | 0 | break; |
5663 | 0 | } |
5664 | | |
5665 | 5.53k | rv = DH_NewKey(&dhParam, &dhPriv); |
5666 | 5.53k | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5667 | 5.53k | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5668 | 5.53k | if (rv != SECSuccess) { |
5669 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5670 | 0 | sftk_fatalError = PR_TRUE; |
5671 | 0 | } |
5672 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5673 | 0 | break; |
5674 | 0 | } |
5675 | | |
5676 | 5.53k | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
5677 | 5.53k | sftk_item_expand(&dhPriv->publicValue)); |
5678 | 5.53k | if (crv != CKR_OK) |
5679 | 0 | goto dhgn_done; |
5680 | | |
5681 | 5.53k | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5682 | 5.53k | sftk_item_expand(&dhPriv->publicValue)); |
5683 | 5.53k | if (crv != CKR_OK) |
5684 | 0 | goto dhgn_done; |
5685 | | |
5686 | 5.53k | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5687 | 5.53k | sftk_item_expand(&dhPriv->privateValue)); |
5688 | | |
5689 | 5.53k | dhgn_done: |
5690 | | /* should zeroize, since this function doesn't. */ |
5691 | 5.53k | PORT_FreeArena(dhPriv->arena, PR_TRUE); |
5692 | 5.53k | break; |
5693 | | |
5694 | 35.3k | case CKM_EC_KEY_PAIR_GEN: |
5695 | 35.3k | sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); |
5696 | 35.3k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
5697 | 35.3k | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5698 | 35.3k | key_type = CKK_EC; |
5699 | | |
5700 | | /* extract the necessary parameters and copy them to private keys */ |
5701 | 35.3k | crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
5702 | 35.3k | CKA_EC_PARAMS); |
5703 | 35.3k | if (crv != CKR_OK) |
5704 | 0 | break; |
5705 | | |
5706 | 35.3k | crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
5707 | 35.3k | sftk_item_expand(&ecEncodedParams)); |
5708 | 35.3k | if (crv != CKR_OK) { |
5709 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
5710 | 0 | break; |
5711 | 0 | } |
5712 | | |
5713 | | /* Decode ec params before calling EC_NewKey */ |
5714 | 35.3k | rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
5715 | 35.3k | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
5716 | 35.3k | if (rv != SECSuccess) { |
5717 | 562 | crv = sftk_MapCryptError(PORT_GetError()); |
5718 | 562 | break; |
5719 | 562 | } |
5720 | 34.8k | rv = EC_NewKey(ecParams, &ecPriv); |
5721 | 34.8k | if (rv != SECSuccess) { |
5722 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5723 | 0 | sftk_fatalError = PR_TRUE; |
5724 | 0 | } |
5725 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5726 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5727 | 0 | break; |
5728 | 0 | } |
5729 | | |
5730 | 34.8k | if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") || |
5731 | 34.8k | ecParams->type != ec_params_named) { |
5732 | 20.8k | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5733 | 20.8k | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
5734 | 20.8k | sftk_item_expand(&ecPriv->publicValue)); |
5735 | 20.8k | } else { |
5736 | 13.9k | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5737 | 13.9k | SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, |
5738 | 13.9k | &ecPriv->publicValue, |
5739 | 13.9k | SEC_ASN1_GET(SEC_OctetStringTemplate)); |
5740 | 13.9k | if (!pubValue) { |
5741 | 0 | crv = CKR_ARGUMENTS_BAD; |
5742 | 0 | goto ecgn_done; |
5743 | 0 | } |
5744 | 13.9k | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
5745 | 13.9k | sftk_item_expand(pubValue)); |
5746 | 13.9k | SECITEM_ZfreeItem(pubValue, PR_TRUE); |
5747 | 13.9k | } |
5748 | 34.8k | if (crv != CKR_OK) |
5749 | 0 | goto ecgn_done; |
5750 | | |
5751 | 34.8k | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5752 | 34.8k | sftk_item_expand(&ecPriv->privateValue)); |
5753 | 34.8k | if (crv != CKR_OK) |
5754 | 0 | goto ecgn_done; |
5755 | | |
5756 | 34.8k | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5757 | 34.8k | sftk_item_expand(&ecPriv->publicValue)); |
5758 | 34.8k | ecgn_done: |
5759 | | /* should zeroize, since this function doesn't. */ |
5760 | 34.8k | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
5761 | 34.8k | break; |
5762 | | |
5763 | 0 | case CKM_NSS_KYBER_KEY_PAIR_GEN: |
5764 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5765 | 0 | key_type = CKK_NSS_KYBER; |
5766 | |
|
5767 | 0 | SECItem privKey = { siBuffer, NULL, 0 }; |
5768 | 0 | SECItem pubKey = { siBuffer, NULL, 0 }; |
5769 | 0 | KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(ckKyberParamSet); |
5770 | 0 | if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) { |
5771 | 0 | crv = CKR_HOST_MEMORY; |
5772 | 0 | goto kyber_done; |
5773 | 0 | } |
5774 | 0 | if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) { |
5775 | 0 | crv = CKR_HOST_MEMORY; |
5776 | 0 | goto kyber_done; |
5777 | 0 | } |
5778 | 0 | rv = Kyber_NewKey(kyberParams, NULL, &privKey, &pubKey); |
5779 | 0 | if (rv != SECSuccess) { |
5780 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5781 | 0 | goto kyber_done; |
5782 | 0 | } |
5783 | | |
5784 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, sftk_item_expand(&pubKey)); |
5785 | 0 | if (crv != CKR_OK) { |
5786 | 0 | goto kyber_done; |
5787 | 0 | } |
5788 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_NSS_PARAMETER_SET, |
5789 | 0 | &ckKyberParamSet, sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE)); |
5790 | 0 | if (crv != CKR_OK) { |
5791 | 0 | goto kyber_done; |
5792 | 0 | } |
5793 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5794 | 0 | sftk_item_expand(&privKey)); |
5795 | 0 | if (crv != CKR_OK) { |
5796 | 0 | goto kyber_done; |
5797 | 0 | } |
5798 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_PARAMETER_SET, |
5799 | 0 | &ckKyberParamSet, sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE)); |
5800 | 0 | if (crv != CKR_OK) { |
5801 | 0 | goto kyber_done; |
5802 | 0 | } |
5803 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5804 | 0 | sftk_item_expand(&pubKey)); |
5805 | 0 | kyber_done: |
5806 | 0 | SECITEM_ZfreeItem(&privKey, PR_FALSE); |
5807 | 0 | SECITEM_FreeItem(&pubKey, PR_FALSE); |
5808 | 0 | break; |
5809 | | |
5810 | 0 | case CKM_EC_EDWARDS_KEY_PAIR_GEN: |
5811 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); |
5812 | 0 | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
5813 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5814 | 0 | key_type = CKK_EC_EDWARDS; |
5815 | | |
5816 | | /* extract the necessary parameters and copy them to private keys */ |
5817 | 0 | crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
5818 | 0 | CKA_EC_PARAMS); |
5819 | 0 | if (crv != CKR_OK) { |
5820 | 0 | break; |
5821 | 0 | } |
5822 | | |
5823 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
5824 | 0 | sftk_item_expand(&ecEncodedParams)); |
5825 | 0 | if (crv != CKR_OK) { |
5826 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
5827 | 0 | break; |
5828 | 0 | } |
5829 | | |
5830 | | /* Decode ec params before calling EC_NewKey */ |
5831 | 0 | rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
5832 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
5833 | 0 | if (rv != SECSuccess) { |
5834 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5835 | 0 | break; |
5836 | 0 | } |
5837 | | |
5838 | 0 | rv = EC_NewKey(ecParams, &ecPriv); |
5839 | 0 | if (rv != SECSuccess) { |
5840 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5841 | 0 | sftk_fatalError = PR_TRUE; |
5842 | 0 | } |
5843 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5844 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5845 | 0 | break; |
5846 | 0 | } |
5847 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5848 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
5849 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
5850 | 0 | if (crv != CKR_OK) |
5851 | 0 | goto edgn_done; |
5852 | | |
5853 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5854 | 0 | sftk_item_expand(&ecPriv->privateValue)); |
5855 | 0 | if (crv != CKR_OK) |
5856 | 0 | goto edgn_done; |
5857 | | |
5858 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5859 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
5860 | 0 | edgn_done: |
5861 | | /* should zeroize, since this function doesn't. */ |
5862 | 0 | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
5863 | 0 | break; |
5864 | | |
5865 | 0 | default: |
5866 | 0 | crv = CKR_MECHANISM_INVALID; |
5867 | 40.8k | } |
5868 | | |
5869 | 40.8k | if (crv != CKR_OK) { |
5870 | 562 | sftk_FreeObject(privateKey); |
5871 | 562 | sftk_FreeObject(publicKey); |
5872 | 562 | return crv; |
5873 | 562 | } |
5874 | | |
5875 | | /* Add the class, key_type The loop lets us check errors blow out |
5876 | | * on errors and clean up at the bottom */ |
5877 | 40.3k | session = NULL; /* make pedtantic happy... session cannot leave the*/ |
5878 | | /* loop below NULL unless an error is set... */ |
5879 | 40.3k | do { |
5880 | 40.3k | crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass, |
5881 | 40.3k | sizeof(CK_OBJECT_CLASS)); |
5882 | 40.3k | if (crv != CKR_OK) |
5883 | 0 | break; |
5884 | 40.3k | crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass, |
5885 | 40.3k | sizeof(CK_OBJECT_CLASS)); |
5886 | 40.3k | if (crv != CKR_OK) |
5887 | 0 | break; |
5888 | 40.3k | crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type, |
5889 | 40.3k | sizeof(CK_KEY_TYPE)); |
5890 | 40.3k | if (crv != CKR_OK) |
5891 | 0 | break; |
5892 | 40.3k | crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type, |
5893 | 40.3k | sizeof(CK_KEY_TYPE)); |
5894 | 40.3k | if (crv != CKR_OK) |
5895 | 0 | break; |
5896 | 40.3k | session = sftk_SessionFromHandle(hSession); |
5897 | 40.3k | if (session == NULL) |
5898 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
5899 | 40.3k | } while (0); |
5900 | | |
5901 | 40.3k | if (crv != CKR_OK) { |
5902 | 0 | sftk_FreeObject(privateKey); |
5903 | 0 | sftk_FreeObject(publicKey); |
5904 | 0 | return crv; |
5905 | 0 | } |
5906 | | |
5907 | | /* |
5908 | | * handle the base object cleanup for the public Key |
5909 | | */ |
5910 | 40.3k | crv = sftk_handleObject(privateKey, session); |
5911 | 40.3k | if (crv != CKR_OK) { |
5912 | 0 | sftk_FreeSession(session); |
5913 | 0 | sftk_FreeObject(privateKey); |
5914 | 0 | sftk_FreeObject(publicKey); |
5915 | 0 | return crv; |
5916 | 0 | } |
5917 | | |
5918 | | /* |
5919 | | * handle the base object cleanup for the private Key |
5920 | | * If we have any problems, we destroy the public Key we've |
5921 | | * created and linked. |
5922 | | */ |
5923 | 40.3k | crv = sftk_handleObject(publicKey, session); |
5924 | 40.3k | sftk_FreeSession(session); |
5925 | 40.3k | if (crv != CKR_OK) { |
5926 | 0 | sftk_FreeObject(publicKey); |
5927 | 0 | NSC_DestroyObject(hSession, privateKey->handle); |
5928 | 0 | sftk_FreeObject(privateKey); |
5929 | 0 | return crv; |
5930 | 0 | } |
5931 | 40.3k | if (sftk_isTrue(privateKey, CKA_SENSITIVE)) { |
5932 | 0 | crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE, |
5933 | 0 | &cktrue, sizeof(CK_BBOOL)); |
5934 | 0 | } |
5935 | 40.3k | if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) { |
5936 | 0 | crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE, |
5937 | 0 | &cktrue, sizeof(CK_BBOOL)); |
5938 | 0 | } |
5939 | 40.3k | if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) { |
5940 | 0 | crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE, |
5941 | 0 | &cktrue, sizeof(CK_BBOOL)); |
5942 | 0 | } |
5943 | 40.3k | if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) { |
5944 | 40.3k | crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE, |
5945 | 40.3k | &cktrue, sizeof(CK_BBOOL)); |
5946 | 40.3k | } |
5947 | | |
5948 | 40.3k | if (crv == CKR_OK && key_type != CKK_NSS_KYBER) { |
5949 | | /* Perform FIPS 140-2 pairwise consistency check. */ |
5950 | 40.3k | crv = sftk_PairwiseConsistencyCheck(hSession, slot, |
5951 | 40.3k | publicKey, privateKey, key_type); |
5952 | 40.3k | if (crv != CKR_OK) { |
5953 | 0 | if (sftk_audit_enabled) { |
5954 | 0 | char msg[128]; |
5955 | 0 | PR_snprintf(msg, sizeof msg, |
5956 | 0 | "C_GenerateKeyPair(hSession=0x%08lX, " |
5957 | 0 | "pMechanism->mechanism=0x%08lX)=0x%08lX " |
5958 | 0 | "self-test: pair-wise consistency test failed", |
5959 | 0 | (PRUint32)hSession, (PRUint32)pMechanism->mechanism, |
5960 | 0 | (PRUint32)crv); |
5961 | 0 | sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); |
5962 | 0 | } |
5963 | 0 | } |
5964 | 40.3k | } |
5965 | | |
5966 | 40.3k | if (crv != CKR_OK) { |
5967 | 0 | NSC_DestroyObject(hSession, publicKey->handle); |
5968 | 0 | sftk_FreeObject(publicKey); |
5969 | 0 | NSC_DestroyObject(hSession, privateKey->handle); |
5970 | 0 | sftk_FreeObject(privateKey); |
5971 | 0 | return crv; |
5972 | 0 | } |
5973 | | |
5974 | 40.3k | *phPrivateKey = privateKey->handle; |
5975 | 40.3k | *phPublicKey = publicKey->handle; |
5976 | 40.3k | sftk_FreeObject(publicKey); |
5977 | 40.3k | sftk_FreeObject(privateKey); |
5978 | | |
5979 | 40.3k | return CKR_OK; |
5980 | 40.3k | } |
5981 | | |
5982 | | static SECItem * |
5983 | | sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) |
5984 | 0 | { |
5985 | 0 | NSSLOWKEYPrivateKey *lk = NULL; |
5986 | 0 | NSSLOWKEYPrivateKeyInfo *pki = NULL; |
5987 | 0 | SFTKAttribute *attribute = NULL; |
5988 | 0 | PLArenaPool *arena = NULL; |
5989 | 0 | SECOidTag algorithm = SEC_OID_UNKNOWN; |
5990 | 0 | void *dummy, *param = NULL; |
5991 | 0 | SECStatus rv = SECSuccess; |
5992 | 0 | SECItem *encodedKey = NULL; |
5993 | | #ifdef EC_DEBUG |
5994 | | SECItem *fordebug; |
5995 | | #endif |
5996 | 0 | int savelen; |
5997 | |
|
5998 | 0 | if (!key) { |
5999 | 0 | *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ |
6000 | 0 | return NULL; |
6001 | 0 | } |
6002 | | |
6003 | 0 | attribute = sftk_FindAttribute(key, CKA_KEY_TYPE); |
6004 | 0 | if (!attribute) { |
6005 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6006 | 0 | return NULL; |
6007 | 0 | } |
6008 | | |
6009 | 0 | lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp); |
6010 | 0 | sftk_FreeAttribute(attribute); |
6011 | 0 | if (!lk) { |
6012 | 0 | return NULL; |
6013 | 0 | } |
6014 | | |
6015 | 0 | arena = PORT_NewArena(2048); /* XXX different size? */ |
6016 | 0 | if (!arena) { |
6017 | 0 | *crvp = CKR_HOST_MEMORY; |
6018 | 0 | rv = SECFailure; |
6019 | 0 | goto loser; |
6020 | 0 | } |
6021 | | |
6022 | 0 | pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, |
6023 | 0 | sizeof(NSSLOWKEYPrivateKeyInfo)); |
6024 | 0 | if (!pki) { |
6025 | 0 | *crvp = CKR_HOST_MEMORY; |
6026 | 0 | rv = SECFailure; |
6027 | 0 | goto loser; |
6028 | 0 | } |
6029 | 0 | pki->arena = arena; |
6030 | |
|
6031 | 0 | param = NULL; |
6032 | 0 | switch (lk->keyType) { |
6033 | 0 | case NSSLOWKEYRSAKey: |
6034 | 0 | prepare_low_rsa_priv_key_for_asn1(lk); |
6035 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6036 | 0 | nsslowkey_RSAPrivateKeyTemplate); |
6037 | | |
6038 | | /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */ |
6039 | 0 | attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO); |
6040 | 0 | if (attribute) { |
6041 | 0 | NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo; |
6042 | 0 | SECItem spki; |
6043 | |
|
6044 | 0 | spki.data = attribute->attrib.pValue; |
6045 | 0 | spki.len = attribute->attrib.ulValueLen; |
6046 | |
|
6047 | 0 | publicKeyInfo = PORT_ArenaZAlloc(arena, |
6048 | 0 | sizeof(NSSLOWKEYSubjectPublicKeyInfo)); |
6049 | 0 | if (!publicKeyInfo) { |
6050 | 0 | sftk_FreeAttribute(attribute); |
6051 | 0 | *crvp = CKR_HOST_MEMORY; |
6052 | 0 | rv = SECFailure; |
6053 | 0 | goto loser; |
6054 | 0 | } |
6055 | 0 | rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo, |
6056 | 0 | nsslowkey_SubjectPublicKeyInfoTemplate, |
6057 | 0 | &spki); |
6058 | 0 | if (rv != SECSuccess) { |
6059 | 0 | sftk_FreeAttribute(attribute); |
6060 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6061 | 0 | goto loser; |
6062 | 0 | } |
6063 | 0 | algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm); |
6064 | 0 | if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION && |
6065 | 0 | algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { |
6066 | 0 | sftk_FreeAttribute(attribute); |
6067 | 0 | rv = SECFailure; |
6068 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6069 | 0 | goto loser; |
6070 | 0 | } |
6071 | 0 | param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters); |
6072 | 0 | if (!param) { |
6073 | 0 | sftk_FreeAttribute(attribute); |
6074 | 0 | rv = SECFailure; |
6075 | 0 | *crvp = CKR_HOST_MEMORY; |
6076 | 0 | goto loser; |
6077 | 0 | } |
6078 | 0 | sftk_FreeAttribute(attribute); |
6079 | 0 | } else { |
6080 | | /* default to PKCS #1 */ |
6081 | 0 | algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
6082 | 0 | } |
6083 | 0 | break; |
6084 | 0 | case NSSLOWKEYDSAKey: |
6085 | 0 | prepare_low_dsa_priv_key_export_for_asn1(lk); |
6086 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6087 | 0 | nsslowkey_DSAPrivateKeyExportTemplate); |
6088 | 0 | prepare_low_pqg_params_for_asn1(&lk->u.dsa.params); |
6089 | 0 | param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), |
6090 | 0 | nsslowkey_PQGParamsTemplate); |
6091 | 0 | algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; |
6092 | 0 | break; |
6093 | 0 | case NSSLOWKEYECKey: |
6094 | 0 | prepare_low_ec_priv_key_for_asn1(lk); |
6095 | | /* Public value is encoded as a bit string so adjust length |
6096 | | * to be in bits before ASN encoding and readjust |
6097 | | * immediately after. |
6098 | | * |
6099 | | * Since the SECG specification recommends not including the |
6100 | | * parameters as part of ECPrivateKey, we zero out the curveOID |
6101 | | * length before encoding and restore it later. |
6102 | | */ |
6103 | 0 | lk->u.ec.publicValue.len <<= 3; |
6104 | 0 | savelen = lk->u.ec.ecParams.curveOID.len; |
6105 | 0 | lk->u.ec.ecParams.curveOID.len = 0; |
6106 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6107 | 0 | nsslowkey_ECPrivateKeyTemplate); |
6108 | 0 | lk->u.ec.ecParams.curveOID.len = savelen; |
6109 | 0 | lk->u.ec.publicValue.len >>= 3; |
6110 | |
|
6111 | | #ifdef EC_DEBUG |
6112 | | fordebug = &pki->privateKey; |
6113 | | SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType, |
6114 | | fordebug); |
6115 | | #endif |
6116 | |
|
6117 | 0 | param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); |
6118 | |
|
6119 | 0 | algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; |
6120 | 0 | break; |
6121 | 0 | case NSSLOWKEYDHKey: |
6122 | 0 | default: |
6123 | 0 | dummy = NULL; |
6124 | 0 | break; |
6125 | 0 | } |
6126 | | |
6127 | 0 | if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { |
6128 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6129 | 0 | rv = SECFailure; |
6130 | 0 | goto loser; |
6131 | 0 | } |
6132 | | |
6133 | 0 | rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, |
6134 | 0 | (SECItem *)param); |
6135 | 0 | if (rv != SECSuccess) { |
6136 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6137 | 0 | rv = SECFailure; |
6138 | 0 | goto loser; |
6139 | 0 | } |
6140 | | |
6141 | 0 | dummy = SEC_ASN1EncodeInteger(arena, &pki->version, |
6142 | 0 | NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); |
6143 | 0 | if (!dummy) { |
6144 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6145 | 0 | rv = SECFailure; |
6146 | 0 | goto loser; |
6147 | 0 | } |
6148 | | |
6149 | 0 | encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, |
6150 | 0 | nsslowkey_PrivateKeyInfoTemplate); |
6151 | 0 | *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR; |
6152 | |
|
6153 | | #ifdef EC_DEBUG |
6154 | | fordebug = encodedKey; |
6155 | | SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType, |
6156 | | fordebug); |
6157 | | #endif |
6158 | 0 | loser: |
6159 | 0 | if (arena) { |
6160 | 0 | PORT_FreeArena(arena, PR_TRUE); |
6161 | 0 | } |
6162 | |
|
6163 | 0 | if (lk && (lk != key->objectInfo)) { |
6164 | 0 | nsslowkey_DestroyPrivateKey(lk); |
6165 | 0 | } |
6166 | |
|
6167 | 0 | if (param) { |
6168 | 0 | SECITEM_ZfreeItem((SECItem *)param, PR_TRUE); |
6169 | 0 | } |
6170 | |
|
6171 | 0 | if (rv != SECSuccess) { |
6172 | 0 | return NULL; |
6173 | 0 | } |
6174 | | |
6175 | 0 | return encodedKey; |
6176 | 0 | } |
6177 | | |
6178 | | /* it doesn't matter yet, since we colapse error conditions in the |
6179 | | * level above, but we really should map those few key error differences */ |
6180 | | static CK_RV |
6181 | | sftk_mapWrap(CK_RV crv) |
6182 | 4.50k | { |
6183 | 4.50k | switch (crv) { |
6184 | 0 | case CKR_ENCRYPTED_DATA_INVALID: |
6185 | 0 | crv = CKR_WRAPPED_KEY_INVALID; |
6186 | 0 | break; |
6187 | 4.50k | } |
6188 | 4.50k | return crv; |
6189 | 4.50k | } |
6190 | | |
6191 | | /* NSC_WrapKey wraps (i.e., encrypts) a key. */ |
6192 | | CK_RV |
6193 | | NSC_WrapKey(CK_SESSION_HANDLE hSession, |
6194 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, |
6195 | | CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, |
6196 | | CK_ULONG_PTR pulWrappedKeyLen) |
6197 | 4.48k | { |
6198 | 4.48k | SFTKSession *session; |
6199 | 4.48k | SFTKAttribute *attribute; |
6200 | 4.48k | SFTKObject *key; |
6201 | 4.48k | CK_RV crv; |
6202 | | |
6203 | 4.48k | CHECK_FORK(); |
6204 | | |
6205 | 4.48k | session = sftk_SessionFromHandle(hSession); |
6206 | 4.48k | if (session == NULL) { |
6207 | 0 | return CKR_SESSION_HANDLE_INVALID; |
6208 | 0 | } |
6209 | | |
6210 | 4.48k | key = sftk_ObjectFromHandle(hKey, session); |
6211 | 4.48k | if (key == NULL) { |
6212 | 0 | sftk_FreeSession(session); |
6213 | 0 | return CKR_KEY_HANDLE_INVALID; |
6214 | 0 | } |
6215 | | |
6216 | 4.48k | switch (key->objclass) { |
6217 | 4.48k | case CKO_SECRET_KEY: { |
6218 | 4.48k | SFTKSessionContext *context = NULL; |
6219 | 4.48k | SECItem pText; |
6220 | | |
6221 | 4.48k | attribute = sftk_FindAttribute(key, CKA_VALUE); |
6222 | | |
6223 | 4.48k | if (attribute == NULL) { |
6224 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
6225 | 0 | break; |
6226 | 0 | } |
6227 | 4.48k | crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
6228 | 4.48k | CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
6229 | 4.48k | if (crv != CKR_OK) { |
6230 | 18 | sftk_FreeAttribute(attribute); |
6231 | 18 | break; |
6232 | 18 | } |
6233 | | |
6234 | 4.46k | pText.type = siBuffer; |
6235 | 4.46k | pText.data = (unsigned char *)attribute->attrib.pValue; |
6236 | 4.46k | pText.len = attribute->attrib.ulValueLen; |
6237 | | |
6238 | | /* Find out if this is a block cipher. */ |
6239 | 4.46k | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, NULL); |
6240 | 4.46k | if (crv != CKR_OK || !context) |
6241 | 0 | break; |
6242 | 4.46k | if (context->blockSize > 1) { |
6243 | 1.73k | unsigned int remainder = pText.len % context->blockSize; |
6244 | 1.73k | if (!context->doPad && remainder) { |
6245 | | /* When wrapping secret keys with unpadded block ciphers, |
6246 | | ** the keys are zero padded, if necessary, to fill out |
6247 | | ** a full block. |
6248 | | */ |
6249 | 0 | pText.len += context->blockSize - remainder; |
6250 | 0 | pText.data = PORT_ZAlloc(pText.len); |
6251 | 0 | if (pText.data) |
6252 | 0 | memcpy(pText.data, attribute->attrib.pValue, |
6253 | 0 | attribute->attrib.ulValueLen); |
6254 | 0 | else { |
6255 | 0 | crv = CKR_HOST_MEMORY; |
6256 | 0 | break; |
6257 | 0 | } |
6258 | 0 | } |
6259 | 1.73k | } |
6260 | | |
6261 | 4.46k | crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, |
6262 | 4.46k | pText.len, pWrappedKey, pulWrappedKeyLen); |
6263 | | /* always force a finalize, both on errors and when |
6264 | | * we are just getting the size */ |
6265 | 4.46k | if (crv != CKR_OK || pWrappedKey == NULL) { |
6266 | 0 | CK_RV lcrv; |
6267 | 0 | lcrv = sftk_GetContext(hSession, &context, |
6268 | 0 | SFTK_ENCRYPT, PR_FALSE, NULL); |
6269 | 0 | sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); |
6270 | 0 | if (lcrv == CKR_OK && context) { |
6271 | 0 | sftk_FreeContext(context); |
6272 | 0 | } |
6273 | 0 | } |
6274 | | |
6275 | 4.46k | if (pText.data != (unsigned char *)attribute->attrib.pValue) |
6276 | 0 | PORT_ZFree(pText.data, pText.len); |
6277 | 4.46k | sftk_FreeAttribute(attribute); |
6278 | 4.46k | break; |
6279 | 4.46k | } |
6280 | | |
6281 | 0 | case CKO_PRIVATE_KEY: { |
6282 | 0 | SECItem *bpki = sftk_PackagePrivateKey(key, &crv); |
6283 | 0 | SFTKSessionContext *context = NULL; |
6284 | |
|
6285 | 0 | if (!bpki) { |
6286 | 0 | break; |
6287 | 0 | } |
6288 | | |
6289 | 0 | crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
6290 | 0 | CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
6291 | 0 | if (crv != CKR_OK) { |
6292 | 0 | SECITEM_ZfreeItem(bpki, PR_TRUE); |
6293 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
6294 | 0 | break; |
6295 | 0 | } |
6296 | | |
6297 | 0 | crv = NSC_Encrypt(hSession, bpki->data, bpki->len, |
6298 | 0 | pWrappedKey, pulWrappedKeyLen); |
6299 | | /* always force a finalize */ |
6300 | 0 | if (crv != CKR_OK || pWrappedKey == NULL) { |
6301 | 0 | CK_RV lcrv; |
6302 | 0 | lcrv = sftk_GetContext(hSession, &context, |
6303 | 0 | SFTK_ENCRYPT, PR_FALSE, NULL); |
6304 | 0 | sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); |
6305 | 0 | if (lcrv == CKR_OK && context) { |
6306 | 0 | sftk_FreeContext(context); |
6307 | 0 | } |
6308 | 0 | } |
6309 | 0 | SECITEM_ZfreeItem(bpki, PR_TRUE); |
6310 | 0 | break; |
6311 | 0 | } |
6312 | | |
6313 | 0 | default: |
6314 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
6315 | 0 | break; |
6316 | 4.48k | } |
6317 | 4.48k | sftk_FreeObject(key); |
6318 | 4.48k | sftk_FreeSession(session); |
6319 | 4.48k | return sftk_mapWrap(crv); |
6320 | 4.48k | } |
6321 | | |
6322 | | /* |
6323 | | * import a pprivate key info into the desired slot |
6324 | | */ |
6325 | | static SECStatus |
6326 | | sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) |
6327 | 0 | { |
6328 | 0 | CK_BBOOL cktrue = CK_TRUE; |
6329 | 0 | CK_KEY_TYPE keyType = CKK_RSA; |
6330 | 0 | SECStatus rv = SECFailure; |
6331 | 0 | const SEC_ASN1Template *keyTemplate, *paramTemplate; |
6332 | 0 | void *paramDest = NULL; |
6333 | 0 | PLArenaPool *arena; |
6334 | 0 | NSSLOWKEYPrivateKey *lpk = NULL; |
6335 | 0 | NSSLOWKEYPrivateKeyInfo *pki = NULL; |
6336 | 0 | CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; |
6337 | |
|
6338 | 0 | arena = PORT_NewArena(2048); |
6339 | 0 | if (!arena) { |
6340 | 0 | return SECFailure; |
6341 | 0 | } |
6342 | | |
6343 | 0 | pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, |
6344 | 0 | sizeof(NSSLOWKEYPrivateKeyInfo)); |
6345 | 0 | if (!pki) { |
6346 | 0 | PORT_FreeArena(arena, PR_FALSE); |
6347 | 0 | return SECFailure; |
6348 | 0 | } |
6349 | | |
6350 | 0 | if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) { |
6351 | 0 | PORT_FreeArena(arena, PR_TRUE); |
6352 | 0 | return SECFailure; |
6353 | 0 | } |
6354 | | |
6355 | 0 | lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena, |
6356 | 0 | sizeof(NSSLOWKEYPrivateKey)); |
6357 | 0 | if (lpk == NULL) { |
6358 | 0 | goto loser; |
6359 | 0 | } |
6360 | 0 | lpk->arena = arena; |
6361 | |
|
6362 | 0 | switch (SECOID_GetAlgorithmTag(&pki->algorithm)) { |
6363 | 0 | case SEC_OID_PKCS1_RSA_ENCRYPTION: |
6364 | 0 | case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
6365 | 0 | keyTemplate = nsslowkey_RSAPrivateKeyTemplate; |
6366 | 0 | paramTemplate = NULL; |
6367 | 0 | paramDest = NULL; |
6368 | 0 | lpk->keyType = NSSLOWKEYRSAKey; |
6369 | 0 | prepare_low_rsa_priv_key_for_asn1(lpk); |
6370 | 0 | break; |
6371 | 0 | case SEC_OID_ANSIX9_DSA_SIGNATURE: |
6372 | 0 | keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; |
6373 | 0 | paramTemplate = nsslowkey_PQGParamsTemplate; |
6374 | 0 | paramDest = &(lpk->u.dsa.params); |
6375 | 0 | lpk->keyType = NSSLOWKEYDSAKey; |
6376 | 0 | prepare_low_dsa_priv_key_export_for_asn1(lpk); |
6377 | 0 | prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); |
6378 | 0 | break; |
6379 | | /* case NSSLOWKEYDHKey: */ |
6380 | 0 | case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
6381 | 0 | keyTemplate = nsslowkey_ECPrivateKeyTemplate; |
6382 | 0 | paramTemplate = NULL; |
6383 | 0 | paramDest = &(lpk->u.ec.ecParams.DEREncoding); |
6384 | 0 | lpk->keyType = NSSLOWKEYECKey; |
6385 | 0 | prepare_low_ec_priv_key_for_asn1(lpk); |
6386 | 0 | prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); |
6387 | 0 | break; |
6388 | 0 | default: |
6389 | 0 | keyTemplate = NULL; |
6390 | 0 | paramTemplate = NULL; |
6391 | 0 | paramDest = NULL; |
6392 | 0 | break; |
6393 | 0 | } |
6394 | | |
6395 | 0 | if (!keyTemplate) { |
6396 | 0 | goto loser; |
6397 | 0 | } |
6398 | | |
6399 | | /* decode the private key and any algorithm parameters */ |
6400 | 0 | rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); |
6401 | |
|
6402 | 0 | if (lpk->keyType == NSSLOWKEYECKey) { |
6403 | | /* convert length in bits to length in bytes */ |
6404 | 0 | lpk->u.ec.publicValue.len >>= 3; |
6405 | 0 | rv = SECITEM_CopyItem(arena, |
6406 | 0 | &(lpk->u.ec.ecParams.DEREncoding), |
6407 | 0 | &(pki->algorithm.parameters)); |
6408 | 0 | if (rv != SECSuccess) { |
6409 | 0 | goto loser; |
6410 | 0 | } |
6411 | 0 | } |
6412 | | |
6413 | 0 | if (rv != SECSuccess) { |
6414 | 0 | goto loser; |
6415 | 0 | } |
6416 | 0 | if (paramDest && paramTemplate) { |
6417 | 0 | rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate, |
6418 | 0 | &(pki->algorithm.parameters)); |
6419 | 0 | if (rv != SECSuccess) { |
6420 | 0 | goto loser; |
6421 | 0 | } |
6422 | 0 | } |
6423 | | |
6424 | 0 | rv = SECFailure; |
6425 | |
|
6426 | 0 | switch (lpk->keyType) { |
6427 | 0 | case NSSLOWKEYRSAKey: |
6428 | 0 | keyType = CKK_RSA; |
6429 | 0 | if (sftk_hasAttribute(key, CKA_NSS_DB)) { |
6430 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_DB); |
6431 | 0 | } |
6432 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
6433 | 0 | sizeof(keyType)); |
6434 | 0 | if (crv != CKR_OK) |
6435 | 0 | break; |
6436 | 0 | crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue, |
6437 | 0 | sizeof(CK_BBOOL)); |
6438 | 0 | if (crv != CKR_OK) |
6439 | 0 | break; |
6440 | 0 | crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue, |
6441 | 0 | sizeof(CK_BBOOL)); |
6442 | 0 | if (crv != CKR_OK) |
6443 | 0 | break; |
6444 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
6445 | 0 | sizeof(CK_BBOOL)); |
6446 | 0 | if (crv != CKR_OK) |
6447 | 0 | break; |
6448 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
6449 | 0 | sizeof(CK_BBOOL)); |
6450 | 0 | if (crv != CKR_OK) |
6451 | 0 | break; |
6452 | 0 | crv = sftk_AddAttributeType(key, CKA_MODULUS, |
6453 | 0 | sftk_item_expand(&lpk->u.rsa.modulus)); |
6454 | 0 | if (crv != CKR_OK) |
6455 | 0 | break; |
6456 | 0 | crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT, |
6457 | 0 | sftk_item_expand(&lpk->u.rsa.publicExponent)); |
6458 | 0 | if (crv != CKR_OK) |
6459 | 0 | break; |
6460 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT, |
6461 | 0 | sftk_item_expand(&lpk->u.rsa.privateExponent)); |
6462 | 0 | if (crv != CKR_OK) |
6463 | 0 | break; |
6464 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME_1, |
6465 | 0 | sftk_item_expand(&lpk->u.rsa.prime1)); |
6466 | 0 | if (crv != CKR_OK) |
6467 | 0 | break; |
6468 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME_2, |
6469 | 0 | sftk_item_expand(&lpk->u.rsa.prime2)); |
6470 | 0 | if (crv != CKR_OK) |
6471 | 0 | break; |
6472 | 0 | crv = sftk_AddAttributeType(key, CKA_EXPONENT_1, |
6473 | 0 | sftk_item_expand(&lpk->u.rsa.exponent1)); |
6474 | 0 | if (crv != CKR_OK) |
6475 | 0 | break; |
6476 | 0 | crv = sftk_AddAttributeType(key, CKA_EXPONENT_2, |
6477 | 0 | sftk_item_expand(&lpk->u.rsa.exponent2)); |
6478 | 0 | if (crv != CKR_OK) |
6479 | 0 | break; |
6480 | 0 | crv = sftk_AddAttributeType(key, CKA_COEFFICIENT, |
6481 | 0 | sftk_item_expand(&lpk->u.rsa.coefficient)); |
6482 | 0 | break; |
6483 | 0 | case NSSLOWKEYDSAKey: |
6484 | 0 | keyType = CKK_DSA; |
6485 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
6486 | 0 | if (crv != CKR_OK) |
6487 | 0 | break; |
6488 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
6489 | 0 | sizeof(keyType)); |
6490 | 0 | if (crv != CKR_OK) |
6491 | 0 | break; |
6492 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
6493 | 0 | sizeof(CK_BBOOL)); |
6494 | 0 | if (crv != CKR_OK) |
6495 | 0 | break; |
6496 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
6497 | 0 | sizeof(CK_BBOOL)); |
6498 | 0 | if (crv != CKR_OK) |
6499 | 0 | break; |
6500 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME, |
6501 | 0 | sftk_item_expand(&lpk->u.dsa.params.prime)); |
6502 | 0 | if (crv != CKR_OK) |
6503 | 0 | break; |
6504 | 0 | crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
6505 | 0 | sftk_item_expand(&lpk->u.dsa.params.subPrime)); |
6506 | 0 | if (crv != CKR_OK) |
6507 | 0 | break; |
6508 | 0 | crv = sftk_AddAttributeType(key, CKA_BASE, |
6509 | 0 | sftk_item_expand(&lpk->u.dsa.params.base)); |
6510 | 0 | if (crv != CKR_OK) |
6511 | 0 | break; |
6512 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
6513 | 0 | sftk_item_expand(&lpk->u.dsa.privateValue)); |
6514 | 0 | if (crv != CKR_OK) |
6515 | 0 | break; |
6516 | 0 | break; |
6517 | | #ifdef notdef |
6518 | | case NSSLOWKEYDHKey: |
6519 | | template = dhTemplate; |
6520 | | templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE); |
6521 | | keyType = CKK_DH; |
6522 | | break; |
6523 | | #endif |
6524 | | /* what about fortezza??? */ |
6525 | 0 | case NSSLOWKEYECKey: |
6526 | 0 | keyType = CKK_EC; |
6527 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
6528 | 0 | if (crv != CKR_OK) |
6529 | 0 | break; |
6530 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
6531 | 0 | sizeof(keyType)); |
6532 | 0 | if (crv != CKR_OK) |
6533 | 0 | break; |
6534 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
6535 | 0 | sizeof(CK_BBOOL)); |
6536 | 0 | if (crv != CKR_OK) |
6537 | 0 | break; |
6538 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
6539 | 0 | sizeof(CK_BBOOL)); |
6540 | 0 | if (crv != CKR_OK) |
6541 | 0 | break; |
6542 | 0 | crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue, |
6543 | 0 | sizeof(CK_BBOOL)); |
6544 | 0 | if (crv != CKR_OK) |
6545 | 0 | break; |
6546 | 0 | crv = sftk_AddAttributeType(key, CKA_EC_PARAMS, |
6547 | 0 | sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding)); |
6548 | 0 | if (crv != CKR_OK) |
6549 | 0 | break; |
6550 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
6551 | 0 | sftk_item_expand(&lpk->u.ec.privateValue)); |
6552 | 0 | if (crv != CKR_OK) |
6553 | 0 | break; |
6554 | | /* XXX Do we need to decode the EC Params here ?? */ |
6555 | 0 | break; |
6556 | 0 | default: |
6557 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
6558 | 0 | break; |
6559 | 0 | } |
6560 | | |
6561 | 0 | if (crv != CKR_OK) { |
6562 | 0 | goto loser; |
6563 | 0 | } |
6564 | | |
6565 | | /* For RSA-PSS, record the original algorithm parameters so |
6566 | | * they can be encrypted altoghether when wrapping */ |
6567 | 0 | if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { |
6568 | 0 | NSSLOWKEYSubjectPublicKeyInfo spki; |
6569 | 0 | NSSLOWKEYPublicKey pubk; |
6570 | 0 | SECItem *publicKeyInfo; |
6571 | |
|
6572 | 0 | memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo)); |
6573 | 0 | rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm); |
6574 | 0 | if (rv != SECSuccess) { |
6575 | 0 | crv = CKR_HOST_MEMORY; |
6576 | 0 | goto loser; |
6577 | 0 | } |
6578 | | |
6579 | 0 | prepare_low_rsa_pub_key_for_asn1(&pubk); |
6580 | |
|
6581 | 0 | rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus); |
6582 | 0 | if (rv != SECSuccess) { |
6583 | 0 | crv = CKR_HOST_MEMORY; |
6584 | 0 | goto loser; |
6585 | 0 | } |
6586 | 0 | rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent); |
6587 | 0 | if (rv != SECSuccess) { |
6588 | 0 | crv = CKR_HOST_MEMORY; |
6589 | 0 | goto loser; |
6590 | 0 | } |
6591 | | |
6592 | 0 | if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey, |
6593 | 0 | &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) { |
6594 | 0 | crv = CKR_HOST_MEMORY; |
6595 | 0 | goto loser; |
6596 | 0 | } |
6597 | | |
6598 | 0 | publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL, |
6599 | 0 | &spki, nsslowkey_SubjectPublicKeyInfoTemplate); |
6600 | 0 | if (!publicKeyInfo) { |
6601 | 0 | crv = CKR_HOST_MEMORY; |
6602 | 0 | goto loser; |
6603 | 0 | } |
6604 | 0 | crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO, |
6605 | 0 | sftk_item_expand(publicKeyInfo)); |
6606 | 0 | } |
6607 | | |
6608 | 0 | loser: |
6609 | 0 | if (lpk) { |
6610 | 0 | nsslowkey_DestroyPrivateKey(lpk); |
6611 | 0 | } |
6612 | |
|
6613 | 0 | if (crv != CKR_OK) { |
6614 | 0 | return SECFailure; |
6615 | 0 | } |
6616 | | |
6617 | 0 | return SECSuccess; |
6618 | 0 | } |
6619 | | |
6620 | | /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */ |
6621 | | CK_RV |
6622 | | NSC_UnwrapKey(CK_SESSION_HANDLE hSession, |
6623 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, |
6624 | | CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, |
6625 | | CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
6626 | | CK_OBJECT_HANDLE_PTR phKey) |
6627 | 27 | { |
6628 | 27 | SFTKObject *key = NULL; |
6629 | 27 | SFTKSession *session; |
6630 | 27 | CK_ULONG key_length = 0; |
6631 | 27 | unsigned char *buf = NULL; |
6632 | 27 | CK_RV crv = CKR_OK; |
6633 | 27 | int i; |
6634 | 27 | CK_ULONG bsize = ulWrappedKeyLen; |
6635 | 27 | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
6636 | 27 | SECItem bpki; |
6637 | 27 | CK_OBJECT_CLASS target_type = CKO_SECRET_KEY; |
6638 | | |
6639 | 27 | CHECK_FORK(); |
6640 | | |
6641 | 27 | if (!slot) { |
6642 | 0 | return CKR_SESSION_HANDLE_INVALID; |
6643 | 0 | } |
6644 | | /* |
6645 | | * now lets create an object to hang the attributes off of |
6646 | | */ |
6647 | 27 | key = sftk_NewObject(slot); /* fill in the handle later */ |
6648 | 27 | if (key == NULL) { |
6649 | 0 | return CKR_HOST_MEMORY; |
6650 | 0 | } |
6651 | | |
6652 | | /* |
6653 | | * load the template values into the object |
6654 | | */ |
6655 | 108 | for (i = 0; i < (int)ulAttributeCount; i++) { |
6656 | 81 | if (pTemplate[i].type == CKA_VALUE_LEN) { |
6657 | 0 | key_length = *(CK_ULONG *)pTemplate[i].pValue; |
6658 | 0 | continue; |
6659 | 0 | } |
6660 | 81 | if (pTemplate[i].type == CKA_CLASS) { |
6661 | 27 | target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; |
6662 | 27 | } |
6663 | 81 | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
6664 | 81 | if (crv != CKR_OK) |
6665 | 0 | break; |
6666 | 81 | } |
6667 | 27 | if (crv != CKR_OK) { |
6668 | 0 | sftk_FreeObject(key); |
6669 | 0 | return crv; |
6670 | 0 | } |
6671 | | |
6672 | 27 | crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP, |
6673 | 27 | CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE); |
6674 | 27 | if (crv != CKR_OK) { |
6675 | 0 | sftk_FreeObject(key); |
6676 | 0 | return sftk_mapWrap(crv); |
6677 | 0 | } |
6678 | | |
6679 | | /* allocate the buffer to decrypt into |
6680 | | * this assumes the unwrapped key is never larger than the |
6681 | | * wrapped key. For all the mechanisms we support this is true */ |
6682 | 27 | buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen); |
6683 | 27 | bsize = ulWrappedKeyLen; |
6684 | | |
6685 | 27 | crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize); |
6686 | 27 | if (crv != CKR_OK) { |
6687 | 20 | sftk_FreeObject(key); |
6688 | 20 | PORT_Free(buf); |
6689 | 20 | return sftk_mapWrap(crv); |
6690 | 20 | } |
6691 | | |
6692 | 7 | switch (target_type) { |
6693 | 7 | case CKO_SECRET_KEY: |
6694 | 7 | if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) { |
6695 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6696 | 0 | break; |
6697 | 0 | } |
6698 | | |
6699 | 7 | if (key_length == 0 || key_length > bsize) { |
6700 | 7 | key_length = bsize; |
6701 | 7 | } |
6702 | 7 | if (key_length > MAX_KEY_LEN) { |
6703 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
6704 | 0 | break; |
6705 | 0 | } |
6706 | | |
6707 | | /* add the value */ |
6708 | 7 | crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); |
6709 | 7 | break; |
6710 | 0 | case CKO_PRIVATE_KEY: |
6711 | 0 | bpki.data = (unsigned char *)buf; |
6712 | 0 | bpki.len = bsize; |
6713 | 0 | crv = CKR_OK; |
6714 | 0 | if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) { |
6715 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6716 | 0 | } |
6717 | 0 | break; |
6718 | 0 | default: |
6719 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
6720 | 0 | break; |
6721 | 7 | } |
6722 | | |
6723 | 7 | PORT_ZFree(buf, bsize); |
6724 | 7 | if (crv != CKR_OK) { |
6725 | 0 | sftk_FreeObject(key); |
6726 | 0 | return crv; |
6727 | 0 | } |
6728 | | |
6729 | | /* get the session */ |
6730 | 7 | session = sftk_SessionFromHandle(hSession); |
6731 | 7 | if (session == NULL) { |
6732 | 0 | sftk_FreeObject(key); |
6733 | 0 | return CKR_SESSION_HANDLE_INVALID; |
6734 | 0 | } |
6735 | | |
6736 | | /* mark the key as FIPS if the previous operation was all FIPS */ |
6737 | 7 | key->isFIPS = session->lastOpWasFIPS; |
6738 | | |
6739 | | /* |
6740 | | * handle the base object stuff |
6741 | | */ |
6742 | 7 | crv = sftk_handleObject(key, session); |
6743 | 7 | *phKey = key->handle; |
6744 | 7 | sftk_FreeSession(session); |
6745 | 7 | sftk_FreeObject(key); |
6746 | | |
6747 | 7 | return crv; |
6748 | 7 | } |
6749 | | |
6750 | | /* |
6751 | | * The SSL key gen mechanism create's lots of keys. This function handles the |
6752 | | * details of each of these key creation. |
6753 | | */ |
6754 | | static CK_RV |
6755 | | sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, |
6756 | | PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize, |
6757 | | CK_OBJECT_HANDLE *keyHandle) |
6758 | 25.4k | { |
6759 | 25.4k | SFTKObject *key; |
6760 | 25.4k | SFTKSession *session; |
6761 | 25.4k | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
6762 | 25.4k | CK_BBOOL cktrue = CK_TRUE; |
6763 | 25.4k | CK_BBOOL ckfalse = CK_FALSE; |
6764 | 25.4k | CK_RV crv = CKR_HOST_MEMORY; |
6765 | | |
6766 | | /* |
6767 | | * now lets create an object to hang the attributes off of |
6768 | | */ |
6769 | 25.4k | *keyHandle = CK_INVALID_HANDLE; |
6770 | 25.4k | key = sftk_NewObject(baseKey->slot); |
6771 | 25.4k | if (key == NULL) |
6772 | 0 | return CKR_HOST_MEMORY; |
6773 | 25.4k | sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE; |
6774 | | |
6775 | 25.4k | crv = sftk_CopyObject(key, baseKey); |
6776 | 25.4k | if (crv != CKR_OK) |
6777 | 0 | goto loser; |
6778 | 25.4k | if (isMacKey) { |
6779 | 13.8k | crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
6780 | 13.8k | if (crv != CKR_OK) |
6781 | 0 | goto loser; |
6782 | 13.8k | crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); |
6783 | 13.8k | if (crv != CKR_OK) |
6784 | 0 | goto loser; |
6785 | 13.8k | crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL)); |
6786 | 13.8k | if (crv != CKR_OK) |
6787 | 0 | goto loser; |
6788 | 13.8k | crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL)); |
6789 | 13.8k | if (crv != CKR_OK) |
6790 | 0 | goto loser; |
6791 | 13.8k | crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); |
6792 | 13.8k | if (crv != CKR_OK) |
6793 | 0 | goto loser; |
6794 | 13.8k | crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); |
6795 | 13.8k | if (crv != CKR_OK) |
6796 | 0 | goto loser; |
6797 | 13.8k | crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL)); |
6798 | 13.8k | if (crv != CKR_OK) |
6799 | 0 | goto loser; |
6800 | 13.8k | crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL)); |
6801 | 13.8k | if (crv != CKR_OK) |
6802 | 0 | goto loser; |
6803 | 13.8k | } |
6804 | 25.4k | crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize); |
6805 | 25.4k | if (crv != CKR_OK) |
6806 | 0 | goto loser; |
6807 | | |
6808 | | /* get the session */ |
6809 | 25.4k | crv = CKR_HOST_MEMORY; |
6810 | 25.4k | session = sftk_SessionFromHandle(hSession); |
6811 | 25.4k | if (session == NULL) { |
6812 | 0 | goto loser; |
6813 | 0 | } |
6814 | | |
6815 | 25.4k | crv = sftk_handleObject(key, session); |
6816 | 25.4k | sftk_FreeSession(session); |
6817 | 25.4k | *keyHandle = key->handle; |
6818 | 25.4k | loser: |
6819 | 25.4k | if (key) |
6820 | 25.4k | sftk_FreeObject(key); |
6821 | 25.4k | return crv; |
6822 | 25.4k | } |
6823 | | |
6824 | | /* |
6825 | | * if there is an error, we need to free the keys we already created in SSL |
6826 | | * This is the routine that will do it.. |
6827 | | */ |
6828 | | static void |
6829 | | sftk_freeSSLKeys(CK_SESSION_HANDLE session, |
6830 | | CK_SSL3_KEY_MAT_OUT *returnedMaterial) |
6831 | 0 | { |
6832 | 0 | if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { |
6833 | 0 | NSC_DestroyObject(session, returnedMaterial->hClientMacSecret); |
6834 | 0 | } |
6835 | 0 | if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { |
6836 | 0 | NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); |
6837 | 0 | } |
6838 | 0 | if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { |
6839 | 0 | NSC_DestroyObject(session, returnedMaterial->hClientKey); |
6840 | 0 | } |
6841 | 0 | if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { |
6842 | 0 | NSC_DestroyObject(session, returnedMaterial->hServerKey); |
6843 | 0 | } |
6844 | 0 | } |
6845 | | |
6846 | | /* |
6847 | | * when deriving from sensitive and extractable keys, we need to preserve some |
6848 | | * of the semantics in the derived key. This helper routine maintains these |
6849 | | * semantics. |
6850 | | */ |
6851 | | static CK_RV |
6852 | | sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey, |
6853 | | PRBool canBeData) |
6854 | 28.2k | { |
6855 | 28.2k | PRBool hasSensitive; |
6856 | 28.2k | PRBool sensitive = PR_FALSE; |
6857 | 28.2k | CK_BBOOL bFalse = CK_FALSE; |
6858 | 28.2k | PRBool hasExtractable; |
6859 | 28.2k | PRBool extractable = PR_TRUE; |
6860 | 28.2k | CK_BBOOL bTrue = CK_TRUE; |
6861 | 28.2k | CK_RV crv = CKR_OK; |
6862 | 28.2k | SFTKAttribute *att; |
6863 | 28.2k | PRBool isData = PR_TRUE; |
6864 | | |
6865 | 28.2k | if (canBeData) { |
6866 | 21.3k | CK_OBJECT_CLASS objClass; |
6867 | | |
6868 | | /* if the target key is actually data, don't set the unexpected |
6869 | | * attributes */ |
6870 | 21.3k | crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass); |
6871 | 21.3k | if (crv != CKR_OK) { |
6872 | 0 | return crv; |
6873 | 0 | } |
6874 | 21.3k | if (objClass == CKO_DATA) { |
6875 | 3.29k | return CKR_OK; |
6876 | 3.29k | } |
6877 | | |
6878 | | /* if the base key is data, it doesn't have sensitive attributes, |
6879 | | * allow the destKey to get it's own */ |
6880 | 18.0k | crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass); |
6881 | 18.0k | if (crv != CKR_OK) { |
6882 | 0 | return crv; |
6883 | 0 | } |
6884 | 18.0k | if (objClass == CKO_DATA) { |
6885 | 3.36k | isData = PR_TRUE; |
6886 | 3.36k | } |
6887 | 18.0k | } |
6888 | | |
6889 | 24.9k | hasSensitive = PR_FALSE; |
6890 | 24.9k | att = sftk_FindAttribute(destKey, CKA_SENSITIVE); |
6891 | 24.9k | if (att) { |
6892 | 0 | hasSensitive = PR_TRUE; |
6893 | 0 | sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue; |
6894 | 0 | sftk_FreeAttribute(att); |
6895 | 0 | } |
6896 | | |
6897 | 24.9k | hasExtractable = PR_FALSE; |
6898 | 24.9k | att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE); |
6899 | 24.9k | if (att) { |
6900 | 0 | hasExtractable = PR_TRUE; |
6901 | 0 | extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue; |
6902 | 0 | sftk_FreeAttribute(att); |
6903 | 0 | } |
6904 | | |
6905 | | /* don't make a key more accessible */ |
6906 | 24.9k | if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive && |
6907 | 24.9k | (sensitive == PR_FALSE)) { |
6908 | 0 | return CKR_KEY_FUNCTION_NOT_PERMITTED; |
6909 | 0 | } |
6910 | 24.9k | if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable && |
6911 | 24.9k | (extractable == PR_TRUE)) { |
6912 | 0 | return CKR_KEY_FUNCTION_NOT_PERMITTED; |
6913 | 0 | } |
6914 | | |
6915 | | /* inherit parent's sensitivity */ |
6916 | 24.9k | if (!hasSensitive) { |
6917 | 24.9k | att = sftk_FindAttribute(baseKey, CKA_SENSITIVE); |
6918 | 24.9k | if (att != NULL) { |
6919 | 21.5k | crv = sftk_defaultAttribute(destKey, |
6920 | 21.5k | sftk_attr_expand(&att->attrib)); |
6921 | 21.5k | sftk_FreeAttribute(att); |
6922 | 21.5k | } else if (isData) { |
6923 | 3.36k | crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE, |
6924 | 3.36k | &bFalse, sizeof(bFalse)); |
6925 | 3.36k | } else { |
6926 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
6927 | 0 | } |
6928 | 24.9k | if (crv != CKR_OK) |
6929 | 0 | return crv; |
6930 | 24.9k | } |
6931 | 24.9k | if (!hasExtractable) { |
6932 | 24.9k | att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE); |
6933 | 24.9k | if (att != NULL) { |
6934 | 21.5k | crv = sftk_defaultAttribute(destKey, |
6935 | 21.5k | sftk_attr_expand(&att->attrib)); |
6936 | 21.5k | sftk_FreeAttribute(att); |
6937 | 21.5k | } else if (isData) { |
6938 | 3.36k | crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE, |
6939 | 3.36k | &bTrue, sizeof(bTrue)); |
6940 | 3.36k | } else { |
6941 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
6942 | 0 | } |
6943 | 24.9k | if (crv != CKR_OK) |
6944 | 0 | return crv; |
6945 | 24.9k | } |
6946 | | |
6947 | | /* we should inherit the parent's always extractable/ never sensitive info, |
6948 | | * but handleObject always forces this attributes, so we would need to do |
6949 | | * something special. */ |
6950 | 24.9k | return CKR_OK; |
6951 | 24.9k | } |
6952 | | |
6953 | | /* |
6954 | | * make known fixed PKCS #11 key types to their sizes in bytes |
6955 | | */ |
6956 | | unsigned long |
6957 | | sftk_MapKeySize(CK_KEY_TYPE keyType) |
6958 | 15.3k | { |
6959 | 15.3k | switch (keyType) { |
6960 | 0 | case CKK_CDMF: |
6961 | 0 | return 8; |
6962 | 356 | case CKK_DES: |
6963 | 356 | return 8; |
6964 | 0 | case CKK_DES2: |
6965 | 0 | return 16; |
6966 | 1.89k | case CKK_DES3: |
6967 | 1.89k | return 24; |
6968 | | /* IDEA and CAST need to be added */ |
6969 | 13.1k | default: |
6970 | 13.1k | break; |
6971 | 15.3k | } |
6972 | 13.1k | return 0; |
6973 | 15.3k | } |
6974 | | |
6975 | | /* Inputs: |
6976 | | * key_len: Length of derived key to be generated. |
6977 | | * SharedSecret: a shared secret that is the output of a key agreement primitive. |
6978 | | * SharedInfo: (Optional) some data shared by the entities computing the secret key. |
6979 | | * SharedInfoLen: the length in octets of SharedInfo |
6980 | | * Hash: The hash function to be used in the KDF |
6981 | | * HashLen: the length in octets of the output of Hash |
6982 | | * Output: |
6983 | | * key: Pointer to a buffer containing derived key, if return value is SECSuccess. |
6984 | | */ |
6985 | | static CK_RV |
6986 | | sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret, |
6987 | | CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
6988 | | SECStatus Hash(unsigned char *, const unsigned char *, PRUint32), |
6989 | | CK_ULONG HashLen) |
6990 | 0 | { |
6991 | 0 | unsigned char *buffer = NULL, *output_buffer = NULL; |
6992 | 0 | PRUint32 buffer_len, max_counter, i; |
6993 | 0 | SECStatus rv; |
6994 | 0 | CK_RV crv; |
6995 | | |
6996 | | /* Check that key_len isn't too long. The maximum key length could be |
6997 | | * greatly increased if the code below did not limit the 4-byte counter |
6998 | | * to a maximum value of 255. */ |
6999 | 0 | if (key_len > 254 * HashLen) |
7000 | 0 | return CKR_ARGUMENTS_BAD; |
7001 | | |
7002 | 0 | if (SharedInfo == NULL) |
7003 | 0 | SharedInfoLen = 0; |
7004 | |
|
7005 | 0 | buffer_len = SharedSecret->len + 4 + SharedInfoLen; |
7006 | 0 | buffer = (CK_BYTE *)PORT_Alloc(buffer_len); |
7007 | 0 | if (buffer == NULL) { |
7008 | 0 | crv = CKR_HOST_MEMORY; |
7009 | 0 | goto loser; |
7010 | 0 | } |
7011 | | |
7012 | 0 | max_counter = key_len / HashLen; |
7013 | 0 | if (key_len > max_counter * HashLen) |
7014 | 0 | max_counter++; |
7015 | |
|
7016 | 0 | output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen); |
7017 | 0 | if (output_buffer == NULL) { |
7018 | 0 | crv = CKR_HOST_MEMORY; |
7019 | 0 | goto loser; |
7020 | 0 | } |
7021 | | |
7022 | | /* Populate buffer with SharedSecret || Counter || [SharedInfo] |
7023 | | * where Counter is 0x00000001 */ |
7024 | 0 | PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len); |
7025 | 0 | buffer[SharedSecret->len] = 0; |
7026 | 0 | buffer[SharedSecret->len + 1] = 0; |
7027 | 0 | buffer[SharedSecret->len + 2] = 0; |
7028 | 0 | buffer[SharedSecret->len + 3] = 1; |
7029 | 0 | if (SharedInfo) { |
7030 | 0 | PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen); |
7031 | 0 | } |
7032 | |
|
7033 | 0 | for (i = 0; i < max_counter; i++) { |
7034 | 0 | rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len); |
7035 | 0 | if (rv != SECSuccess) { |
7036 | | /* 'Hash' should not fail. */ |
7037 | 0 | crv = CKR_FUNCTION_FAILED; |
7038 | 0 | goto loser; |
7039 | 0 | } |
7040 | | |
7041 | | /* Increment counter (assumes max_counter < 255) */ |
7042 | 0 | buffer[SharedSecret->len + 3]++; |
7043 | 0 | } |
7044 | | |
7045 | 0 | PORT_ZFree(buffer, buffer_len); |
7046 | 0 | if (key_len < max_counter * HashLen) { |
7047 | 0 | PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len); |
7048 | 0 | } |
7049 | 0 | *key = output_buffer; |
7050 | |
|
7051 | 0 | return CKR_OK; |
7052 | | |
7053 | 0 | loser: |
7054 | 0 | if (buffer) { |
7055 | 0 | PORT_ZFree(buffer, buffer_len); |
7056 | 0 | } |
7057 | 0 | if (output_buffer) { |
7058 | 0 | PORT_ZFree(output_buffer, max_counter * HashLen); |
7059 | 0 | } |
7060 | 0 | return crv; |
7061 | 0 | } |
7062 | | |
7063 | | static CK_RV |
7064 | | sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, |
7065 | | SECItem *SharedSecret, |
7066 | | CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
7067 | | CK_EC_KDF_TYPE kdf) |
7068 | 0 | { |
7069 | 0 | if (kdf == CKD_SHA1_KDF) |
7070 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7071 | 0 | SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH); |
7072 | 0 | else if (kdf == CKD_SHA224_KDF) |
7073 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7074 | 0 | SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH); |
7075 | 0 | else if (kdf == CKD_SHA256_KDF) |
7076 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7077 | 0 | SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH); |
7078 | 0 | else if (kdf == CKD_SHA384_KDF) |
7079 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7080 | 0 | SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH); |
7081 | 0 | else if (kdf == CKD_SHA512_KDF) |
7082 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7083 | 0 | SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH); |
7084 | 0 | else |
7085 | 0 | return CKR_MECHANISM_INVALID; |
7086 | 0 | } |
7087 | | |
7088 | | /* |
7089 | | * Handle the derive from a block encryption cipher |
7090 | | */ |
7091 | | CK_RV |
7092 | | sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo, |
7093 | | int blockSize, SFTKObject *key, CK_ULONG keySize, |
7094 | | unsigned char *data, CK_ULONG len) |
7095 | 0 | { |
7096 | | /* large enough for a 512-bit key */ |
7097 | 0 | unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE]; |
7098 | 0 | SECStatus rv; |
7099 | 0 | unsigned int outLen; |
7100 | 0 | CK_RV crv; |
7101 | |
|
7102 | 0 | if ((len % blockSize) != 0) { |
7103 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7104 | 0 | } |
7105 | 0 | if (len > SFTK_MAX_DERIVE_KEY_SIZE) { |
7106 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7107 | 0 | } |
7108 | 0 | if (keySize && (len < keySize)) { |
7109 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7110 | 0 | } |
7111 | 0 | if (keySize == 0) { |
7112 | 0 | keySize = len; |
7113 | 0 | } |
7114 | |
|
7115 | 0 | rv = (*encrypt)(cipherInfo, &tmpdata, &outLen, len, data, len); |
7116 | 0 | if (rv != SECSuccess) { |
7117 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
7118 | 0 | return crv; |
7119 | 0 | } |
7120 | | |
7121 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize); |
7122 | 0 | PORT_Memset(tmpdata, 0, sizeof tmpdata); |
7123 | 0 | return crv; |
7124 | 0 | } |
7125 | | |
7126 | | CK_RV |
7127 | | sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession, |
7128 | | SFTKObject *sourceKey, const unsigned char *sourceKeyBytes, |
7129 | | int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes, |
7130 | | int keySize, PRBool canBeData, PRBool isFIPS) |
7131 | 21.3k | { |
7132 | 21.3k | SFTKSession *session; |
7133 | 21.3k | SFTKAttribute *saltKey_att = NULL; |
7134 | 21.3k | const SECHashObject *rawHash; |
7135 | 21.3k | unsigned hashLen; |
7136 | 21.3k | unsigned genLen = 0; |
7137 | 21.3k | unsigned char hashbuf[HASH_LENGTH_MAX]; |
7138 | 21.3k | unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH]; |
7139 | 21.3k | unsigned char *keyBlockAlloc = NULL; /* allocated keyBlock */ |
7140 | 21.3k | unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */ |
7141 | 21.3k | const unsigned char *prk; /* psuedo-random key */ |
7142 | 21.3k | CK_ULONG prkLen; |
7143 | 21.3k | const unsigned char *okm; /* output keying material */ |
7144 | 21.3k | HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism); |
7145 | 21.3k | SFTKObject *saltKey = NULL; |
7146 | 21.3k | CK_RV crv = CKR_OK; |
7147 | | |
7148 | | /* Spec says it should be the base hash, but also accept the HMAC */ |
7149 | 21.3k | if (hashType == HASH_AlgNULL) { |
7150 | 0 | hashType = sftk_HMACMechanismToHash(params->prfHashMechanism); |
7151 | 0 | } |
7152 | 21.3k | rawHash = HASH_GetRawHashObject(hashType); |
7153 | 21.3k | if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) { |
7154 | 0 | return CKR_MECHANISM_INVALID; |
7155 | 0 | } |
7156 | 21.3k | hashLen = rawHash->length; |
7157 | | |
7158 | 21.3k | if ((!params->bExpand && !params->bExtract) || |
7159 | 21.3k | (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) || |
7160 | 21.3k | (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) { |
7161 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7162 | 0 | } |
7163 | 21.3k | if ((params->bExpand && keySize == 0) || |
7164 | 21.3k | (!params->bExpand && keySize > hashLen) || |
7165 | 21.3k | (params->bExpand && keySize > 255 * hashLen)) { |
7166 | 0 | return CKR_TEMPLATE_INCONSISTENT; |
7167 | 0 | } |
7168 | | |
7169 | | /* sourceKey is NULL if we are called from the POST, skip the |
7170 | | * sensitiveCheck */ |
7171 | 21.3k | if (sourceKey != NULL) { |
7172 | 21.3k | crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData); |
7173 | 21.3k | if (crv != CKR_OK) |
7174 | 0 | return crv; |
7175 | 21.3k | } |
7176 | | |
7177 | | /* HKDF-Extract(salt, base key value) */ |
7178 | 21.3k | if (params->bExtract) { |
7179 | 5.04k | CK_BYTE *salt; |
7180 | 5.04k | CK_ULONG saltLen; |
7181 | 5.04k | HMACContext *hmac; |
7182 | 5.04k | unsigned int bufLen; |
7183 | | |
7184 | 5.04k | switch (params->ulSaltType) { |
7185 | 1.68k | case CKF_HKDF_SALT_NULL: |
7186 | 1.68k | saltLen = hashLen; |
7187 | 1.68k | salt = hashbuf; |
7188 | 1.68k | memset(salt, 0, saltLen); |
7189 | 1.68k | break; |
7190 | 0 | case CKF_HKDF_SALT_DATA: |
7191 | 0 | salt = params->pSalt; |
7192 | 0 | saltLen = params->ulSaltLen; |
7193 | 0 | if ((salt == NULL) || (params->ulSaltLen == 0)) { |
7194 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7195 | 0 | } |
7196 | 0 | break; |
7197 | 3.36k | case CKF_HKDF_SALT_KEY: |
7198 | | /* lookup key */ |
7199 | 3.36k | session = sftk_SessionFromHandle(hSession); |
7200 | 3.36k | if (session == NULL) { |
7201 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7202 | 0 | } |
7203 | | |
7204 | 3.36k | saltKey = sftk_ObjectFromHandle(params->hSaltKey, session); |
7205 | 3.36k | sftk_FreeSession(session); |
7206 | 3.36k | if (saltKey == NULL) { |
7207 | 0 | return CKR_KEY_HANDLE_INVALID; |
7208 | 0 | } |
7209 | | /* if the base key is not fips, but the salt key is, the |
7210 | | * resulting key can be fips */ |
7211 | 3.36k | if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) { |
7212 | 0 | CK_MECHANISM mech; |
7213 | 0 | mech.mechanism = CKM_HKDF_DERIVE; |
7214 | 0 | mech.pParameter = params; |
7215 | 0 | mech.ulParameterLen = sizeof(*params); |
7216 | 0 | key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech, |
7217 | 0 | CKA_DERIVE, saltKey); |
7218 | 0 | } |
7219 | 3.36k | saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE); |
7220 | 3.36k | if (saltKey_att == NULL) { |
7221 | 0 | sftk_FreeObject(saltKey); |
7222 | 0 | return CKR_KEY_HANDLE_INVALID; |
7223 | 0 | } |
7224 | | /* save the resulting salt */ |
7225 | 3.36k | salt = saltKey_att->attrib.pValue; |
7226 | 3.36k | saltLen = saltKey_att->attrib.ulValueLen; |
7227 | 3.36k | break; |
7228 | 0 | default: |
7229 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7230 | 0 | break; |
7231 | 5.04k | } |
7232 | | |
7233 | 5.04k | hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); |
7234 | 5.04k | if (saltKey_att) { |
7235 | 3.36k | sftk_FreeAttribute(saltKey_att); |
7236 | 3.36k | } |
7237 | 5.04k | if (saltKey) { |
7238 | 3.36k | sftk_FreeObject(saltKey); |
7239 | 3.36k | } |
7240 | 5.04k | if (!hmac) { |
7241 | 0 | return CKR_HOST_MEMORY; |
7242 | 0 | } |
7243 | 5.04k | HMAC_Begin(hmac); |
7244 | 5.04k | HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen); |
7245 | 5.04k | HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf)); |
7246 | 5.04k | HMAC_Destroy(hmac, PR_TRUE); |
7247 | 5.04k | PORT_Assert(bufLen == rawHash->length); |
7248 | 5.04k | prk = hashbuf; |
7249 | 5.04k | prkLen = bufLen; |
7250 | 16.2k | } else { |
7251 | | /* PRK = base key value */ |
7252 | 16.2k | prk = sourceKeyBytes; |
7253 | 16.2k | prkLen = sourceKeyLen; |
7254 | 16.2k | } |
7255 | | |
7256 | | /* HKDF-Expand */ |
7257 | 21.3k | if (!params->bExpand) { |
7258 | 5.04k | okm = prk; |
7259 | 5.04k | keySize = genLen = hashLen; |
7260 | 16.2k | } else { |
7261 | | /* T(1) = HMAC-Hash(prk, "" | info | 0x01) |
7262 | | * T(n) = HMAC-Hash(prk, T(n-1) | info | n |
7263 | | * key material = T(1) | ... | T(n) |
7264 | | */ |
7265 | 16.2k | HMACContext *hmac; |
7266 | 16.2k | CK_BYTE bi; |
7267 | 16.2k | unsigned iterations; |
7268 | | |
7269 | 16.2k | genLen = PR_ROUNDUP(keySize, hashLen); |
7270 | 16.2k | iterations = genLen / hashLen; |
7271 | | |
7272 | 16.2k | if (genLen > sizeof(keyBlock)) { |
7273 | 0 | keyBlockAlloc = PORT_Alloc(genLen); |
7274 | 0 | if (keyBlockAlloc == NULL) { |
7275 | 0 | return CKR_HOST_MEMORY; |
7276 | 0 | } |
7277 | 0 | keyBlockData = keyBlockAlloc; |
7278 | 0 | } |
7279 | 16.2k | hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); |
7280 | 16.2k | if (hmac == NULL) { |
7281 | 0 | PORT_Free(keyBlockAlloc); |
7282 | 0 | return CKR_HOST_MEMORY; |
7283 | 0 | } |
7284 | 32.5k | for (bi = 1; bi <= iterations && bi > 0; ++bi) { |
7285 | 16.2k | unsigned len; |
7286 | 16.2k | HMAC_Begin(hmac); |
7287 | 16.2k | if (bi > 1) { |
7288 | 0 | HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen); |
7289 | 0 | } |
7290 | 16.2k | if (params->ulInfoLen != 0) { |
7291 | 16.2k | HMAC_Update(hmac, params->pInfo, params->ulInfoLen); |
7292 | 16.2k | } |
7293 | 16.2k | HMAC_Update(hmac, &bi, 1); |
7294 | 16.2k | HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len, |
7295 | 16.2k | hashLen); |
7296 | 16.2k | PORT_Assert(len == hashLen); |
7297 | 16.2k | } |
7298 | 16.2k | HMAC_Destroy(hmac, PR_TRUE); |
7299 | 16.2k | okm = &keyBlockData[0]; |
7300 | 16.2k | } |
7301 | | /* key material = okm */ |
7302 | 21.3k | crv = CKR_OK; |
7303 | 21.3k | if (key) { |
7304 | 21.3k | crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize); |
7305 | 21.3k | } else { |
7306 | 0 | PORT_Assert(outKeyBytes != NULL); |
7307 | 0 | PORT_Memcpy(outKeyBytes, okm, keySize); |
7308 | 0 | } |
7309 | 21.3k | PORT_Memset(keyBlockData, 0, genLen); |
7310 | 21.3k | PORT_Memset(hashbuf, 0, sizeof(hashbuf)); |
7311 | 21.3k | PORT_Free(keyBlockAlloc); |
7312 | 21.3k | return crv; |
7313 | 21.3k | } |
7314 | | |
7315 | | /* |
7316 | | * SSL Key generation given pre master secret |
7317 | | */ |
7318 | 0 | #define NUM_MIXERS 9 |
7319 | | static const char *const mixers[NUM_MIXERS] = { |
7320 | | "A", |
7321 | | "BB", |
7322 | | "CCC", |
7323 | | "DDDD", |
7324 | | "EEEEE", |
7325 | | "FFFFFF", |
7326 | | "GGGGGGG", |
7327 | | "HHHHHHHH", |
7328 | | "IIIIIIIII" |
7329 | | }; |
7330 | 2.78k | #define SSL3_PMS_LENGTH 48 |
7331 | 20.7k | #define SSL3_MASTER_SECRET_LENGTH 48 |
7332 | 55.2k | #define SSL3_RANDOM_LENGTH 32 |
7333 | | |
7334 | | /* NSC_DeriveKey derives a key from a base key, creating a new key object. */ |
7335 | | CK_RV |
7336 | | NSC_DeriveKey(CK_SESSION_HANDLE hSession, |
7337 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, |
7338 | | CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
7339 | | CK_OBJECT_HANDLE_PTR phKey) |
7340 | 84.6k | { |
7341 | 84.6k | SFTKSession *session; |
7342 | 84.6k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
7343 | 84.6k | SFTKObject *key; |
7344 | 84.6k | SFTKObject *sourceKey; |
7345 | 84.6k | SFTKAttribute *att = NULL; |
7346 | 84.6k | SFTKAttribute *att2 = NULL; |
7347 | 84.6k | unsigned char *buf; |
7348 | 84.6k | SHA1Context *sha; |
7349 | 84.6k | MD5Context *md5; |
7350 | 84.6k | MD2Context *md2; |
7351 | 84.6k | CK_ULONG macSize; |
7352 | 84.6k | CK_ULONG tmpKeySize; |
7353 | 84.6k | CK_ULONG IVSize; |
7354 | 84.6k | CK_ULONG keySize = 0; |
7355 | 84.6k | CK_RV crv = CKR_OK; |
7356 | 84.6k | CK_BBOOL cktrue = CK_TRUE; |
7357 | 84.6k | CK_BBOOL ckfalse = CK_FALSE; |
7358 | 84.6k | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
7359 | 84.6k | CK_OBJECT_CLASS classType = CKO_SECRET_KEY; |
7360 | 84.6k | CK_KEY_DERIVATION_STRING_DATA *stringPtr; |
7361 | 84.6k | PRBool isTLS = PR_FALSE; |
7362 | 84.6k | PRBool isDH = PR_FALSE; |
7363 | 84.6k | HASH_HashType tlsPrfHash = HASH_AlgNULL; |
7364 | 84.6k | SECStatus rv; |
7365 | 84.6k | int i; |
7366 | 84.6k | unsigned int outLen; |
7367 | 84.6k | unsigned char sha_out[SHA1_LENGTH]; |
7368 | 84.6k | unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH]; |
7369 | 84.6k | PRBool isFIPS; |
7370 | 84.6k | HASH_HashType hashType; |
7371 | 84.6k | CK_MECHANISM_TYPE hashMech; |
7372 | 84.6k | PRBool extractValue = PR_TRUE; |
7373 | 84.6k | CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS ikeAppB; |
7374 | 84.6k | CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *pIkeAppB; |
7375 | | |
7376 | 84.6k | CHECK_FORK(); |
7377 | | |
7378 | 84.6k | if (!slot) { |
7379 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7380 | 0 | } |
7381 | 84.6k | if (!pMechanism) { |
7382 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7383 | 0 | } |
7384 | 84.6k | CK_MECHANISM_TYPE mechanism = pMechanism->mechanism; |
7385 | | |
7386 | | /* |
7387 | | * now lets create an object to hang the attributes off of |
7388 | | */ |
7389 | 84.6k | if (phKey) |
7390 | 84.6k | *phKey = CK_INVALID_HANDLE; |
7391 | | |
7392 | 84.6k | key = sftk_NewObject(slot); /* fill in the handle later */ |
7393 | 84.6k | if (key == NULL) { |
7394 | 0 | return CKR_HOST_MEMORY; |
7395 | 0 | } |
7396 | 84.6k | isFIPS = sftk_isFIPS(slot->slotID); |
7397 | | |
7398 | | /* |
7399 | | * load the template values into the object |
7400 | | */ |
7401 | 456k | for (i = 0; i < (int)ulAttributeCount; i++) { |
7402 | 372k | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
7403 | 372k | if (crv != CKR_OK) |
7404 | 0 | break; |
7405 | | |
7406 | 372k | if (pTemplate[i].type == CKA_KEY_TYPE) { |
7407 | 84.6k | keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue; |
7408 | 84.6k | } |
7409 | 372k | if (pTemplate[i].type == CKA_VALUE_LEN) { |
7410 | 71.5k | keySize = *(CK_ULONG *)pTemplate[i].pValue; |
7411 | 71.5k | } |
7412 | 372k | } |
7413 | 84.6k | if (crv != CKR_OK) { |
7414 | 0 | sftk_FreeObject(key); |
7415 | 0 | return crv; |
7416 | 0 | } |
7417 | | |
7418 | 84.6k | if (keySize == 0) { |
7419 | 13.1k | keySize = sftk_MapKeySize(keyType); |
7420 | 13.1k | } |
7421 | | |
7422 | 84.6k | switch (mechanism) { |
7423 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ |
7424 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ |
7425 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ |
7426 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA512: |
7427 | 0 | extractValue = PR_FALSE; |
7428 | 0 | classType = CKO_PRIVATE_KEY; |
7429 | 0 | break; |
7430 | 0 | case CKM_NSS_PUB_FROM_PRIV: |
7431 | 0 | extractValue = PR_FALSE; |
7432 | 0 | classType = CKO_PUBLIC_KEY; |
7433 | 0 | break; |
7434 | 3.29k | case CKM_HKDF_DATA: /* fall through */ |
7435 | 3.29k | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
7436 | 3.29k | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
7437 | 3.29k | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: |
7438 | 3.29k | classType = CKO_DATA; |
7439 | 3.29k | break; |
7440 | 0 | case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ |
7441 | 0 | case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ |
7442 | 0 | case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ |
7443 | 0 | case CKM_NSS_JPAKE_FINAL_SHA512: |
7444 | 0 | extractValue = PR_FALSE; |
7445 | | /* fall through */ |
7446 | 81.3k | default: |
7447 | 81.3k | classType = CKO_SECRET_KEY; |
7448 | 84.6k | } |
7449 | | |
7450 | 84.6k | crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType)); |
7451 | 84.6k | if (crv != CKR_OK) { |
7452 | 0 | sftk_FreeObject(key); |
7453 | 0 | return crv; |
7454 | 0 | } |
7455 | | |
7456 | | /* look up the base key we're deriving with */ |
7457 | 84.6k | session = sftk_SessionFromHandle(hSession); |
7458 | 84.6k | if (session == NULL) { |
7459 | 0 | sftk_FreeObject(key); |
7460 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7461 | 0 | } |
7462 | | |
7463 | 84.6k | sourceKey = sftk_ObjectFromHandle(hBaseKey, session); |
7464 | 84.6k | sftk_FreeSession(session); |
7465 | | /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's |
7466 | | * FIPS state below. */ |
7467 | 84.6k | session->lastOpWasFIPS = PR_FALSE; |
7468 | 84.6k | if (sourceKey == NULL) { |
7469 | 0 | sftk_FreeObject(key); |
7470 | 0 | return CKR_KEY_HANDLE_INVALID; |
7471 | 0 | } |
7472 | | |
7473 | 84.6k | if (extractValue) { |
7474 | | /* get the value of the base key */ |
7475 | 84.6k | att = sftk_FindAttribute(sourceKey, CKA_VALUE); |
7476 | 84.6k | if (att == NULL) { |
7477 | 0 | sftk_FreeObject(key); |
7478 | 0 | sftk_FreeObject(sourceKey); |
7479 | 0 | return CKR_KEY_HANDLE_INVALID; |
7480 | 0 | } |
7481 | 84.6k | } |
7482 | 84.6k | key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey); |
7483 | | |
7484 | 84.6k | switch (mechanism) { |
7485 | | /* get a public key from a private key. nsslowkey_ConvertToPublickey() |
7486 | | * will generate the public portion if it doesn't already exist. */ |
7487 | 0 | case CKM_NSS_PUB_FROM_PRIV: { |
7488 | 0 | NSSLOWKEYPrivateKey *privKey; |
7489 | 0 | NSSLOWKEYPublicKey *pubKey; |
7490 | 0 | int error; |
7491 | |
|
7492 | 0 | crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType); |
7493 | 0 | if (crv != CKR_OK) { |
7494 | 0 | break; |
7495 | 0 | } |
7496 | | |
7497 | | /* privKey is stored in sourceKey and will be destroyed when |
7498 | | * the sourceKey is freed. */ |
7499 | 0 | privKey = sftk_GetPrivKey(sourceKey, keyType, &crv); |
7500 | 0 | if (privKey == NULL) { |
7501 | 0 | break; |
7502 | 0 | } |
7503 | 0 | pubKey = nsslowkey_ConvertToPublicKey(privKey); |
7504 | 0 | if (pubKey == NULL) { |
7505 | 0 | error = PORT_GetError(); |
7506 | 0 | crv = sftk_MapCryptError(error); |
7507 | 0 | break; |
7508 | 0 | } |
7509 | 0 | crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey); |
7510 | 0 | nsslowkey_DestroyPublicKey(pubKey); |
7511 | 0 | break; |
7512 | 0 | } |
7513 | 0 | case CKM_NSS_IKE_PRF_DERIVE: |
7514 | 0 | if (pMechanism->ulParameterLen != |
7515 | 0 | sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) { |
7516 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7517 | 0 | break; |
7518 | 0 | } |
7519 | 0 | crv = sftk_ike_prf(hSession, att, |
7520 | 0 | (CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key); |
7521 | 0 | break; |
7522 | 0 | case CKM_NSS_IKE1_PRF_DERIVE: |
7523 | 0 | if (pMechanism->ulParameterLen != |
7524 | 0 | sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) { |
7525 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7526 | 0 | break; |
7527 | 0 | } |
7528 | 0 | crv = sftk_ike1_prf(hSession, att, |
7529 | 0 | (CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter, |
7530 | 0 | key, keySize); |
7531 | 0 | break; |
7532 | 0 | case CKM_NSS_IKE1_APP_B_PRF_DERIVE: |
7533 | 0 | pIkeAppB = (CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *)pMechanism->pParameter; |
7534 | 0 | if (pMechanism->ulParameterLen == |
7535 | 0 | sizeof(CK_MECHANISM_TYPE)) { |
7536 | 0 | ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter; |
7537 | 0 | ikeAppB.bHasKeygxy = PR_FALSE; |
7538 | 0 | ikeAppB.hKeygxy = CK_INVALID_HANDLE; |
7539 | 0 | ikeAppB.pExtraData = NULL; |
7540 | 0 | ikeAppB.ulExtraDataLen = 0; |
7541 | 0 | pIkeAppB = &ikeAppB; |
7542 | 0 | } else if (pMechanism->ulParameterLen != |
7543 | 0 | sizeof(CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS)) { |
7544 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7545 | 0 | break; |
7546 | 0 | } |
7547 | 0 | crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key, |
7548 | 0 | keySize); |
7549 | 0 | break; |
7550 | 0 | case CKM_NSS_IKE_PRF_PLUS_DERIVE: |
7551 | 0 | if (pMechanism->ulParameterLen != |
7552 | 0 | sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) { |
7553 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7554 | 0 | break; |
7555 | 0 | } |
7556 | 0 | crv = sftk_ike_prf_plus(hSession, att, |
7557 | 0 | (CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter, |
7558 | 0 | key, keySize); |
7559 | 0 | break; |
7560 | | /* |
7561 | | * generate the master secret |
7562 | | */ |
7563 | 2.31k | case CKM_TLS12_MASTER_KEY_DERIVE: |
7564 | 3.51k | case CKM_TLS12_MASTER_KEY_DERIVE_DH: |
7565 | 3.51k | case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: |
7566 | 3.51k | case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: |
7567 | 3.95k | case CKM_TLS_MASTER_KEY_DERIVE: |
7568 | 6.90k | case CKM_TLS_MASTER_KEY_DERIVE_DH: |
7569 | 6.90k | case CKM_SSL3_MASTER_KEY_DERIVE: |
7570 | 6.90k | case CKM_SSL3_MASTER_KEY_DERIVE_DH: { |
7571 | 6.90k | CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; |
7572 | 6.90k | SSL3RSAPreMasterSecret *rsa_pms; |
7573 | 6.90k | unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; |
7574 | | |
7575 | 6.90k | if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) || |
7576 | 6.90k | (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { |
7577 | 3.51k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) { |
7578 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7579 | 0 | break; |
7580 | 0 | } |
7581 | 3.51k | CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master = |
7582 | 3.51k | (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter; |
7583 | 3.51k | tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism); |
7584 | 3.51k | if (tlsPrfHash == HASH_AlgNULL) { |
7585 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7586 | 0 | break; |
7587 | 0 | } |
7588 | 3.51k | } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) || |
7589 | 3.38k | (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) { |
7590 | 0 | tlsPrfHash = HASH_AlgSHA256; |
7591 | 0 | } |
7592 | | |
7593 | 6.90k | if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) && |
7594 | 6.90k | (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) { |
7595 | 6.90k | isTLS = PR_TRUE; |
7596 | 6.90k | } |
7597 | 6.90k | if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || |
7598 | 6.90k | (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || |
7599 | 6.90k | (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) || |
7600 | 6.90k | (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { |
7601 | 4.14k | isDH = PR_TRUE; |
7602 | 4.14k | } |
7603 | | |
7604 | | /* first do the consistency checks */ |
7605 | 6.90k | if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
7606 | 6 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7607 | 6 | break; |
7608 | 6 | } |
7609 | 6.89k | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
7610 | 6.89k | if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
7611 | 6.89k | CKK_GENERIC_SECRET)) { |
7612 | 0 | if (att2) |
7613 | 0 | sftk_FreeAttribute(att2); |
7614 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7615 | 0 | break; |
7616 | 0 | } |
7617 | 6.89k | sftk_FreeAttribute(att2); |
7618 | 6.89k | if (keyType != CKK_GENERIC_SECRET) { |
7619 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7620 | 0 | break; |
7621 | 0 | } |
7622 | 6.89k | if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
7623 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7624 | 0 | break; |
7625 | 0 | } |
7626 | | |
7627 | | /* finally do the key gen */ |
7628 | 6.89k | ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) |
7629 | 6.89k | pMechanism->pParameter; |
7630 | | |
7631 | 6.89k | if (ssl3_master->pVersion) { |
7632 | 2.74k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
7633 | 2.74k | rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; |
7634 | | /* don't leak more key material then necessary for SSL to work */ |
7635 | 2.74k | if ((sessKey == NULL) || sessKey->wasDerived) { |
7636 | 0 | ssl3_master->pVersion->major = 0xff; |
7637 | 0 | ssl3_master->pVersion->minor = 0xff; |
7638 | 2.74k | } else { |
7639 | 2.74k | ssl3_master->pVersion->major = rsa_pms->client_version[0]; |
7640 | 2.74k | ssl3_master->pVersion->minor = rsa_pms->client_version[1]; |
7641 | 2.74k | } |
7642 | 2.74k | } |
7643 | 6.89k | if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) { |
7644 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7645 | 0 | break; |
7646 | 0 | } |
7647 | 6.89k | if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) { |
7648 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7649 | 0 | break; |
7650 | 0 | } |
7651 | 6.89k | PORT_Memcpy(crsrdata, |
7652 | 6.89k | ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
7653 | 6.89k | PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, |
7654 | 6.89k | ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
7655 | | |
7656 | 6.89k | if (isTLS) { |
7657 | 6.89k | SECStatus status; |
7658 | 6.89k | SECItem crsr = { siBuffer, NULL, 0 }; |
7659 | 6.89k | SECItem master = { siBuffer, NULL, 0 }; |
7660 | 6.89k | SECItem pms = { siBuffer, NULL, 0 }; |
7661 | | |
7662 | 6.89k | crsr.data = crsrdata; |
7663 | 6.89k | crsr.len = sizeof crsrdata; |
7664 | 6.89k | master.data = key_block; |
7665 | 6.89k | master.len = SSL3_MASTER_SECRET_LENGTH; |
7666 | 6.89k | pms.data = (unsigned char *)att->attrib.pValue; |
7667 | 6.89k | pms.len = att->attrib.ulValueLen; |
7668 | | |
7669 | 6.89k | if (tlsPrfHash != HASH_AlgNULL) { |
7670 | 3.51k | status = TLS_P_hash(tlsPrfHash, &pms, "master secret", |
7671 | 3.51k | &crsr, &master, isFIPS); |
7672 | 3.51k | } else { |
7673 | 3.38k | status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); |
7674 | 3.38k | } |
7675 | 6.89k | if (status != SECSuccess) { |
7676 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
7677 | 0 | crv = CKR_FUNCTION_FAILED; |
7678 | 0 | break; |
7679 | 0 | } |
7680 | 6.89k | } else { |
7681 | | /* now allocate the hash contexts */ |
7682 | 0 | md5 = MD5_NewContext(); |
7683 | 0 | if (md5 == NULL) { |
7684 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
7685 | 0 | crv = CKR_HOST_MEMORY; |
7686 | 0 | break; |
7687 | 0 | } |
7688 | 0 | sha = SHA1_NewContext(); |
7689 | 0 | if (sha == NULL) { |
7690 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
7691 | 0 | PORT_Free(md5); |
7692 | 0 | crv = CKR_HOST_MEMORY; |
7693 | 0 | break; |
7694 | 0 | } |
7695 | 0 | for (i = 0; i < 3; i++) { |
7696 | 0 | SHA1_Begin(sha); |
7697 | 0 | SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); |
7698 | 0 | SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, |
7699 | 0 | att->attrib.ulValueLen); |
7700 | 0 | SHA1_Update(sha, crsrdata, sizeof crsrdata); |
7701 | 0 | SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
7702 | 0 | PORT_Assert(outLen == SHA1_LENGTH); |
7703 | |
|
7704 | 0 | MD5_Begin(md5); |
7705 | 0 | MD5_Update(md5, (const unsigned char *)att->attrib.pValue, |
7706 | 0 | att->attrib.ulValueLen); |
7707 | 0 | MD5_Update(md5, sha_out, outLen); |
7708 | 0 | MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); |
7709 | 0 | PORT_Assert(outLen == MD5_LENGTH); |
7710 | 0 | } |
7711 | 0 | PORT_Free(md5); |
7712 | 0 | PORT_Free(sha); |
7713 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
7714 | 0 | PORT_Memset(sha_out, 0, sizeof sha_out); |
7715 | 0 | } |
7716 | | |
7717 | | /* store the results */ |
7718 | 6.89k | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH); |
7719 | 6.89k | PORT_Memset(key_block, 0, sizeof key_block); |
7720 | 6.89k | if (crv != CKR_OK) |
7721 | 0 | break; |
7722 | 6.89k | keyType = CKK_GENERIC_SECRET; |
7723 | 6.89k | crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
7724 | 6.89k | if (isTLS) { |
7725 | | /* TLS's master secret is used to "sign" finished msgs with PRF. */ |
7726 | | /* XXX This seems like a hack. But SFTK_Derive only accepts |
7727 | | * one "operation" argument. */ |
7728 | 6.89k | crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); |
7729 | 6.89k | if (crv != CKR_OK) |
7730 | 0 | break; |
7731 | 6.89k | crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); |
7732 | 6.89k | if (crv != CKR_OK) |
7733 | 0 | break; |
7734 | | /* While we're here, we might as well force this, too. */ |
7735 | 6.89k | crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); |
7736 | 6.89k | if (crv != CKR_OK) |
7737 | 0 | break; |
7738 | 6.89k | } |
7739 | 6.89k | break; |
7740 | 6.89k | } |
7741 | | |
7742 | | /* Extended master key derivation [draft-ietf-tls-session-hash] */ |
7743 | 6.89k | case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: |
7744 | 38 | case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: { |
7745 | 38 | CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params; |
7746 | 38 | SSL3RSAPreMasterSecret *rsa_pms; |
7747 | 38 | SECStatus status; |
7748 | 38 | SECItem pms = { siBuffer, NULL, 0 }; |
7749 | 38 | SECItem seed = { siBuffer, NULL, 0 }; |
7750 | 38 | SECItem master = { siBuffer, NULL, 0 }; |
7751 | | |
7752 | 38 | ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *) |
7753 | 38 | pMechanism->pParameter; |
7754 | | |
7755 | | /* First do the consistency checks */ |
7756 | 38 | if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) && |
7757 | 38 | (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
7758 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7759 | 0 | break; |
7760 | 0 | } |
7761 | 38 | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
7762 | 38 | if ((att2 == NULL) || |
7763 | 38 | (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) { |
7764 | 0 | if (att2) |
7765 | 0 | sftk_FreeAttribute(att2); |
7766 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7767 | 0 | break; |
7768 | 0 | } |
7769 | 38 | sftk_FreeAttribute(att2); |
7770 | 38 | if (keyType != CKK_GENERIC_SECRET) { |
7771 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7772 | 0 | break; |
7773 | 0 | } |
7774 | 38 | if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
7775 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7776 | 0 | break; |
7777 | 0 | } |
7778 | | |
7779 | | /* Do the key derivation */ |
7780 | 38 | pms.data = (unsigned char *)att->attrib.pValue; |
7781 | 38 | pms.len = att->attrib.ulValueLen; |
7782 | 38 | seed.data = ems_params->pSessionHash; |
7783 | 38 | seed.len = ems_params->ulSessionHashLen; |
7784 | 38 | master.data = key_block; |
7785 | 38 | master.len = SSL3_MASTER_SECRET_LENGTH; |
7786 | 38 | if (ems_params->prfHashMechanism == CKM_TLS_PRF) { |
7787 | | /* |
7788 | | * In this case, the session hash is the concatenation of SHA-1 |
7789 | | * and MD5, so it should be 36 bytes long. |
7790 | | */ |
7791 | 0 | if (seed.len != MD5_LENGTH + SHA1_LENGTH) { |
7792 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
7793 | 0 | break; |
7794 | 0 | } |
7795 | | |
7796 | 0 | status = TLS_PRF(&pms, "extended master secret", |
7797 | 0 | &seed, &master, isFIPS); |
7798 | 38 | } else { |
7799 | 38 | const SECHashObject *hashObj; |
7800 | | |
7801 | 38 | tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism); |
7802 | 38 | if (tlsPrfHash == HASH_AlgNULL) { |
7803 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7804 | 0 | break; |
7805 | 0 | } |
7806 | | |
7807 | 38 | hashObj = HASH_GetRawHashObject(tlsPrfHash); |
7808 | 38 | if (seed.len != hashObj->length) { |
7809 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
7810 | 0 | break; |
7811 | 0 | } |
7812 | | |
7813 | 38 | status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret", |
7814 | 38 | &seed, &master, isFIPS); |
7815 | 38 | } |
7816 | 38 | if (status != SECSuccess) { |
7817 | 0 | crv = CKR_FUNCTION_FAILED; |
7818 | 0 | break; |
7819 | 0 | } |
7820 | | |
7821 | | /* Reflect the version if required */ |
7822 | 38 | if (ems_params->pVersion) { |
7823 | 26 | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
7824 | 26 | rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; |
7825 | | /* don't leak more key material than necessary for SSL to work */ |
7826 | 26 | if ((sessKey == NULL) || sessKey->wasDerived) { |
7827 | 0 | ems_params->pVersion->major = 0xff; |
7828 | 0 | ems_params->pVersion->minor = 0xff; |
7829 | 26 | } else { |
7830 | 26 | ems_params->pVersion->major = rsa_pms->client_version[0]; |
7831 | 26 | ems_params->pVersion->minor = rsa_pms->client_version[1]; |
7832 | 26 | } |
7833 | 26 | } |
7834 | | |
7835 | | /* Store the results */ |
7836 | 38 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, |
7837 | 38 | SSL3_MASTER_SECRET_LENGTH); |
7838 | 38 | PORT_Memset(key_block, 0, sizeof key_block); |
7839 | 38 | break; |
7840 | 38 | } |
7841 | | |
7842 | 3.52k | case CKM_TLS12_KEY_AND_MAC_DERIVE: |
7843 | 3.52k | case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: |
7844 | 6.91k | case CKM_TLS_KEY_AND_MAC_DERIVE: |
7845 | 6.91k | case CKM_SSL3_KEY_AND_MAC_DERIVE: { |
7846 | 6.91k | CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; |
7847 | 6.91k | CK_SSL3_KEY_MAT_OUT *ssl3_keys_out; |
7848 | 6.91k | CK_ULONG effKeySize; |
7849 | 6.91k | unsigned int block_needed; |
7850 | 6.91k | unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; |
7851 | | |
7852 | 6.91k | if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) { |
7853 | 3.52k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) { |
7854 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7855 | 0 | break; |
7856 | 0 | } |
7857 | 3.52k | CK_TLS12_KEY_MAT_PARAMS *tls12_keys = |
7858 | 3.52k | (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter; |
7859 | 3.52k | tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism); |
7860 | 3.52k | if (tlsPrfHash == HASH_AlgNULL) { |
7861 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7862 | 0 | break; |
7863 | 0 | } |
7864 | 3.52k | } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) { |
7865 | 0 | tlsPrfHash = HASH_AlgSHA256; |
7866 | 0 | } |
7867 | | |
7868 | 6.91k | if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) { |
7869 | 6.91k | isTLS = PR_TRUE; |
7870 | 6.91k | } |
7871 | | |
7872 | 6.91k | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
7873 | 6.91k | if (crv != CKR_OK) |
7874 | 0 | break; |
7875 | | |
7876 | 6.91k | if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { |
7877 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7878 | 0 | break; |
7879 | 0 | } |
7880 | 6.91k | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
7881 | 6.91k | if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
7882 | 6.91k | CKK_GENERIC_SECRET)) { |
7883 | 0 | if (att2) |
7884 | 0 | sftk_FreeAttribute(att2); |
7885 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7886 | 0 | break; |
7887 | 0 | } |
7888 | 6.91k | sftk_FreeAttribute(att2); |
7889 | 6.91k | md5 = MD5_NewContext(); |
7890 | 6.91k | if (md5 == NULL) { |
7891 | 0 | crv = CKR_HOST_MEMORY; |
7892 | 0 | break; |
7893 | 0 | } |
7894 | 6.91k | sha = SHA1_NewContext(); |
7895 | 6.91k | if (sha == NULL) { |
7896 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
7897 | 0 | crv = CKR_HOST_MEMORY; |
7898 | 0 | break; |
7899 | 0 | } |
7900 | | |
7901 | 6.91k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) { |
7902 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
7903 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
7904 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7905 | 0 | break; |
7906 | 0 | } |
7907 | 6.91k | ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; |
7908 | | |
7909 | 6.91k | PORT_Memcpy(srcrdata, |
7910 | 6.91k | ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
7911 | 6.91k | PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, |
7912 | 6.91k | ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
7913 | | |
7914 | | /* |
7915 | | * clear out our returned keys so we can recover on failure |
7916 | | */ |
7917 | 6.91k | ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; |
7918 | 6.91k | ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; |
7919 | 6.91k | ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; |
7920 | 6.91k | ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; |
7921 | 6.91k | ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; |
7922 | | |
7923 | | /* |
7924 | | * How much key material do we need? |
7925 | | */ |
7926 | 6.91k | macSize = ssl3_keys->ulMacSizeInBits / 8; |
7927 | 6.91k | effKeySize = ssl3_keys->ulKeySizeInBits / 8; |
7928 | 6.91k | IVSize = ssl3_keys->ulIVSizeInBits / 8; |
7929 | 6.91k | if (keySize == 0) { |
7930 | 1.11k | effKeySize = keySize; |
7931 | 1.11k | } |
7932 | | |
7933 | | /* bIsExport must be false. */ |
7934 | 6.91k | if (ssl3_keys->bIsExport) { |
7935 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
7936 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
7937 | 0 | PORT_Memset(srcrdata, 0, sizeof srcrdata); |
7938 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7939 | 0 | break; |
7940 | 0 | } |
7941 | | |
7942 | 6.91k | block_needed = 2 * (macSize + effKeySize + IVSize); |
7943 | 6.91k | PORT_Assert(block_needed <= sizeof key_block); |
7944 | 6.91k | if (block_needed > sizeof key_block) |
7945 | 0 | block_needed = sizeof key_block; |
7946 | | |
7947 | | /* |
7948 | | * generate the key material: This looks amazingly similar to the |
7949 | | * PMS code, and is clearly crying out for a function to provide it. |
7950 | | */ |
7951 | 6.91k | if (isTLS) { |
7952 | 6.91k | SECStatus status; |
7953 | 6.91k | SECItem srcr = { siBuffer, NULL, 0 }; |
7954 | 6.91k | SECItem keyblk = { siBuffer, NULL, 0 }; |
7955 | 6.91k | SECItem master = { siBuffer, NULL, 0 }; |
7956 | | |
7957 | 6.91k | srcr.data = srcrdata; |
7958 | 6.91k | srcr.len = sizeof srcrdata; |
7959 | 6.91k | keyblk.data = key_block; |
7960 | 6.91k | keyblk.len = block_needed; |
7961 | 6.91k | master.data = (unsigned char *)att->attrib.pValue; |
7962 | 6.91k | master.len = att->attrib.ulValueLen; |
7963 | | |
7964 | 6.91k | if (tlsPrfHash != HASH_AlgNULL) { |
7965 | 3.52k | status = TLS_P_hash(tlsPrfHash, &master, "key expansion", |
7966 | 3.52k | &srcr, &keyblk, isFIPS); |
7967 | 3.52k | } else { |
7968 | 3.38k | status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, |
7969 | 3.38k | isFIPS); |
7970 | 3.38k | } |
7971 | 6.91k | if (status != SECSuccess) { |
7972 | 0 | goto key_and_mac_derive_fail; |
7973 | 0 | } |
7974 | 6.91k | } else { |
7975 | 0 | unsigned int block_bytes = 0; |
7976 | | /* key_block = |
7977 | | * MD5(master_secret + SHA('A' + master_secret + |
7978 | | * ServerHello.random + ClientHello.random)) + |
7979 | | * MD5(master_secret + SHA('BB' + master_secret + |
7980 | | * ServerHello.random + ClientHello.random)) + |
7981 | | * MD5(master_secret + SHA('CCC' + master_secret + |
7982 | | * ServerHello.random + ClientHello.random)) + |
7983 | | * [...]; |
7984 | | */ |
7985 | 0 | for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { |
7986 | 0 | SHA1_Begin(sha); |
7987 | 0 | SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); |
7988 | 0 | SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, |
7989 | 0 | att->attrib.ulValueLen); |
7990 | 0 | SHA1_Update(sha, srcrdata, sizeof srcrdata); |
7991 | 0 | SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
7992 | 0 | PORT_Assert(outLen == SHA1_LENGTH); |
7993 | 0 | MD5_Begin(md5); |
7994 | 0 | MD5_Update(md5, (const unsigned char *)att->attrib.pValue, |
7995 | 0 | att->attrib.ulValueLen); |
7996 | 0 | MD5_Update(md5, sha_out, outLen); |
7997 | 0 | MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); |
7998 | 0 | PORT_Assert(outLen == MD5_LENGTH); |
7999 | 0 | block_bytes += outLen; |
8000 | 0 | } |
8001 | 0 | PORT_Memset(sha_out, 0, sizeof sha_out); |
8002 | 0 | } |
8003 | | |
8004 | | /* |
8005 | | * Put the key material where it goes. |
8006 | | */ |
8007 | 6.91k | i = 0; /* now shows how much consumed */ |
8008 | | |
8009 | | /* |
8010 | | * The key_block is partitioned as follows: |
8011 | | * client_write_MAC_secret[CipherSpec.hash_size] |
8012 | | */ |
8013 | 6.91k | crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, |
8014 | 6.91k | &ssl3_keys_out->hClientMacSecret); |
8015 | 6.91k | if (crv != CKR_OK) |
8016 | 0 | goto key_and_mac_derive_fail; |
8017 | | |
8018 | 6.91k | i += macSize; |
8019 | | |
8020 | | /* |
8021 | | * server_write_MAC_secret[CipherSpec.hash_size] |
8022 | | */ |
8023 | 6.91k | crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, |
8024 | 6.91k | &ssl3_keys_out->hServerMacSecret); |
8025 | 6.91k | if (crv != CKR_OK) { |
8026 | 0 | goto key_and_mac_derive_fail; |
8027 | 0 | } |
8028 | 6.91k | i += macSize; |
8029 | | |
8030 | 6.91k | if (keySize) { |
8031 | | /* |
8032 | | ** Generate Domestic write keys and IVs. |
8033 | | ** client_write_key[CipherSpec.key_material] |
8034 | | */ |
8035 | 5.79k | crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], |
8036 | 5.79k | keySize, &ssl3_keys_out->hClientKey); |
8037 | 5.79k | if (crv != CKR_OK) { |
8038 | 0 | goto key_and_mac_derive_fail; |
8039 | 0 | } |
8040 | 5.79k | i += keySize; |
8041 | | |
8042 | | /* |
8043 | | ** server_write_key[CipherSpec.key_material] |
8044 | | */ |
8045 | 5.79k | crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], |
8046 | 5.79k | keySize, &ssl3_keys_out->hServerKey); |
8047 | 5.79k | if (crv != CKR_OK) { |
8048 | 0 | goto key_and_mac_derive_fail; |
8049 | 0 | } |
8050 | 5.79k | i += keySize; |
8051 | | |
8052 | | /* |
8053 | | ** client_write_IV[CipherSpec.IV_size] |
8054 | | */ |
8055 | 5.79k | if (IVSize > 0) { |
8056 | 5.54k | PORT_Memcpy(ssl3_keys_out->pIVClient, |
8057 | 5.54k | &key_block[i], IVSize); |
8058 | 5.54k | i += IVSize; |
8059 | 5.54k | } |
8060 | | |
8061 | | /* |
8062 | | ** server_write_IV[CipherSpec.IV_size] |
8063 | | */ |
8064 | 5.79k | if (IVSize > 0) { |
8065 | 5.54k | PORT_Memcpy(ssl3_keys_out->pIVServer, |
8066 | 5.54k | &key_block[i], IVSize); |
8067 | 5.54k | i += IVSize; |
8068 | 5.54k | } |
8069 | 5.79k | PORT_Assert(i <= sizeof key_block); |
8070 | 5.79k | } |
8071 | | |
8072 | 6.91k | crv = CKR_OK; |
8073 | | |
8074 | 6.91k | if (0) { |
8075 | 0 | key_and_mac_derive_fail: |
8076 | 0 | if (crv == CKR_OK) |
8077 | 0 | crv = CKR_FUNCTION_FAILED; |
8078 | 0 | sftk_freeSSLKeys(hSession, ssl3_keys_out); |
8079 | 0 | } |
8080 | 6.91k | PORT_Memset(srcrdata, 0, sizeof srcrdata); |
8081 | 6.91k | PORT_Memset(key_block, 0, sizeof key_block); |
8082 | 6.91k | MD5_DestroyContext(md5, PR_TRUE); |
8083 | 6.91k | SHA1_DestroyContext(sha, PR_TRUE); |
8084 | 6.91k | sftk_FreeObject(key); |
8085 | 6.91k | key = NULL; |
8086 | 6.91k | break; |
8087 | 6.91k | } |
8088 | | |
8089 | 0 | case CKM_DES3_ECB_ENCRYPT_DATA: |
8090 | 0 | case CKM_DES3_CBC_ENCRYPT_DATA: { |
8091 | 0 | void *cipherInfo; |
8092 | 0 | unsigned char des3key[MAX_DES3_KEY_SIZE]; |
8093 | 0 | CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr; |
8094 | 0 | int mode; |
8095 | 0 | unsigned char *iv; |
8096 | 0 | unsigned char *data; |
8097 | 0 | CK_ULONG len; |
8098 | |
|
8099 | 0 | if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) { |
8100 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8101 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8102 | 0 | break; |
8103 | 0 | } |
8104 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
8105 | 0 | pMechanism->pParameter; |
8106 | 0 | mode = NSS_DES_EDE3; |
8107 | 0 | iv = NULL; |
8108 | 0 | data = stringPtr->pData; |
8109 | 0 | len = stringPtr->ulLen; |
8110 | 0 | } else { |
8111 | 0 | mode = NSS_DES_EDE3_CBC; |
8112 | 0 | desEncryptPtr = |
8113 | 0 | (CK_DES_CBC_ENCRYPT_DATA_PARAMS *) |
8114 | 0 | pMechanism->pParameter; |
8115 | 0 | iv = desEncryptPtr->iv; |
8116 | 0 | data = desEncryptPtr->pData; |
8117 | 0 | len = desEncryptPtr->length; |
8118 | 0 | } |
8119 | 0 | if (att->attrib.ulValueLen == 16) { |
8120 | 0 | PORT_Memcpy(des3key, att->attrib.pValue, 16); |
8121 | 0 | PORT_Memcpy(des3key + 16, des3key, 8); |
8122 | 0 | } else if (att->attrib.ulValueLen == 24) { |
8123 | 0 | PORT_Memcpy(des3key, att->attrib.pValue, 24); |
8124 | 0 | } else { |
8125 | 0 | crv = CKR_KEY_SIZE_RANGE; |
8126 | 0 | break; |
8127 | 0 | } |
8128 | 0 | cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE); |
8129 | 0 | PORT_Memset(des3key, 0, 24); |
8130 | 0 | if (cipherInfo == NULL) { |
8131 | 0 | crv = CKR_HOST_MEMORY; |
8132 | 0 | break; |
8133 | 0 | } |
8134 | 0 | crv = sftk_DeriveEncrypt((SFTKCipher)DES_Encrypt, |
8135 | 0 | cipherInfo, 8, key, keySize, |
8136 | 0 | data, len); |
8137 | 0 | DES_DestroyContext(cipherInfo, PR_TRUE); |
8138 | 0 | break; |
8139 | 0 | } |
8140 | | |
8141 | 0 | case CKM_AES_ECB_ENCRYPT_DATA: |
8142 | 0 | case CKM_AES_CBC_ENCRYPT_DATA: { |
8143 | 0 | void *cipherInfo; |
8144 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
8145 | 0 | int mode; |
8146 | 0 | unsigned char *iv; |
8147 | 0 | unsigned char *data; |
8148 | 0 | CK_ULONG len; |
8149 | |
|
8150 | 0 | if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) { |
8151 | 0 | mode = NSS_AES; |
8152 | 0 | iv = NULL; |
8153 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8154 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8155 | 0 | break; |
8156 | 0 | } |
8157 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
8158 | 0 | data = stringPtr->pData; |
8159 | 0 | len = stringPtr->ulLen; |
8160 | 0 | } else { |
8161 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
8162 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8163 | 0 | break; |
8164 | 0 | } |
8165 | 0 | aesEncryptPtr = |
8166 | 0 | (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter; |
8167 | 0 | mode = NSS_AES_CBC; |
8168 | 0 | iv = aesEncryptPtr->iv; |
8169 | 0 | data = aesEncryptPtr->pData; |
8170 | 0 | len = aesEncryptPtr->length; |
8171 | 0 | } |
8172 | | |
8173 | 0 | cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue, |
8174 | 0 | iv, mode, PR_TRUE, |
8175 | 0 | att->attrib.ulValueLen, 16); |
8176 | 0 | if (cipherInfo == NULL) { |
8177 | 0 | crv = CKR_HOST_MEMORY; |
8178 | 0 | break; |
8179 | 0 | } |
8180 | 0 | crv = sftk_DeriveEncrypt((SFTKCipher)AES_Encrypt, |
8181 | 0 | cipherInfo, 16, key, keySize, |
8182 | 0 | data, len); |
8183 | 0 | AES_DestroyContext(cipherInfo, PR_TRUE); |
8184 | 0 | break; |
8185 | 0 | } |
8186 | | |
8187 | 0 | case CKM_CAMELLIA_ECB_ENCRYPT_DATA: |
8188 | 0 | case CKM_CAMELLIA_CBC_ENCRYPT_DATA: { |
8189 | 0 | void *cipherInfo; |
8190 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
8191 | 0 | int mode; |
8192 | 0 | unsigned char *iv; |
8193 | 0 | unsigned char *data; |
8194 | 0 | CK_ULONG len; |
8195 | |
|
8196 | 0 | if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) { |
8197 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8198 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8199 | 0 | break; |
8200 | 0 | } |
8201 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
8202 | 0 | pMechanism->pParameter; |
8203 | 0 | aesEncryptPtr = NULL; |
8204 | 0 | mode = NSS_CAMELLIA; |
8205 | 0 | data = stringPtr->pData; |
8206 | 0 | len = stringPtr->ulLen; |
8207 | 0 | iv = NULL; |
8208 | 0 | } else { |
8209 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
8210 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8211 | 0 | break; |
8212 | 0 | } |
8213 | 0 | stringPtr = NULL; |
8214 | 0 | aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) |
8215 | 0 | pMechanism->pParameter; |
8216 | 0 | mode = NSS_CAMELLIA_CBC; |
8217 | 0 | iv = aesEncryptPtr->iv; |
8218 | 0 | data = aesEncryptPtr->pData; |
8219 | 0 | len = aesEncryptPtr->length; |
8220 | 0 | } |
8221 | | |
8222 | 0 | cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue, |
8223 | 0 | iv, mode, PR_TRUE, |
8224 | 0 | att->attrib.ulValueLen); |
8225 | 0 | if (cipherInfo == NULL) { |
8226 | 0 | crv = CKR_HOST_MEMORY; |
8227 | 0 | break; |
8228 | 0 | } |
8229 | 0 | crv = sftk_DeriveEncrypt((SFTKCipher)Camellia_Encrypt, |
8230 | 0 | cipherInfo, 16, key, keySize, |
8231 | 0 | data, len); |
8232 | 0 | Camellia_DestroyContext(cipherInfo, PR_TRUE); |
8233 | 0 | break; |
8234 | 0 | } |
8235 | | |
8236 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
8237 | 0 | case CKM_SEED_ECB_ENCRYPT_DATA: |
8238 | 0 | case CKM_SEED_CBC_ENCRYPT_DATA: { |
8239 | 0 | void *cipherInfo; |
8240 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
8241 | 0 | int mode; |
8242 | 0 | unsigned char *iv; |
8243 | 0 | unsigned char *data; |
8244 | 0 | CK_ULONG len; |
8245 | |
|
8246 | 0 | if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) { |
8247 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8248 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8249 | 0 | break; |
8250 | 0 | } |
8251 | 0 | mode = NSS_SEED; |
8252 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
8253 | 0 | pMechanism->pParameter; |
8254 | 0 | aesEncryptPtr = NULL; |
8255 | 0 | data = stringPtr->pData; |
8256 | 0 | len = stringPtr->ulLen; |
8257 | 0 | iv = NULL; |
8258 | 0 | } else { |
8259 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
8260 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8261 | 0 | break; |
8262 | 0 | } |
8263 | 0 | mode = NSS_SEED_CBC; |
8264 | 0 | aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) |
8265 | 0 | pMechanism->pParameter; |
8266 | 0 | iv = aesEncryptPtr->iv; |
8267 | 0 | data = aesEncryptPtr->pData; |
8268 | 0 | len = aesEncryptPtr->length; |
8269 | 0 | } |
8270 | | |
8271 | 0 | cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue, |
8272 | 0 | iv, mode, PR_TRUE); |
8273 | 0 | if (cipherInfo == NULL) { |
8274 | 0 | crv = CKR_HOST_MEMORY; |
8275 | 0 | break; |
8276 | 0 | } |
8277 | 0 | crv = sftk_DeriveEncrypt((SFTKCipher)SEED_Encrypt, |
8278 | 0 | cipherInfo, 16, key, keySize, |
8279 | 0 | data, len); |
8280 | 0 | SEED_DestroyContext(cipherInfo, PR_TRUE); |
8281 | 0 | break; |
8282 | 0 | } |
8283 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
8284 | | |
8285 | 0 | case CKM_CONCATENATE_BASE_AND_KEY: { |
8286 | 0 | SFTKObject *paramKey; |
8287 | |
|
8288 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8289 | 0 | if (crv != CKR_OK) |
8290 | 0 | break; |
8291 | | |
8292 | 0 | session = sftk_SessionFromHandle(hSession); |
8293 | 0 | if (session == NULL) { |
8294 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
8295 | 0 | break; |
8296 | 0 | } |
8297 | | |
8298 | 0 | paramKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *) |
8299 | 0 | pMechanism->pParameter, |
8300 | 0 | session); |
8301 | 0 | sftk_FreeSession(session); |
8302 | 0 | if (paramKey == NULL) { |
8303 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
8304 | 0 | break; |
8305 | 0 | } |
8306 | | |
8307 | 0 | if (sftk_isTrue(paramKey, CKA_SENSITIVE)) { |
8308 | 0 | crv = sftk_forceAttribute(key, CKA_SENSITIVE, &cktrue, |
8309 | 0 | sizeof(CK_BBOOL)); |
8310 | 0 | if (crv != CKR_OK) { |
8311 | 0 | sftk_FreeObject(paramKey); |
8312 | 0 | break; |
8313 | 0 | } |
8314 | 0 | } |
8315 | | |
8316 | 0 | if (sftk_hasAttribute(paramKey, CKA_EXTRACTABLE) && !sftk_isTrue(paramKey, CKA_EXTRACTABLE)) { |
8317 | 0 | crv = sftk_forceAttribute(key, CKA_EXTRACTABLE, &ckfalse, sizeof(CK_BBOOL)); |
8318 | 0 | if (crv != CKR_OK) { |
8319 | 0 | sftk_FreeObject(paramKey); |
8320 | 0 | break; |
8321 | 0 | } |
8322 | 0 | } |
8323 | | |
8324 | 0 | att2 = sftk_FindAttribute(paramKey, CKA_VALUE); |
8325 | 0 | if (att2 == NULL) { |
8326 | 0 | sftk_FreeObject(paramKey); |
8327 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
8328 | 0 | break; |
8329 | 0 | } |
8330 | 0 | tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen; |
8331 | 0 | if (keySize == 0) |
8332 | 0 | keySize = tmpKeySize; |
8333 | 0 | if (keySize > tmpKeySize) { |
8334 | 0 | sftk_FreeObject(paramKey); |
8335 | 0 | sftk_FreeAttribute(att2); |
8336 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8337 | 0 | break; |
8338 | 0 | } |
8339 | 0 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
8340 | 0 | if (buf == NULL) { |
8341 | 0 | sftk_FreeAttribute(att2); |
8342 | 0 | sftk_FreeObject(paramKey); |
8343 | 0 | crv = CKR_HOST_MEMORY; |
8344 | 0 | break; |
8345 | 0 | } |
8346 | | |
8347 | 0 | PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); |
8348 | 0 | PORT_Memcpy(buf + att->attrib.ulValueLen, |
8349 | 0 | att2->attrib.pValue, att2->attrib.ulValueLen); |
8350 | |
|
8351 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8352 | 0 | PORT_ZFree(buf, tmpKeySize); |
8353 | 0 | sftk_FreeAttribute(att2); |
8354 | 0 | sftk_FreeObject(paramKey); |
8355 | 0 | break; |
8356 | 0 | } |
8357 | | |
8358 | 0 | case CKM_CONCATENATE_BASE_AND_DATA: |
8359 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8360 | 0 | if (crv != CKR_OK) |
8361 | 0 | break; |
8362 | | |
8363 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8364 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8365 | 0 | break; |
8366 | 0 | } |
8367 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
8368 | 0 | tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; |
8369 | 0 | if (keySize == 0) |
8370 | 0 | keySize = tmpKeySize; |
8371 | 0 | if (keySize > tmpKeySize) { |
8372 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8373 | 0 | break; |
8374 | 0 | } |
8375 | 0 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
8376 | 0 | if (buf == NULL) { |
8377 | 0 | crv = CKR_HOST_MEMORY; |
8378 | 0 | break; |
8379 | 0 | } |
8380 | | |
8381 | 0 | PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); |
8382 | 0 | PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData, |
8383 | 0 | stringPtr->ulLen); |
8384 | |
|
8385 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8386 | 0 | PORT_ZFree(buf, tmpKeySize); |
8387 | 0 | break; |
8388 | 0 | case CKM_CONCATENATE_DATA_AND_BASE: |
8389 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8390 | 0 | if (crv != CKR_OK) |
8391 | 0 | break; |
8392 | | |
8393 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8394 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8395 | 0 | break; |
8396 | 0 | } |
8397 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
8398 | 0 | tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; |
8399 | 0 | if (keySize == 0) |
8400 | 0 | keySize = tmpKeySize; |
8401 | 0 | if (keySize > tmpKeySize) { |
8402 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8403 | 0 | break; |
8404 | 0 | } |
8405 | 0 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
8406 | 0 | if (buf == NULL) { |
8407 | 0 | crv = CKR_HOST_MEMORY; |
8408 | 0 | break; |
8409 | 0 | } |
8410 | | |
8411 | 0 | PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen); |
8412 | 0 | PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue, |
8413 | 0 | att->attrib.ulValueLen); |
8414 | |
|
8415 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8416 | 0 | PORT_ZFree(buf, tmpKeySize); |
8417 | 0 | break; |
8418 | 0 | case CKM_XOR_BASE_AND_DATA: |
8419 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8420 | 0 | if (crv != CKR_OK) |
8421 | 0 | break; |
8422 | | |
8423 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8424 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8425 | 0 | break; |
8426 | 0 | } |
8427 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
8428 | 0 | tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen); |
8429 | 0 | if (keySize == 0) |
8430 | 0 | keySize = tmpKeySize; |
8431 | 0 | if (keySize > tmpKeySize) { |
8432 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8433 | 0 | break; |
8434 | 0 | } |
8435 | 0 | buf = (unsigned char *)PORT_Alloc(keySize); |
8436 | 0 | if (buf == NULL) { |
8437 | 0 | crv = CKR_HOST_MEMORY; |
8438 | 0 | break; |
8439 | 0 | } |
8440 | | |
8441 | 0 | PORT_Memcpy(buf, att->attrib.pValue, keySize); |
8442 | 0 | for (i = 0; i < (int)keySize; i++) { |
8443 | 0 | buf[i] ^= stringPtr->pData[i]; |
8444 | 0 | } |
8445 | |
|
8446 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8447 | 0 | PORT_ZFree(buf, keySize); |
8448 | 0 | break; |
8449 | | |
8450 | 0 | case CKM_EXTRACT_KEY_FROM_KEY: { |
8451 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) { |
8452 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8453 | 0 | break; |
8454 | 0 | } |
8455 | | /* the following assumes 8 bits per byte */ |
8456 | 0 | CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter; |
8457 | 0 | CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ |
8458 | 0 | CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ |
8459 | |
|
8460 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8461 | 0 | if (crv != CKR_OK) |
8462 | 0 | break; |
8463 | | |
8464 | 0 | if (keySize == 0) { |
8465 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
8466 | 0 | break; |
8467 | 0 | } |
8468 | | /* make sure we have enough bits in the original key */ |
8469 | 0 | if (att->attrib.ulValueLen < |
8470 | 0 | (offset + keySize + ((shift != 0) ? 1 : 0))) { |
8471 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8472 | 0 | break; |
8473 | 0 | } |
8474 | 0 | buf = (unsigned char *)PORT_Alloc(keySize); |
8475 | 0 | if (buf == NULL) { |
8476 | 0 | crv = CKR_HOST_MEMORY; |
8477 | 0 | break; |
8478 | 0 | } |
8479 | | |
8480 | | /* copy the bits we need into the new key */ |
8481 | 0 | for (i = 0; i < (int)keySize; i++) { |
8482 | 0 | unsigned char *value = |
8483 | 0 | ((unsigned char *)att->attrib.pValue) + offset + i; |
8484 | 0 | if (shift) { |
8485 | 0 | buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift)); |
8486 | 0 | } else { |
8487 | 0 | buf[i] = value[0]; |
8488 | 0 | } |
8489 | 0 | } |
8490 | |
|
8491 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8492 | 0 | PORT_ZFree(buf, keySize); |
8493 | 0 | break; |
8494 | 0 | } |
8495 | 0 | case CKM_MD2_KEY_DERIVATION: |
8496 | 0 | if (keySize == 0) |
8497 | 0 | keySize = MD2_LENGTH; |
8498 | 0 | if (keySize > MD2_LENGTH) { |
8499 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8500 | 0 | break; |
8501 | 0 | } |
8502 | | /* now allocate the hash contexts */ |
8503 | 0 | md2 = MD2_NewContext(); |
8504 | 0 | if (md2 == NULL) { |
8505 | 0 | crv = CKR_HOST_MEMORY; |
8506 | 0 | break; |
8507 | 0 | } |
8508 | 0 | MD2_Begin(md2); |
8509 | 0 | MD2_Update(md2, (const unsigned char *)att->attrib.pValue, |
8510 | 0 | att->attrib.ulValueLen); |
8511 | 0 | MD2_End(md2, key_block, &outLen, MD2_LENGTH); |
8512 | 0 | MD2_DestroyContext(md2, PR_TRUE); |
8513 | |
|
8514 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); |
8515 | 0 | PORT_Memset(key_block, 0, MD2_LENGTH); |
8516 | 0 | break; |
8517 | 0 | #define DERIVE_KEY_HASH(hash) \ |
8518 | 0 | case CKM_##hash##_KEY_DERIVATION: \ |
8519 | 0 | if (keySize == 0) \ |
8520 | 0 | keySize = hash##_LENGTH; \ |
8521 | 0 | if (keySize > hash##_LENGTH) { \ |
8522 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; \ |
8523 | 0 | break; \ |
8524 | 0 | } \ |
8525 | 0 | hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \ |
8526 | 0 | att->attrib.ulValueLen); \ |
8527 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); \ |
8528 | 0 | PORT_Memset(key_block, 0, hash##_LENGTH); \ |
8529 | 0 | break; |
8530 | 0 | DERIVE_KEY_HASH(MD5) |
8531 | 0 | DERIVE_KEY_HASH(SHA1) |
8532 | 0 | DERIVE_KEY_HASH(SHA224) |
8533 | 0 | DERIVE_KEY_HASH(SHA256) |
8534 | 0 | DERIVE_KEY_HASH(SHA384) |
8535 | 0 | DERIVE_KEY_HASH(SHA512) |
8536 | 0 | DERIVE_KEY_HASH(SHA3_224) |
8537 | 0 | DERIVE_KEY_HASH(SHA3_256) |
8538 | 0 | DERIVE_KEY_HASH(SHA3_384) |
8539 | 0 | DERIVE_KEY_HASH(SHA3_512) |
8540 | | |
8541 | 6.60k | case CKM_DH_PKCS_DERIVE: { |
8542 | 6.60k | SECItem derived, dhPublic; |
8543 | 6.60k | SECItem dhPrime, dhValue; |
8544 | 6.60k | const SECItem *subPrime; |
8545 | | /* sourceKey - values for the local existing low key */ |
8546 | | /* get prime and value attributes */ |
8547 | 6.60k | crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); |
8548 | 6.60k | if (crv != CKR_OK) |
8549 | 0 | break; |
8550 | | |
8551 | 6.60k | dhPublic.data = pMechanism->pParameter; |
8552 | 6.60k | dhPublic.len = pMechanism->ulParameterLen; |
8553 | | |
8554 | | /* if the prime is an approved prime, we can skip all the other |
8555 | | * checks. */ |
8556 | 6.60k | subPrime = sftk_VerifyDH_Prime(&dhPrime, isFIPS); |
8557 | 6.60k | if (subPrime == NULL) { |
8558 | 0 | SECItem dhSubPrime; |
8559 | | /* If the caller set the subprime value, it means that |
8560 | | * either the caller knows the subprime value and wants us |
8561 | | * to validate the key against the subprime, or that the |
8562 | | * caller wants us to verify that the prime is a safe prime |
8563 | | * by passing in subprime = (prime-1)/2 */ |
8564 | 0 | dhSubPrime.data = NULL; |
8565 | 0 | dhSubPrime.len = 0; |
8566 | 0 | crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, |
8567 | 0 | sourceKey, CKA_SUBPRIME); |
8568 | | /* we ignore the value of crv here, We treat a valid |
8569 | | * return of len = 0 and a failure to find a subrime the same |
8570 | | * NOTE: we free the subprime in both cases depending on |
8571 | | * PORT_Free of NULL to be a noop */ |
8572 | 0 | if (dhSubPrime.len != 0) { |
8573 | 0 | PRBool isSafe = PR_FALSE; |
8574 | | |
8575 | | /* Callers can set dhSubPrime to q=(p-1)/2 to force |
8576 | | * checks for safe primes. If so we only need to check |
8577 | | * q and p for primality and skip the group test. */ |
8578 | 0 | rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe); |
8579 | 0 | if (rv != SECSuccess) { |
8580 | | /* either p or q was even and therefore not prime, |
8581 | | * we can stop processing here and fail now */ |
8582 | 0 | crv = CKR_ARGUMENTS_BAD; |
8583 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8584 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8585 | 0 | break; |
8586 | 0 | } |
8587 | | |
8588 | | /* first make sure the primes are really prime */ |
8589 | 0 | if (!KEA_PrimeCheck(&dhPrime)) { |
8590 | 0 | crv = CKR_ARGUMENTS_BAD; |
8591 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8592 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8593 | 0 | break; |
8594 | 0 | } |
8595 | 0 | if (!KEA_PrimeCheck(&dhSubPrime)) { |
8596 | 0 | crv = CKR_ARGUMENTS_BAD; |
8597 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8598 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8599 | 0 | break; |
8600 | 0 | } |
8601 | 0 | if (isFIPS || !isSafe) { |
8602 | | /* With safe primes, there is only one other small |
8603 | | * subgroup. As long as y isn't 0, 1, or -1 mod p, |
8604 | | * any other y is safe. Only do the full check for |
8605 | | * non-safe primes, except in FIPS mode we need |
8606 | | * to do this check on all primes in which |
8607 | | * we receive the subprime value */ |
8608 | 0 | if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) { |
8609 | 0 | crv = CKR_ARGUMENTS_BAD; |
8610 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8611 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8612 | 0 | break; |
8613 | 0 | } |
8614 | 0 | } |
8615 | 0 | } else if (isFIPS) { |
8616 | | /* In FIPS mode we only accept approved primes, or |
8617 | | * primes with the full subprime value */ |
8618 | 0 | crv = CKR_ARGUMENTS_BAD; |
8619 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8620 | 0 | break; |
8621 | 0 | } |
8622 | | /* checks are complete, no need for the subPrime any longer */ |
8623 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8624 | 0 | } |
8625 | | |
8626 | | /* now that the prime is validated, get the private value */ |
8627 | 6.60k | crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); |
8628 | 6.60k | if (crv != CKR_OK) { |
8629 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8630 | 0 | break; |
8631 | 0 | } |
8632 | | |
8633 | | /* calculate private value - oct */ |
8634 | 6.60k | rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); |
8635 | | |
8636 | 6.60k | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8637 | 6.60k | SECITEM_ZfreeItem(&dhValue, PR_FALSE); |
8638 | | |
8639 | 6.60k | if (rv == SECSuccess) { |
8640 | 6.60k | sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); |
8641 | 6.60k | SECITEM_ZfreeItem(&derived, PR_FALSE); |
8642 | 6.60k | crv = CKR_OK; |
8643 | 6.60k | } else |
8644 | 0 | crv = CKR_HOST_MEMORY; |
8645 | | |
8646 | 6.60k | break; |
8647 | 6.60k | } |
8648 | | |
8649 | 42.9k | case CKM_ECDH1_DERIVE: |
8650 | 42.9k | case CKM_ECDH1_COFACTOR_DERIVE: { |
8651 | 42.9k | SECItem ecScalar, ecPoint; |
8652 | 42.9k | SECItem tmp; |
8653 | 42.9k | PRBool withCofactor = PR_FALSE; |
8654 | 42.9k | unsigned char *secret; |
8655 | 42.9k | unsigned char *keyData = NULL; |
8656 | 42.9k | unsigned int secretlen, pubKeyLen; |
8657 | 42.9k | CK_ECDH1_DERIVE_PARAMS *mechParams; |
8658 | 42.9k | NSSLOWKEYPrivateKey *privKey; |
8659 | 42.9k | PLArenaPool *arena = NULL; |
8660 | | |
8661 | | /* Check mechanism parameters */ |
8662 | 42.9k | mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter; |
8663 | 42.9k | if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) || |
8664 | 42.9k | ((mechParams->kdf == CKD_NULL) && |
8665 | 42.9k | ((mechParams->ulSharedDataLen != 0) || |
8666 | 42.9k | (mechParams->pSharedData != NULL)))) { |
8667 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8668 | 0 | break; |
8669 | 0 | } |
8670 | | |
8671 | 42.9k | privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv); |
8672 | 42.9k | if (privKey == NULL) { |
8673 | 0 | break; |
8674 | 0 | } |
8675 | | |
8676 | | /* Now we are working with a non-NULL private key */ |
8677 | 42.9k | SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); |
8678 | | |
8679 | 42.9k | ecPoint.data = mechParams->pPublicData; |
8680 | 42.9k | ecPoint.len = mechParams->ulPublicDataLen; |
8681 | | |
8682 | 42.9k | pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams); |
8683 | | |
8684 | | /* if the len is too large, might be an encoded point */ |
8685 | 42.9k | if (ecPoint.len > pubKeyLen) { |
8686 | 15.6k | SECItem newPoint; |
8687 | | |
8688 | 15.6k | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
8689 | 15.6k | if (arena == NULL) { |
8690 | 0 | goto ec_loser; |
8691 | 0 | } |
8692 | | |
8693 | 15.6k | rv = SEC_QuickDERDecodeItem(arena, &newPoint, |
8694 | 15.6k | SEC_ASN1_GET(SEC_OctetStringTemplate), |
8695 | 15.6k | &ecPoint); |
8696 | 15.6k | if (rv != SECSuccess) { |
8697 | 135 | goto ec_loser; |
8698 | 135 | } |
8699 | 15.5k | ecPoint = newPoint; |
8700 | 15.5k | } |
8701 | | |
8702 | 42.7k | if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) { |
8703 | 0 | withCofactor = PR_TRUE; |
8704 | 0 | } |
8705 | | |
8706 | 42.7k | rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, |
8707 | 42.7k | withCofactor, &tmp); |
8708 | 42.7k | SECITEM_ZfreeItem(&ecScalar, PR_FALSE); |
8709 | 42.7k | ecScalar.data = NULL; |
8710 | 42.7k | if (privKey != sourceKey->objectInfo) { |
8711 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
8712 | 0 | privKey = NULL; |
8713 | 0 | } |
8714 | 42.7k | if (arena) { |
8715 | 15.5k | PORT_FreeArena(arena, PR_FALSE); |
8716 | 15.5k | arena = NULL; |
8717 | 15.5k | } |
8718 | | |
8719 | 42.7k | if (rv != SECSuccess) { |
8720 | 3.20k | crv = sftk_MapCryptError(PORT_GetError()); |
8721 | 3.20k | break; |
8722 | 3.20k | } |
8723 | | |
8724 | | /* |
8725 | | * apply the kdf function. |
8726 | | */ |
8727 | 39.5k | if (mechParams->kdf == CKD_NULL) { |
8728 | | /* |
8729 | | * tmp is the raw data created by ECDH_Derive, |
8730 | | * secret and secretlen are the values we will |
8731 | | * eventually pass as our generated key. |
8732 | | */ |
8733 | 39.5k | secret = tmp.data; |
8734 | 39.5k | secretlen = tmp.len; |
8735 | 39.5k | } else { |
8736 | 0 | secretlen = keySize; |
8737 | 0 | crv = sftk_ANSI_X9_63_kdf(&secret, keySize, |
8738 | 0 | &tmp, mechParams->pSharedData, |
8739 | 0 | mechParams->ulSharedDataLen, mechParams->kdf); |
8740 | 0 | PORT_ZFree(tmp.data, tmp.len); |
8741 | 0 | if (crv != CKR_OK) { |
8742 | 0 | break; |
8743 | 0 | } |
8744 | 0 | tmp.data = secret; |
8745 | 0 | tmp.len = secretlen; |
8746 | 0 | } |
8747 | | |
8748 | | /* |
8749 | | * if keySize is supplied, then we are generating a key of a specific |
8750 | | * length. This is done by taking the least significant 'keySize' |
8751 | | * bytes from the unsigned value calculated by ECDH. Note: this may |
8752 | | * mean padding temp with extra leading zeros from what ECDH_Derive |
8753 | | * already returned (which itself may contain leading zeros). |
8754 | | */ |
8755 | 39.5k | if (keySize) { |
8756 | 39.5k | if (secretlen < keySize) { |
8757 | 34.8k | keyData = PORT_ZAlloc(keySize); |
8758 | 34.8k | if (!keyData) { |
8759 | 0 | PORT_ZFree(tmp.data, tmp.len); |
8760 | 0 | crv = CKR_HOST_MEMORY; |
8761 | 0 | break; |
8762 | 0 | } |
8763 | 34.8k | PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen); |
8764 | 34.8k | secret = keyData; |
8765 | 34.8k | } else { |
8766 | 4.76k | secret += (secretlen - keySize); |
8767 | 4.76k | } |
8768 | 39.5k | secretlen = keySize; |
8769 | 39.5k | } |
8770 | | |
8771 | 39.5k | sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); |
8772 | 39.5k | PORT_ZFree(tmp.data, tmp.len); |
8773 | 39.5k | if (keyData) { |
8774 | 34.8k | PORT_ZFree(keyData, keySize); |
8775 | 34.8k | } |
8776 | 39.5k | break; |
8777 | | |
8778 | 135 | ec_loser: |
8779 | 135 | crv = CKR_ARGUMENTS_BAD; |
8780 | 135 | SECITEM_ZfreeItem(&ecScalar, PR_FALSE); |
8781 | 135 | if (privKey != sourceKey->objectInfo) |
8782 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
8783 | 135 | if (arena) { |
8784 | 135 | PORT_FreeArena(arena, PR_TRUE); |
8785 | 135 | } |
8786 | 135 | break; |
8787 | 39.5k | } |
8788 | | /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */ |
8789 | 0 | case CKM_NSS_HKDF_SHA1: |
8790 | 0 | hashMech = CKM_SHA_1; |
8791 | 0 | goto hkdf; |
8792 | 0 | case CKM_NSS_HKDF_SHA256: |
8793 | 0 | hashMech = CKM_SHA256; |
8794 | 0 | goto hkdf; |
8795 | 0 | case CKM_NSS_HKDF_SHA384: |
8796 | 0 | hashMech = CKM_SHA384; |
8797 | 0 | goto hkdf; |
8798 | 0 | case CKM_NSS_HKDF_SHA512: |
8799 | 0 | hashMech = CKM_SHA512; |
8800 | 0 | goto hkdf; |
8801 | 0 | hkdf : { |
8802 | 0 | const CK_NSS_HKDFParams *params = |
8803 | 0 | (const CK_NSS_HKDFParams *)pMechanism->pParameter; |
8804 | 0 | CK_HKDF_PARAMS hkdfParams; |
8805 | |
|
8806 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) { |
8807 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8808 | 0 | break; |
8809 | 0 | } |
8810 | 0 | hkdfParams.bExtract = params->bExtract; |
8811 | 0 | hkdfParams.bExpand = params->bExpand; |
8812 | 0 | if (params->pSalt) { |
8813 | 0 | hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA; |
8814 | 0 | } else { |
8815 | 0 | hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL; |
8816 | 0 | } |
8817 | 0 | hkdfParams.pSalt = params->pSalt; |
8818 | 0 | hkdfParams.ulSaltLen = params->ulSaltLen; |
8819 | 0 | hkdfParams.hSaltKey = CK_INVALID_HANDLE; |
8820 | 0 | hkdfParams.pInfo = params->pInfo; |
8821 | 0 | hkdfParams.ulInfoLen = params->ulInfoLen; |
8822 | 0 | hkdfParams.prfHashMechanism = hashMech; |
8823 | |
|
8824 | 0 | crv = sftk_HKDF(&hkdfParams, hSession, sourceKey, |
8825 | 0 | att->attrib.pValue, att->attrib.ulValueLen, |
8826 | 0 | key, NULL, keySize, PR_FALSE, isFIPS); |
8827 | 0 | } break; |
8828 | 18.0k | case CKM_HKDF_DERIVE: |
8829 | 21.3k | case CKM_HKDF_DATA: /* only difference is the class of key */ |
8830 | 21.3k | if ((pMechanism->pParameter == NULL) || |
8831 | 21.3k | (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) { |
8832 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8833 | 0 | break; |
8834 | 0 | } |
8835 | 21.3k | crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter, |
8836 | 21.3k | hSession, sourceKey, att->attrib.pValue, |
8837 | 21.3k | att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE, |
8838 | 21.3k | isFIPS); |
8839 | 21.3k | break; |
8840 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA1: |
8841 | 0 | hashType = HASH_AlgSHA1; |
8842 | 0 | goto jpake2; |
8843 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA256: |
8844 | 0 | hashType = HASH_AlgSHA256; |
8845 | 0 | goto jpake2; |
8846 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA384: |
8847 | 0 | hashType = HASH_AlgSHA384; |
8848 | 0 | goto jpake2; |
8849 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA512: |
8850 | 0 | hashType = HASH_AlgSHA512; |
8851 | 0 | goto jpake2; |
8852 | 0 | jpake2: |
8853 | 0 | if (pMechanism->pParameter == NULL || |
8854 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params)) |
8855 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8856 | 0 | if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN)) |
8857 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8858 | 0 | if (crv == CKR_OK) |
8859 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8860 | 0 | if (crv == CKR_OK) |
8861 | 0 | crv = jpake_Round2(hashType, |
8862 | 0 | (CK_NSS_JPAKERound2Params *)pMechanism->pParameter, |
8863 | 0 | sourceKey, key); |
8864 | 0 | break; |
8865 | | |
8866 | 0 | case CKM_NSS_JPAKE_FINAL_SHA1: |
8867 | 0 | hashType = HASH_AlgSHA1; |
8868 | 0 | goto jpakeFinal; |
8869 | 0 | case CKM_NSS_JPAKE_FINAL_SHA256: |
8870 | 0 | hashType = HASH_AlgSHA256; |
8871 | 0 | goto jpakeFinal; |
8872 | 0 | case CKM_NSS_JPAKE_FINAL_SHA384: |
8873 | 0 | hashType = HASH_AlgSHA384; |
8874 | 0 | goto jpakeFinal; |
8875 | 0 | case CKM_NSS_JPAKE_FINAL_SHA512: |
8876 | 0 | hashType = HASH_AlgSHA512; |
8877 | 0 | goto jpakeFinal; |
8878 | 0 | jpakeFinal: |
8879 | 0 | if (pMechanism->pParameter == NULL || |
8880 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams)) |
8881 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8882 | | /* We purposely do not do the derive sensitivity check; we want to be |
8883 | | able to derive non-sensitive keys while allowing the ROUND1 and |
8884 | | ROUND2 keys to be sensitive (which they always are, since they are |
8885 | | in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE |
8886 | | in the template in order for the resultant keyblock key to be |
8887 | | sensitive. |
8888 | | */ |
8889 | 0 | if (crv == CKR_OK) |
8890 | 0 | crv = jpake_Final(hashType, |
8891 | 0 | (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter, |
8892 | 0 | sourceKey, key); |
8893 | 0 | break; |
8894 | | |
8895 | 0 | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
8896 | 0 | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
8897 | 0 | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */ |
8898 | 0 | case CKM_SP800_108_COUNTER_KDF: /* fall through */ |
8899 | 0 | case CKM_SP800_108_FEEDBACK_KDF: /* fall through */ |
8900 | 0 | case CKM_SP800_108_DOUBLE_PIPELINE_KDF: |
8901 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8902 | 0 | if (crv != CKR_OK) { |
8903 | 0 | break; |
8904 | 0 | } |
8905 | | |
8906 | 0 | crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize); |
8907 | 0 | break; |
8908 | 0 | default: |
8909 | 0 | crv = CKR_MECHANISM_INVALID; |
8910 | 84.6k | } |
8911 | 84.6k | if (att) { |
8912 | 84.6k | sftk_FreeAttribute(att); |
8913 | 84.6k | } |
8914 | 84.6k | sftk_FreeObject(sourceKey); |
8915 | 84.6k | if (crv != CKR_OK) { |
8916 | 3.34k | if (key) |
8917 | 3.34k | sftk_FreeObject(key); |
8918 | 3.34k | return crv; |
8919 | 3.34k | } |
8920 | | |
8921 | | /* link the key object into the list */ |
8922 | 81.3k | if (key) { |
8923 | 74.4k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
8924 | 74.4k | PORT_Assert(sessKey); |
8925 | | /* get the session */ |
8926 | 74.4k | sessKey->wasDerived = PR_TRUE; |
8927 | 74.4k | session = sftk_SessionFromHandle(hSession); |
8928 | 74.4k | if (session == NULL) { |
8929 | 0 | sftk_FreeObject(key); |
8930 | 0 | return CKR_HOST_MEMORY; |
8931 | 0 | } |
8932 | | |
8933 | 74.4k | crv = sftk_handleObject(key, session); |
8934 | 74.4k | session->lastOpWasFIPS = key->isFIPS; |
8935 | 74.4k | sftk_FreeSession(session); |
8936 | 74.4k | *phKey = key->handle; |
8937 | 74.4k | sftk_FreeObject(key); |
8938 | 74.4k | } |
8939 | 81.3k | return crv; |
8940 | 81.3k | } |
8941 | | |
8942 | | /* NSC_GetFunctionStatus obtains an updated status of a function running |
8943 | | * in parallel with an application. */ |
8944 | | CK_RV |
8945 | | NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) |
8946 | 0 | { |
8947 | 0 | CHECK_FORK(); |
8948 | |
|
8949 | 0 | return CKR_FUNCTION_NOT_PARALLEL; |
8950 | 0 | } |
8951 | | |
8952 | | /* NSC_CancelFunction cancels a function running in parallel */ |
8953 | | CK_RV |
8954 | | NSC_CancelFunction(CK_SESSION_HANDLE hSession) |
8955 | 0 | { |
8956 | 0 | CHECK_FORK(); |
8957 | |
|
8958 | 0 | return CKR_FUNCTION_NOT_PARALLEL; |
8959 | 0 | } |
8960 | | |
8961 | | /* NSC_GetOperationState saves the state of the cryptographic |
8962 | | * operation in a session. |
8963 | | * NOTE: This code only works for digest functions for now. eventually need |
8964 | | * to add full flatten/resurect to our state stuff so that all types of state |
8965 | | * can be saved */ |
8966 | | CK_RV |
8967 | | NSC_GetOperationState(CK_SESSION_HANDLE hSession, |
8968 | | CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) |
8969 | 26.7k | { |
8970 | 26.7k | SFTKSessionContext *context; |
8971 | 26.7k | SFTKSession *session; |
8972 | 26.7k | CK_RV crv; |
8973 | 26.7k | CK_ULONG pOSLen = *pulOperationStateLen; |
8974 | | |
8975 | 26.7k | CHECK_FORK(); |
8976 | | |
8977 | | /* make sure we're legal */ |
8978 | 26.7k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
8979 | 26.7k | if (crv != CKR_OK) |
8980 | 0 | return crv; |
8981 | | |
8982 | | /* a zero cipherInfoLen signals that this context cannot be serialized */ |
8983 | 26.7k | if (context->cipherInfoLen == 0) { |
8984 | 0 | return CKR_STATE_UNSAVEABLE; |
8985 | 0 | } |
8986 | | |
8987 | 26.7k | *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType); |
8988 | 26.7k | if (pOperationState == NULL) { |
8989 | 7.06k | sftk_FreeSession(session); |
8990 | 7.06k | return CKR_OK; |
8991 | 19.6k | } else { |
8992 | 19.6k | if (pOSLen < *pulOperationStateLen) { |
8993 | 0 | return CKR_BUFFER_TOO_SMALL; |
8994 | 0 | } |
8995 | 19.6k | } |
8996 | 19.6k | PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType)); |
8997 | 19.6k | pOperationState += sizeof(SFTKContextType); |
8998 | 19.6k | PORT_Memcpy(pOperationState, &context->currentMech, |
8999 | 19.6k | sizeof(CK_MECHANISM_TYPE)); |
9000 | 19.6k | pOperationState += sizeof(CK_MECHANISM_TYPE); |
9001 | 19.6k | PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen); |
9002 | 19.6k | sftk_FreeSession(session); |
9003 | 19.6k | return CKR_OK; |
9004 | 26.7k | } |
9005 | | |
9006 | | #define sftk_Decrement(stateSize, len) \ |
9007 | 58.9k | stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0; |
9008 | | |
9009 | | /* NSC_SetOperationState restores the state of the cryptographic |
9010 | | * operation in a session. This is coded like it can restore lots of |
9011 | | * states, but it only works for truly flat cipher structures. */ |
9012 | | CK_RV |
9013 | | NSC_SetOperationState(CK_SESSION_HANDLE hSession, |
9014 | | CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, |
9015 | | CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) |
9016 | 19.6k | { |
9017 | 19.6k | SFTKSessionContext *context; |
9018 | 19.6k | SFTKSession *session; |
9019 | 19.6k | SFTKContextType type; |
9020 | 19.6k | CK_MECHANISM mech; |
9021 | 19.6k | CK_RV crv = CKR_OK; |
9022 | | |
9023 | 19.6k | CHECK_FORK(); |
9024 | | |
9025 | 39.2k | while (ulOperationStateLen != 0) { |
9026 | | /* get what type of state we're dealing with... */ |
9027 | 19.6k | PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType)); |
9028 | | |
9029 | | /* fix up session contexts based on type */ |
9030 | 19.6k | session = sftk_SessionFromHandle(hSession); |
9031 | 19.6k | if (session == NULL) |
9032 | 0 | return CKR_SESSION_HANDLE_INVALID; |
9033 | 19.6k | context = sftk_ReturnContextByType(session, type); |
9034 | 19.6k | sftk_SetContextByType(session, type, NULL); |
9035 | 19.6k | if (context) { |
9036 | 7.06k | sftk_FreeContext(context); |
9037 | 7.06k | } |
9038 | 19.6k | pOperationState += sizeof(SFTKContextType); |
9039 | 19.6k | sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType)); |
9040 | | |
9041 | | /* get the mechanism structure */ |
9042 | 19.6k | PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE)); |
9043 | 19.6k | pOperationState += sizeof(CK_MECHANISM_TYPE); |
9044 | 19.6k | sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE)); |
9045 | | /* should be filled in... but not necessary for hash */ |
9046 | 19.6k | mech.pParameter = NULL; |
9047 | 19.6k | mech.ulParameterLen = 0; |
9048 | 19.6k | switch (type) { |
9049 | 19.6k | case SFTK_HASH: |
9050 | 19.6k | crv = NSC_DigestInit(hSession, &mech); |
9051 | 19.6k | if (crv != CKR_OK) |
9052 | 0 | break; |
9053 | 19.6k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, |
9054 | 19.6k | NULL); |
9055 | 19.6k | if (crv != CKR_OK) |
9056 | 0 | break; |
9057 | 19.6k | if (context->cipherInfoLen == 0) { |
9058 | 0 | crv = CKR_SAVED_STATE_INVALID; |
9059 | 0 | break; |
9060 | 0 | } |
9061 | 19.6k | PORT_Memcpy(context->cipherInfo, pOperationState, |
9062 | 19.6k | context->cipherInfoLen); |
9063 | 19.6k | pOperationState += context->cipherInfoLen; |
9064 | 19.6k | sftk_Decrement(ulOperationStateLen, context->cipherInfoLen); |
9065 | 19.6k | break; |
9066 | 0 | default: |
9067 | | /* do sign/encrypt/decrypt later */ |
9068 | 0 | crv = CKR_SAVED_STATE_INVALID; |
9069 | 19.6k | } |
9070 | 19.6k | sftk_FreeSession(session); |
9071 | 19.6k | if (crv != CKR_OK) |
9072 | 0 | break; |
9073 | 19.6k | } |
9074 | 19.6k | return crv; |
9075 | 19.6k | } |
9076 | | |
9077 | | /* Dual-function cryptographic operations */ |
9078 | | |
9079 | | /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption |
9080 | | * operation. */ |
9081 | | CK_RV |
9082 | | NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
9083 | | CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
9084 | | CK_ULONG_PTR pulEncryptedPartLen) |
9085 | 0 | { |
9086 | 0 | CK_RV crv; |
9087 | |
|
9088 | 0 | CHECK_FORK(); |
9089 | |
|
9090 | 0 | crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, |
9091 | 0 | pulEncryptedPartLen); |
9092 | 0 | if (crv != CKR_OK) |
9093 | 0 | return crv; |
9094 | 0 | crv = NSC_DigestUpdate(hSession, pPart, ulPartLen); |
9095 | |
|
9096 | 0 | return crv; |
9097 | 0 | } |
9098 | | |
9099 | | /* NSC_DecryptDigestUpdate continues a multiple-part decryption and |
9100 | | * digesting operation. */ |
9101 | | CK_RV |
9102 | | NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, |
9103 | | CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
9104 | | CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
9105 | 0 | { |
9106 | 0 | CK_RV crv; |
9107 | |
|
9108 | 0 | CHECK_FORK(); |
9109 | |
|
9110 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen, |
9111 | 0 | pPart, pulPartLen); |
9112 | 0 | if (crv != CKR_OK) |
9113 | 0 | return crv; |
9114 | 0 | crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen); |
9115 | |
|
9116 | 0 | return crv; |
9117 | 0 | } |
9118 | | |
9119 | | /* NSC_SignEncryptUpdate continues a multiple-part signing and |
9120 | | * encryption operation. */ |
9121 | | CK_RV |
9122 | | NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
9123 | | CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
9124 | | CK_ULONG_PTR pulEncryptedPartLen) |
9125 | 0 | { |
9126 | 0 | CK_RV crv; |
9127 | |
|
9128 | 0 | CHECK_FORK(); |
9129 | |
|
9130 | 0 | crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, |
9131 | 0 | pulEncryptedPartLen); |
9132 | 0 | if (crv != CKR_OK) |
9133 | 0 | return crv; |
9134 | 0 | crv = NSC_SignUpdate(hSession, pPart, ulPartLen); |
9135 | |
|
9136 | 0 | return crv; |
9137 | 0 | } |
9138 | | |
9139 | | /* NSC_DecryptVerifyUpdate continues a multiple-part decryption |
9140 | | * and verify operation. */ |
9141 | | CK_RV |
9142 | | NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, |
9143 | | CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, |
9144 | | CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
9145 | 0 | { |
9146 | 0 | CK_RV crv; |
9147 | |
|
9148 | 0 | CHECK_FORK(); |
9149 | |
|
9150 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, |
9151 | 0 | pData, pulDataLen); |
9152 | 0 | if (crv != CKR_OK) |
9153 | 0 | return crv; |
9154 | 0 | crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen); |
9155 | |
|
9156 | 0 | return crv; |
9157 | 0 | } |
9158 | | |
9159 | | /* NSC_DigestKey continues a multi-part message-digesting operation, |
9160 | | * by digesting the value of a secret key as part of the data already digested. |
9161 | | */ |
9162 | | CK_RV |
9163 | | NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) |
9164 | 0 | { |
9165 | 0 | SFTKSession *session = NULL; |
9166 | 0 | SFTKObject *key = NULL; |
9167 | 0 | SFTKAttribute *att; |
9168 | 0 | CK_RV crv; |
9169 | |
|
9170 | 0 | CHECK_FORK(); |
9171 | |
|
9172 | 0 | session = sftk_SessionFromHandle(hSession); |
9173 | 0 | if (session == NULL) |
9174 | 0 | return CKR_SESSION_HANDLE_INVALID; |
9175 | | |
9176 | 0 | key = sftk_ObjectFromHandle(hKey, session); |
9177 | 0 | sftk_FreeSession(session); |
9178 | 0 | if (key == NULL) |
9179 | 0 | return CKR_KEY_HANDLE_INVALID; |
9180 | | |
9181 | | /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */ |
9182 | | |
9183 | | /* make sure it's a valid key for this operation */ |
9184 | 0 | if (key->objclass != CKO_SECRET_KEY) { |
9185 | 0 | sftk_FreeObject(key); |
9186 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
9187 | 0 | } |
9188 | | /* get the key value */ |
9189 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
9190 | 0 | sftk_FreeObject(key); |
9191 | 0 | if (!att) { |
9192 | 0 | return CKR_KEY_HANDLE_INVALID; |
9193 | 0 | } |
9194 | 0 | crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue, |
9195 | 0 | att->attrib.ulValueLen); |
9196 | 0 | sftk_FreeAttribute(att); |
9197 | 0 | return crv; |
9198 | 0 | } |