1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
22 * Dr Stephen Henson <stephen.henson@gemplus.com>
23 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 * This file implements PKCS 11 on top of our existing security modules
41 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
42 * This implementation has two slots:
43 * slot 1 is our generic crypto support. It does not require login.
44 * It supports Public Key ops, and all they bulk ciphers and hashes.
45 * It can also support Private Key ops for imported Private keys. It does
46 * not have any token storage.
47 * slot 2 is our private key support. It requires a login before use. It
48 * can store Private Keys and Certs as token objects. Currently only private
49 * keys and their associated Certificates are saved on the token.
51 * In this implementation, session objects are only visible to the session
52 * that created or generated them.
64 #include "lowpbe.h" /* We do PBE below */
74 #define __PASTE(x,y) x##y
77 * we renamed all our internal functions, get the correct
78 * definitions for them...
80 #undef CK_PKCS11_FUNCTION_INFO
81 #undef CK_NEED_ARG_LIST
83 #define CK_EXTERN extern
84 #define CK_PKCS11_FUNCTION_INFO(func) \
85 CK_RV __PASTE(NS,func)
86 #define CK_NEED_ARG_LIST 1
91 uint8 client_version
[2];
93 } SSL3RSAPreMasterSecret
;
95 static void sftk_Null(void *data
, PRBool freeit
)
100 #ifdef NSS_ENABLE_ECC
102 #define SEC_PRINT(str1, str2, num, sitem) \
103 printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
104 str1, str2, num, sitem->len); \
105 for (i = 0; i < sitem->len; i++) { \
106 printf("%02x:", sitem->data[i]); \
110 #define SEC_PRINT(a, b, c, d)
112 #endif /* NSS_ENABLE_ECC */
115 * free routines.... Free local type allocated data, and convert
116 * other free routines to the destroy signature.
119 sftk_FreePrivKey(NSSLOWKEYPrivateKey
*key
, PRBool freeit
)
121 nsslowkey_DestroyPrivateKey(key
);
125 sftk_Space(void *data
, PRBool freeit
)
132 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
133 * Deprecating a full des key to 40 bit key strenth.
136 sftk_cdmf2des(unsigned char *cdmfkey
, unsigned char *deskey
)
138 unsigned char key1
[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
139 unsigned char key2
[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
140 unsigned char enc_src
[8];
141 unsigned char enc_dest
[8];
147 /* zero the parity bits */
148 for (i
=0; i
< 8; i
++) {
149 enc_src
[i
] = cdmfkey
[i
] & 0xfe;
152 /* encrypt with key 1 */
153 descx
= DES_CreateContext(key1
, NULL
, NSS_DES
, PR_TRUE
);
154 if (descx
== NULL
) return CKR_HOST_MEMORY
;
155 rv
= DES_Encrypt(descx
, enc_dest
, &leng
, 8, enc_src
, 8);
156 DES_DestroyContext(descx
,PR_TRUE
);
157 if (rv
!= SECSuccess
) return CKR_DEVICE_ERROR
;
159 /* xor source with des, zero the parity bits and deprecate the key*/
160 for (i
=0; i
< 8; i
++) {
162 enc_src
[i
] = (enc_src
[i
] ^ enc_dest
[i
]) & 0xfe;
164 enc_src
[i
] = (enc_src
[i
] ^ enc_dest
[i
]) & 0x0e;
168 /* encrypt with key 2 */
169 descx
= DES_CreateContext(key2
, NULL
, NSS_DES
, PR_TRUE
);
170 if (descx
== NULL
) return CKR_HOST_MEMORY
;
171 rv
= DES_Encrypt(descx
, deskey
, &leng
, 8, enc_src
, 8);
172 DES_DestroyContext(descx
,PR_TRUE
);
173 if (rv
!= SECSuccess
) return CKR_DEVICE_ERROR
;
175 /* set the corret parity on our new des key */
176 sftk_FormatDESKey(deskey
, 8);
181 /* NSC_DestroyObject destroys an object. */
183 NSC_DestroyObject(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
)
185 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
186 SFTKSession
*session
;
188 SFTKFreeStatus status
;
193 return CKR_SESSION_HANDLE_INVALID
;
196 * This whole block just makes sure we really can destroy the
199 session
= sftk_SessionFromHandle(hSession
);
200 if (session
== NULL
) {
201 return CKR_SESSION_HANDLE_INVALID
;
204 object
= sftk_ObjectFromHandle(hObject
,session
);
205 if (object
== NULL
) {
206 sftk_FreeSession(session
);
207 return CKR_OBJECT_HANDLE_INVALID
;
210 /* don't destroy a private object if we aren't logged in */
211 if ((!slot
->isLoggedIn
) && (slot
->needLogin
) &&
212 (sftk_isTrue(object
,CKA_PRIVATE
))) {
213 sftk_FreeSession(session
);
214 sftk_FreeObject(object
);
215 return CKR_USER_NOT_LOGGED_IN
;
218 /* don't destroy a token object if we aren't in a rw session */
220 if (((session
->info
.flags
& CKF_RW_SESSION
) == 0) &&
221 (sftk_isTrue(object
,CKA_TOKEN
))) {
222 sftk_FreeSession(session
);
223 sftk_FreeObject(object
);
224 return CKR_SESSION_READ_ONLY
;
227 sftk_DeleteObject(session
,object
);
229 sftk_FreeSession(session
);
232 * get some indication if the object is destroyed. Note: this is not
233 * 100%. Someone may have an object reference outstanding (though that
234 * should not be the case by here. Also note that the object is "half"
235 * destroyed. Our internal representation is destroyed, but it may still
236 * be in the data base.
238 status
= sftk_FreeObject(object
);
240 return (status
!= SFTK_DestroyFailure
) ? CKR_OK
: CKR_DEVICE_ERROR
;
245 ************** Crypto Functions: Utilities ************************
250 * map SEC_ERROR_xxx to CKR_xxx.
253 sftk_MapCryptError(int error
)
256 case SEC_ERROR_INVALID_ARGS
:
257 return CKR_ARGUMENTS_BAD
;
258 case SEC_ERROR_INPUT_LEN
:
259 return CKR_DATA_LEN_RANGE
;
260 case SEC_ERROR_OUTPUT_LEN
:
261 return CKR_BUFFER_TOO_SMALL
;
263 return CKR_DEVICE_ERROR
;
267 * return a context based on the SFTKContext type.
270 sftk_ReturnContextByType(SFTKSession
*session
, SFTKContextType type
)
275 return session
->enc_context
;
277 return session
->hash_context
;
279 case SFTK_SIGN_RECOVER
:
281 case SFTK_VERIFY_RECOVER
:
282 return session
->hash_context
;
288 * change a context based on the SFTKContext type.
291 sftk_SetContextByType(SFTKSession
*session
, SFTKContextType type
,
292 SFTKSessionContext
*context
)
297 session
->enc_context
= context
;
300 session
->hash_context
= context
;
303 case SFTK_SIGN_RECOVER
:
305 case SFTK_VERIFY_RECOVER
:
306 session
->hash_context
= context
;
313 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
314 * and C_XXX function. The function takes a session handle, the context type,
315 * and wether or not the session needs to be multipart. It returns the context,
316 * and optionally returns the session pointer (if sessionPtr != NULL) if session
317 * pointer is returned, the caller is responsible for freeing it.
320 sftk_GetContext(CK_SESSION_HANDLE handle
,SFTKSessionContext
**contextPtr
,
321 SFTKContextType type
, PRBool needMulti
, SFTKSession
**sessionPtr
)
323 SFTKSession
*session
;
324 SFTKSessionContext
*context
;
326 session
= sftk_SessionFromHandle(handle
);
327 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
328 context
= sftk_ReturnContextByType(session
,type
);
329 /* make sure the context is valid */
330 if((context
==NULL
)||(context
->type
!=type
)||(needMulti
&&!(context
->multi
))){
331 sftk_FreeSession(session
);
332 return CKR_OPERATION_NOT_INITIALIZED
;
334 *contextPtr
= context
;
335 if (sessionPtr
!= NULL
) {
336 *sessionPtr
= session
;
338 sftk_FreeSession(session
);
344 ************** Crypto Functions: Encrypt ************************
348 * All the NSC_InitXXX functions have a set of common checks and processing they
349 * all need to do at the beginning. This is done here.
352 sftk_InitGeneric(SFTKSession
*session
,SFTKSessionContext
**contextPtr
,
353 SFTKContextType ctype
,SFTKObject
**keyPtr
,
354 CK_OBJECT_HANDLE hKey
, CK_KEY_TYPE
*keyTypePtr
,
355 CK_OBJECT_CLASS pubKeyType
, CK_ATTRIBUTE_TYPE operation
)
357 SFTKObject
*key
= NULL
;
359 SFTKSessionContext
*context
;
361 /* We can only init if there is not current context active */
362 if (sftk_ReturnContextByType(session
,ctype
) != NULL
) {
363 return CKR_OPERATION_ACTIVE
;
368 key
= sftk_ObjectFromHandle(hKey
,session
);
370 return CKR_KEY_HANDLE_INVALID
;
373 /* make sure it's a valid key for this operation */
374 if (((key
->objclass
!= CKO_SECRET_KEY
) && (key
->objclass
!= pubKeyType
))
375 || !sftk_isTrue(key
,operation
)) {
376 sftk_FreeObject(key
);
377 return CKR_KEY_TYPE_INCONSISTENT
;
379 /* get the key type */
380 att
= sftk_FindAttribute(key
,CKA_KEY_TYPE
);
382 sftk_FreeObject(key
);
383 return CKR_KEY_TYPE_INCONSISTENT
;
385 PORT_Assert(att
->attrib
.ulValueLen
== sizeof(CK_KEY_TYPE
));
386 if (att
->attrib
.ulValueLen
!= sizeof(CK_KEY_TYPE
)) {
387 sftk_FreeAttribute(att
);
388 sftk_FreeObject(key
);
389 return CKR_ATTRIBUTE_VALUE_INVALID
;
391 PORT_Memcpy(keyTypePtr
, att
->attrib
.pValue
, sizeof(CK_KEY_TYPE
));
392 sftk_FreeAttribute(att
);
396 /* allocate the context structure */
397 context
= (SFTKSessionContext
*)PORT_Alloc(sizeof(SFTKSessionContext
));
398 if (context
== NULL
) {
399 if (key
) sftk_FreeObject(key
);
400 return CKR_HOST_MEMORY
;
402 context
->type
= ctype
;
403 context
->multi
= PR_TRUE
;
404 context
->cipherInfo
= NULL
;
405 context
->hashInfo
= NULL
;
406 context
->doPad
= PR_FALSE
;
407 context
->padDataLength
= 0;
409 context
->blockSize
= 0;
411 *contextPtr
= context
;
415 /* NSC_CryptInit initializes an encryption/Decryption operation. */
416 /* This function is used by NSC_EncryptInit, NSC_DecryptInit,
417 * NSC_WrapKey, NSC_UnwrapKey,
418 * NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac),
419 * The only difference in their uses is the value of etype.
422 sftk_CryptInit(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
423 CK_OBJECT_HANDLE hKey
, CK_ATTRIBUTE_TYPE etype
,
424 SFTKContextType contextType
, PRBool isEncrypt
)
426 SFTKSession
*session
;
428 SFTKSessionContext
*context
;
430 CK_RC2_CBC_PARAMS
*rc2_param
;
431 #if NSS_SOFTOKEN_DOES_RC5
432 CK_RC5_CBC_PARAMS
*rc5_param
;
435 CK_KEY_TYPE key_type
;
437 unsigned effectiveKeyLength
;
438 unsigned char newdeskey
[24];
439 PRBool useNewKey
=PR_FALSE
;
442 crv
= sftk_MechAllowsOperation(pMechanism
->mechanism
, etype
);
446 session
= sftk_SessionFromHandle(hSession
);
447 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
449 crv
= sftk_InitGeneric(session
,&context
,contextType
,&key
,hKey
,&key_type
,
450 isEncrypt
?CKO_PUBLIC_KEY
:CKO_PRIVATE_KEY
, etype
);
453 sftk_FreeSession(session
);
457 context
->doPad
= PR_FALSE
;
458 switch(pMechanism
->mechanism
) {
461 if (key_type
!= CKK_RSA
) {
462 crv
= CKR_KEY_TYPE_INCONSISTENT
;
465 context
->multi
= PR_FALSE
;
467 NSSLOWKEYPublicKey
*pubKey
= sftk_GetPubKey(key
,CKK_RSA
,&crv
);
468 if (pubKey
== NULL
) {
471 context
->maxLen
= nsslowkey_PublicModulusLen(pubKey
);
472 context
->cipherInfo
= (void *)pubKey
;
473 context
->update
= (SFTKCipher
)
474 (pMechanism
->mechanism
== CKM_RSA_X_509
475 ? RSA_EncryptRaw
: RSA_EncryptBlock
);
477 NSSLOWKEYPrivateKey
*privKey
= sftk_GetPrivKey(key
,CKK_RSA
,&crv
);
478 if (privKey
== NULL
) {
481 context
->maxLen
= nsslowkey_PrivateModulusLen(privKey
);
482 context
->cipherInfo
= (void *)privKey
;
483 context
->update
= (SFTKCipher
)
484 (pMechanism
->mechanism
== CKM_RSA_X_509
485 ? RSA_DecryptRaw
: RSA_DecryptBlock
);
487 context
->destroy
= sftk_Null
;
489 case CKM_RC2_CBC_PAD
:
490 context
->doPad
= PR_TRUE
;
494 context
->blockSize
= 8;
495 if (key_type
!= CKK_RC2
) {
496 crv
= CKR_KEY_TYPE_INCONSISTENT
;
499 att
= sftk_FindAttribute(key
,CKA_VALUE
);
501 crv
= CKR_KEY_HANDLE_INVALID
;
504 rc2_param
= (CK_RC2_CBC_PARAMS
*)pMechanism
->pParameter
;
505 effectiveKeyLength
= (rc2_param
->ulEffectiveBits
+7)/8;
506 context
->cipherInfo
=
507 RC2_CreateContext((unsigned char*)att
->attrib
.pValue
,
508 att
->attrib
.ulValueLen
, rc2_param
->iv
,
509 pMechanism
->mechanism
== CKM_RC2_ECB
? NSS_RC2
:
510 NSS_RC2_CBC
,effectiveKeyLength
);
511 sftk_FreeAttribute(att
);
512 if (context
->cipherInfo
== NULL
) {
513 crv
= CKR_HOST_MEMORY
;
516 context
->update
= (SFTKCipher
) (isEncrypt
? RC2_Encrypt
: RC2_Decrypt
);
517 context
->destroy
= (SFTKDestroy
) RC2_DestroyContext
;
519 #if NSS_SOFTOKEN_DOES_RC5
520 case CKM_RC5_CBC_PAD
:
521 context
->doPad
= PR_TRUE
;
525 if (key_type
!= CKK_RC5
) {
526 crv
= CKR_KEY_TYPE_INCONSISTENT
;
529 att
= sftk_FindAttribute(key
,CKA_VALUE
);
531 crv
= CKR_KEY_HANDLE_INVALID
;
534 rc5_param
= (CK_RC5_CBC_PARAMS
*)pMechanism
->pParameter
;
535 context
->blockSize
= rc5_param
->ulWordsize
*2;
536 rc5Key
.data
= (unsigned char*)att
->attrib
.pValue
;
537 rc5Key
.len
= att
->attrib
.ulValueLen
;
538 context
->cipherInfo
= RC5_CreateContext(&rc5Key
,rc5_param
->ulRounds
,
539 rc5_param
->ulWordsize
,rc5_param
->pIv
,
540 pMechanism
->mechanism
== CKM_RC5_ECB
? NSS_RC5
: NSS_RC5_CBC
);
541 sftk_FreeAttribute(att
);
542 if (context
->cipherInfo
== NULL
) {
543 crv
= CKR_HOST_MEMORY
;
546 context
->update
= (SFTKCipher
) (isEncrypt
? RC5_Encrypt
: RC5_Decrypt
);
547 context
->destroy
= (SFTKDestroy
) RC5_DestroyContext
;
551 if (key_type
!= CKK_RC4
) {
552 crv
= CKR_KEY_TYPE_INCONSISTENT
;
555 att
= sftk_FindAttribute(key
,CKA_VALUE
);
557 crv
= CKR_KEY_HANDLE_INVALID
;
560 context
->cipherInfo
=
561 RC4_CreateContext((unsigned char*)att
->attrib
.pValue
,
562 att
->attrib
.ulValueLen
);
563 sftk_FreeAttribute(att
);
564 if (context
->cipherInfo
== NULL
) {
565 crv
= CKR_HOST_MEMORY
; /* WRONG !!! */
568 context
->update
= (SFTKCipher
) (isEncrypt
? RC4_Encrypt
: RC4_Decrypt
);
569 context
->destroy
= (SFTKDestroy
) RC4_DestroyContext
;
571 case CKM_CDMF_CBC_PAD
:
572 context
->doPad
= PR_TRUE
;
576 if (key_type
!= CKK_CDMF
) {
577 crv
= CKR_KEY_TYPE_INCONSISTENT
;
580 t
= (pMechanism
->mechanism
== CKM_CDMF_ECB
) ? NSS_DES
: NSS_DES_CBC
;
581 if (crv
!= CKR_OK
) break;
584 if (key_type
!= CKK_DES
) {
585 crv
= CKR_KEY_TYPE_INCONSISTENT
;
590 case CKM_DES_CBC_PAD
:
591 context
->doPad
= PR_TRUE
;
594 if (key_type
!= CKK_DES
) {
595 crv
= CKR_KEY_TYPE_INCONSISTENT
;
601 if ((key_type
!= CKK_DES2
) && (key_type
!= CKK_DES3
)) {
602 crv
= CKR_KEY_TYPE_INCONSISTENT
;
607 case CKM_DES3_CBC_PAD
:
608 context
->doPad
= PR_TRUE
;
611 if ((key_type
!= CKK_DES2
) && (key_type
!= CKK_DES3
)) {
612 crv
= CKR_KEY_TYPE_INCONSISTENT
;
615 t
= NSS_DES_EDE3_CBC
;
617 context
->blockSize
= 8;
618 att
= sftk_FindAttribute(key
,CKA_VALUE
);
620 crv
= CKR_KEY_HANDLE_INVALID
;
623 if (key_type
== CKK_DES2
&&
624 (t
== NSS_DES_EDE3_CBC
|| t
== NSS_DES_EDE3
)) {
625 /* extend DES2 key to DES3 key. */
626 memcpy(newdeskey
, att
->attrib
.pValue
, 16);
627 memcpy(newdeskey
+ 16, newdeskey
, 8);
629 } else if (key_type
== CKK_CDMF
) {
630 crv
= sftk_cdmf2des((unsigned char*)att
->attrib
.pValue
,newdeskey
);
632 sftk_FreeAttribute(att
);
637 context
->cipherInfo
= DES_CreateContext(
638 useNewKey
? newdeskey
: (unsigned char*)att
->attrib
.pValue
,
639 (unsigned char*)pMechanism
->pParameter
,t
, isEncrypt
);
641 memset(newdeskey
, 0, sizeof newdeskey
);
642 sftk_FreeAttribute(att
);
643 if (context
->cipherInfo
== NULL
) {
644 crv
= CKR_HOST_MEMORY
;
647 context
->update
= (SFTKCipher
) (isEncrypt
? DES_Encrypt
: DES_Decrypt
);
648 context
->destroy
= (SFTKDestroy
) DES_DestroyContext
;
651 case CKM_CAMELLIA_CBC_PAD
:
652 context
->doPad
= PR_TRUE
;
654 case CKM_CAMELLIA_CBC
:
655 if (!pMechanism
->pParameter
||
656 pMechanism
->ulParameterLen
!= 16) {
657 crv
= CKR_MECHANISM_PARAM_INVALID
;
661 case CKM_CAMELLIA_ECB
:
662 context
->blockSize
= 16;
663 if (key_type
!= CKK_CAMELLIA
) {
664 crv
= CKR_KEY_TYPE_INCONSISTENT
;
667 att
= sftk_FindAttribute(key
,CKA_VALUE
);
669 crv
= CKR_KEY_HANDLE_INVALID
;
672 context
->cipherInfo
= Camellia_CreateContext(
673 (unsigned char*)att
->attrib
.pValue
,
674 (unsigned char*)pMechanism
->pParameter
,
675 pMechanism
->mechanism
==
676 CKM_CAMELLIA_ECB
? NSS_CAMELLIA
: NSS_CAMELLIA_CBC
,
677 isEncrypt
, att
->attrib
.ulValueLen
);
678 sftk_FreeAttribute(att
);
679 if (context
->cipherInfo
== NULL
) {
680 crv
= CKR_HOST_MEMORY
;
683 context
->update
= (SFTKCipher
) (isEncrypt
?
684 Camellia_Encrypt
: Camellia_Decrypt
);
685 context
->destroy
= (SFTKDestroy
) Camellia_DestroyContext
;
688 case CKM_AES_CBC_PAD
:
689 context
->doPad
= PR_TRUE
;
693 context
->blockSize
= 16;
694 if (key_type
!= CKK_AES
) {
695 crv
= CKR_KEY_TYPE_INCONSISTENT
;
698 att
= sftk_FindAttribute(key
,CKA_VALUE
);
700 crv
= CKR_KEY_HANDLE_INVALID
;
703 context
->cipherInfo
= AES_CreateContext(
704 (unsigned char*)att
->attrib
.pValue
,
705 (unsigned char*)pMechanism
->pParameter
,
706 pMechanism
->mechanism
== CKM_AES_ECB
? NSS_AES
: NSS_AES_CBC
,
707 isEncrypt
, att
->attrib
.ulValueLen
, 16);
708 sftk_FreeAttribute(att
);
709 if (context
->cipherInfo
== NULL
) {
710 crv
= CKR_HOST_MEMORY
;
713 context
->update
= (SFTKCipher
) (isEncrypt
? AES_Encrypt
: AES_Decrypt
);
714 context
->destroy
= (SFTKDestroy
) AES_DestroyContext
;
717 case CKM_NETSCAPE_AES_KEY_WRAP_PAD
:
718 context
->doPad
= PR_TRUE
;
720 case CKM_NETSCAPE_AES_KEY_WRAP
:
721 context
->multi
= PR_FALSE
;
722 context
->blockSize
= 8;
723 if (key_type
!= CKK_AES
) {
724 crv
= CKR_KEY_TYPE_INCONSISTENT
;
727 att
= sftk_FindAttribute(key
,CKA_VALUE
);
729 crv
= CKR_KEY_HANDLE_INVALID
;
732 context
->cipherInfo
= AESKeyWrap_CreateContext(
733 (unsigned char*)att
->attrib
.pValue
,
734 (unsigned char*)pMechanism
->pParameter
,
735 isEncrypt
, att
->attrib
.ulValueLen
);
736 sftk_FreeAttribute(att
);
737 if (context
->cipherInfo
== NULL
) {
738 crv
= CKR_HOST_MEMORY
;
741 context
->update
= (SFTKCipher
) (isEncrypt
? AESKeyWrap_Encrypt
742 : AESKeyWrap_Decrypt
);
743 context
->destroy
= (SFTKDestroy
) AESKeyWrap_DestroyContext
;
747 crv
= CKR_MECHANISM_INVALID
;
752 sftk_FreeContext(context
);
753 sftk_FreeSession(session
);
756 sftk_SetContextByType(session
, contextType
, context
);
757 sftk_FreeSession(session
);
761 /* NSC_EncryptInit initializes an encryption operation. */
762 CK_RV
NSC_EncryptInit(CK_SESSION_HANDLE hSession
,
763 CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
)
766 return sftk_CryptInit(hSession
, pMechanism
, hKey
, CKA_ENCRYPT
,
767 SFTK_ENCRYPT
, PR_TRUE
);
770 /* NSC_EncryptUpdate continues a multiple-part encryption operation. */
771 CK_RV
NSC_EncryptUpdate(CK_SESSION_HANDLE hSession
,
772 CK_BYTE_PTR pPart
, CK_ULONG ulPartLen
, CK_BYTE_PTR pEncryptedPart
,
773 CK_ULONG_PTR pulEncryptedPartLen
)
775 SFTKSessionContext
*context
;
776 unsigned int outlen
,i
;
777 unsigned int padoutlen
= 0;
778 unsigned int maxout
= *pulEncryptedPartLen
;
784 /* make sure we're legal */
785 crv
= sftk_GetContext(hSession
,&context
,SFTK_ENCRYPT
,PR_TRUE
,NULL
);
786 if (crv
!= CKR_OK
) return crv
;
788 if (!pEncryptedPart
) {
789 if (context
->doPad
) {
790 CK_ULONG totalDataAvailable
= ulPartLen
+ context
->padDataLength
;
791 CK_ULONG blocksToSend
= totalDataAvailable
/context
->blockSize
;
793 *pulEncryptedPartLen
= blocksToSend
* context
->blockSize
;
796 *pulEncryptedPartLen
= ulPartLen
;
801 if (context
->doPad
) {
802 /* deal with previous buffered data */
803 if (context
->padDataLength
!= 0) {
804 /* fill in the padded to a full block size */
805 for (i
=context
->padDataLength
;
806 (ulPartLen
!= 0) && i
< context
->blockSize
; i
++) {
807 context
->padBuf
[i
] = *pPart
++;
809 context
->padDataLength
++;
812 /* not enough data to encrypt yet? then return */
813 if (context
->padDataLength
!= context
->blockSize
) {
814 *pulEncryptedPartLen
= 0;
817 /* encrypt the current padded data */
818 rv
= (*context
->update
)(context
->cipherInfo
, pEncryptedPart
,
819 &padoutlen
, context
->blockSize
, context
->padBuf
,
821 if (rv
!= SECSuccess
) {
822 return sftk_MapCryptError(PORT_GetError());
824 pEncryptedPart
+= padoutlen
;
827 /* save the residual */
828 context
->padDataLength
= ulPartLen
% context
->blockSize
;
829 if (context
->padDataLength
) {
830 PORT_Memcpy(context
->padBuf
,
831 &pPart
[ulPartLen
-context
->padDataLength
],
832 context
->padDataLength
);
833 ulPartLen
-= context
->padDataLength
;
835 /* if we've exhausted our new buffer, we're done */
836 if (ulPartLen
== 0) {
837 *pulEncryptedPartLen
= padoutlen
;
843 /* do it: NOTE: this assumes buf size in is >= buf size out! */
844 rv
= (*context
->update
)(context
->cipherInfo
,pEncryptedPart
,
845 &outlen
, maxout
, pPart
, ulPartLen
);
846 *pulEncryptedPartLen
= (CK_ULONG
) (outlen
+ padoutlen
);
847 if (rv
!= SECSuccess
) {
848 return sftk_MapCryptError(PORT_GetError());
854 /* NSC_EncryptFinal finishes a multiple-part encryption operation. */
855 CK_RV
NSC_EncryptFinal(CK_SESSION_HANDLE hSession
,
856 CK_BYTE_PTR pLastEncryptedPart
, CK_ULONG_PTR pulLastEncryptedPartLen
)
858 SFTKSession
*session
;
859 SFTKSessionContext
*context
;
860 unsigned int outlen
,i
;
861 unsigned int maxout
= *pulLastEncryptedPartLen
;
863 SECStatus rv
= SECSuccess
;
864 PRBool contextFinished
= PR_TRUE
;
868 /* make sure we're legal */
869 crv
= sftk_GetContext(hSession
,&context
,SFTK_ENCRYPT
,PR_TRUE
,&session
);
870 if (crv
!= CKR_OK
) return crv
;
872 *pulLastEncryptedPartLen
= 0;
873 if (!pLastEncryptedPart
) {
874 /* caller is checking the amount of remaining data */
875 if (context
->blockSize
> 0 && context
->doPad
) {
876 *pulLastEncryptedPartLen
= context
->blockSize
;
877 contextFinished
= PR_FALSE
; /* still have padding to go */
883 if (context
->doPad
) {
884 unsigned char padbyte
= (unsigned char)
885 (context
->blockSize
- context
->padDataLength
);
886 /* fill out rest of pad buffer with pad magic*/
887 for (i
=context
->padDataLength
; i
< context
->blockSize
; i
++) {
888 context
->padBuf
[i
] = padbyte
;
890 rv
= (*context
->update
)(context
->cipherInfo
,pLastEncryptedPart
,
891 &outlen
, maxout
, context
->padBuf
, context
->blockSize
);
892 if (rv
== SECSuccess
) *pulLastEncryptedPartLen
= (CK_ULONG
) outlen
;
896 if (contextFinished
) {
897 sftk_SetContextByType(session
, SFTK_ENCRYPT
, NULL
);
898 sftk_FreeContext(context
);
900 sftk_FreeSession(session
);
901 return (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
904 /* NSC_Encrypt encrypts single-part data. */
905 CK_RV
NSC_Encrypt (CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pData
,
906 CK_ULONG ulDataLen
, CK_BYTE_PTR pEncryptedData
,
907 CK_ULONG_PTR pulEncryptedDataLen
)
909 SFTKSession
*session
;
910 SFTKSessionContext
*context
;
912 unsigned int maxoutlen
= *pulEncryptedDataLen
;
915 SECStatus rv
= SECSuccess
;
918 pText
.type
= siBuffer
;
920 pText
.len
= ulDataLen
;
924 /* make sure we're legal */
925 crv
= sftk_GetContext(hSession
,&context
,SFTK_ENCRYPT
,PR_FALSE
,&session
);
926 if (crv
!= CKR_OK
) return crv
;
928 if (!pEncryptedData
) {
929 *pulEncryptedDataLen
= context
->multi
?
930 ulDataLen
+ 2 * context
->blockSize
: context
->maxLen
;
934 if (context
->doPad
) {
935 if (context
->multi
) {
937 /* padding is fairly complicated, have the update and final
938 * code deal with it */
939 sftk_FreeSession(session
);
940 crv
= NSC_EncryptUpdate(hSession
, pData
, ulDataLen
, pEncryptedData
,
941 pulEncryptedDataLen
);
943 *pulEncryptedDataLen
= 0;
944 maxoutlen
-= *pulEncryptedDataLen
;
945 pEncryptedData
+= *pulEncryptedDataLen
;
946 finalLen
= maxoutlen
;
947 crv2
= NSC_EncryptFinal(hSession
, pEncryptedData
, &finalLen
);
949 *pulEncryptedDataLen
+= finalLen
;
950 return crv
== CKR_OK
? crv2
: crv
;
952 /* doPad without multi means that padding must be done on the first
953 ** and only update. There will be no final.
955 PORT_Assert(context
->blockSize
> 1);
956 if (context
->blockSize
> 1) {
957 CK_ULONG remainder
= ulDataLen
% context
->blockSize
;
958 CK_ULONG padding
= context
->blockSize
- remainder
;
959 pText
.len
+= padding
;
960 pText
.data
= PORT_ZAlloc(pText
.len
);
962 memcpy(pText
.data
, pData
, ulDataLen
);
963 memset(pText
.data
+ ulDataLen
, padding
, padding
);
965 crv
= CKR_HOST_MEMORY
;
971 /* do it: NOTE: this assumes buf size is big enough. */
972 rv
= (*context
->update
)(context
->cipherInfo
, pEncryptedData
,
973 &outlen
, maxoutlen
, pText
.data
, pText
.len
);
974 crv
= (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
975 *pulEncryptedDataLen
= (CK_ULONG
) outlen
;
976 if (pText
.data
!= pData
)
977 PORT_ZFree(pText
.data
, pText
.len
);
979 sftk_SetContextByType(session
, SFTK_ENCRYPT
, NULL
);
980 sftk_FreeContext(context
);
982 sftk_FreeSession(session
);
989 ************** Crypto Functions: Decrypt ************************
992 /* NSC_DecryptInit initializes a decryption operation. */
993 CK_RV
NSC_DecryptInit( CK_SESSION_HANDLE hSession
,
994 CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
)
998 return sftk_CryptInit(hSession
, pMechanism
, hKey
, CKA_DECRYPT
,
999 SFTK_DECRYPT
, PR_FALSE
);
1002 /* NSC_DecryptUpdate continues a multiple-part decryption operation. */
1003 CK_RV
NSC_DecryptUpdate(CK_SESSION_HANDLE hSession
,
1004 CK_BYTE_PTR pEncryptedPart
, CK_ULONG ulEncryptedPartLen
,
1005 CK_BYTE_PTR pPart
, CK_ULONG_PTR pulPartLen
)
1007 SFTKSessionContext
*context
;
1008 unsigned int padoutlen
= 0;
1009 unsigned int outlen
;
1010 unsigned int maxout
= *pulPartLen
;
1016 /* make sure we're legal */
1017 crv
= sftk_GetContext(hSession
,&context
,SFTK_DECRYPT
,PR_TRUE
,NULL
);
1018 if (crv
!= CKR_OK
) return crv
;
1020 /* this can only happen on an NSS programming error */
1021 PORT_Assert((context
->padDataLength
== 0)
1022 || context
->padDataLength
== context
->blockSize
);
1026 if (context
->doPad
) {
1027 /* we can check the data length here because if we are padding,
1028 * then we must be using a block cipher. In the non-padding case
1029 * the error will be returned by the underlying decryption
1030 * function when do do the actual decrypt. We need to do the
1031 * check here to avoid returning a negative length to the caller.
1033 if ((ulEncryptedPartLen
== 0) ||
1034 (ulEncryptedPartLen
% context
->blockSize
) != 0) {
1035 return CKR_ENCRYPTED_DATA_LEN_RANGE
;
1038 ulEncryptedPartLen
+ context
->padDataLength
- context
->blockSize
;
1041 /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
1042 * for block ciphers, it must be a multiple of blockSize. The error is
1043 * detected when this function is called again do decrypt the output.
1045 *pulPartLen
= ulEncryptedPartLen
;
1049 if (context
->doPad
) {
1050 /* first decrypt our saved buffer */
1051 if (context
->padDataLength
!= 0) {
1052 rv
= (*context
->update
)(context
->cipherInfo
, pPart
, &padoutlen
,
1053 maxout
, context
->padBuf
, context
->blockSize
);
1054 if (rv
!= SECSuccess
) return CKR_DEVICE_ERROR
;
1056 maxout
-= padoutlen
;
1058 /* now save the final block for the next decrypt or the final */
1059 PORT_Memcpy(context
->padBuf
,&pEncryptedPart
[ulEncryptedPartLen
-
1060 context
->blockSize
], context
->blockSize
);
1061 context
->padDataLength
= context
->blockSize
;
1062 ulEncryptedPartLen
-= context
->padDataLength
;
1065 /* do it: NOTE: this assumes buf size in is >= buf size out! */
1066 rv
= (*context
->update
)(context
->cipherInfo
,pPart
, &outlen
,
1067 maxout
, pEncryptedPart
, ulEncryptedPartLen
);
1068 *pulPartLen
= (CK_ULONG
) (outlen
+ padoutlen
);
1069 return (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
1073 /* NSC_DecryptFinal finishes a multiple-part decryption operation. */
1074 CK_RV
NSC_DecryptFinal(CK_SESSION_HANDLE hSession
,
1075 CK_BYTE_PTR pLastPart
, CK_ULONG_PTR pulLastPartLen
)
1077 SFTKSession
*session
;
1078 SFTKSessionContext
*context
;
1079 unsigned int outlen
;
1080 unsigned int maxout
= *pulLastPartLen
;
1082 SECStatus rv
= SECSuccess
;
1086 /* make sure we're legal */
1087 crv
= sftk_GetContext(hSession
,&context
,SFTK_DECRYPT
,PR_TRUE
,&session
);
1088 if (crv
!= CKR_OK
) return crv
;
1090 *pulLastPartLen
= 0;
1092 /* caller is checking the amount of remaining data */
1093 if (context
->padDataLength
> 0) {
1094 *pulLastPartLen
= context
->padDataLength
;
1100 if (context
->doPad
) {
1101 /* decrypt our saved buffer */
1102 if (context
->padDataLength
!= 0) {
1103 /* this assumes that pLastPart is big enough to hold the *whole*
1105 rv
= (*context
->update
)(context
->cipherInfo
, pLastPart
, &outlen
,
1106 maxout
, context
->padBuf
, context
->blockSize
);
1107 if (rv
== SECSuccess
) {
1108 unsigned int padSize
=
1109 (unsigned int) pLastPart
[context
->blockSize
-1];
1110 if ((padSize
> context
->blockSize
) || (padSize
== 0)) {
1113 *pulLastPartLen
= outlen
- padSize
;
1119 sftk_SetContextByType(session
, SFTK_DECRYPT
, NULL
);
1120 sftk_FreeContext(context
);
1122 sftk_FreeSession(session
);
1123 return (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
1126 /* NSC_Decrypt decrypts encrypted data in a single part. */
1127 CK_RV
NSC_Decrypt(CK_SESSION_HANDLE hSession
,
1128 CK_BYTE_PTR pEncryptedData
,CK_ULONG ulEncryptedDataLen
,CK_BYTE_PTR pData
,
1129 CK_ULONG_PTR pulDataLen
)
1131 SFTKSession
*session
;
1132 SFTKSessionContext
*context
;
1133 unsigned int outlen
;
1134 unsigned int maxoutlen
= *pulDataLen
;
1137 SECStatus rv
= SECSuccess
;
1141 /* make sure we're legal */
1142 crv
= sftk_GetContext(hSession
,&context
,SFTK_DECRYPT
,PR_FALSE
,&session
);
1143 if (crv
!= CKR_OK
) return crv
;
1146 *pulDataLen
= ulEncryptedDataLen
+ context
->blockSize
;
1150 if (context
->doPad
&& context
->multi
) {
1152 /* padding is fairly complicated, have the update and final
1153 * code deal with it */
1154 sftk_FreeSession(session
);
1155 crv
= NSC_DecryptUpdate(hSession
,pEncryptedData
,ulEncryptedDataLen
,
1159 maxoutlen
-= *pulDataLen
;
1160 pData
+= *pulDataLen
;
1161 finalLen
= maxoutlen
;
1162 crv2
= NSC_DecryptFinal(hSession
, pData
, &finalLen
);
1164 *pulDataLen
+= finalLen
;
1165 return crv
== CKR_OK
? crv2
: crv
;
1168 rv
= (*context
->update
)(context
->cipherInfo
, pData
, &outlen
, maxoutlen
,
1169 pEncryptedData
, ulEncryptedDataLen
);
1170 /* XXX need to do MUCH better error mapping than this. */
1171 crv
= (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
1172 if (rv
== SECSuccess
&& context
->doPad
) {
1173 CK_ULONG padding
= pData
[outlen
- 1];
1174 if (padding
> context
->blockSize
|| !padding
) {
1175 crv
= CKR_ENCRYPTED_DATA_INVALID
;
1179 *pulDataLen
= (CK_ULONG
) outlen
;
1180 sftk_SetContextByType(session
, SFTK_DECRYPT
, NULL
);
1181 sftk_FreeContext(context
);
1183 sftk_FreeSession(session
);
1190 ************** Crypto Functions: Digest (HASH) ************************
1193 /* NSC_DigestInit initializes a message-digesting operation. */
1194 CK_RV
NSC_DigestInit(CK_SESSION_HANDLE hSession
,
1195 CK_MECHANISM_PTR pMechanism
)
1197 SFTKSession
*session
;
1198 SFTKSessionContext
*context
;
1203 session
= sftk_SessionFromHandle(hSession
);
1204 if (session
== NULL
)
1205 return CKR_SESSION_HANDLE_INVALID
;
1206 crv
= sftk_InitGeneric(session
,&context
,SFTK_HASH
,NULL
,0,NULL
, 0, 0);
1207 if (crv
!= CKR_OK
) {
1208 sftk_FreeSession(session
);
1213 #define INIT_MECH(mech,mmm) \
1215 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
1216 context->cipherInfo = (void *)mmm ## _ctx; \
1217 context->cipherInfoLen = mmm ## _FlattenSize(mmm ## _ctx); \
1218 context->currentMech = mech; \
1219 context->hashUpdate = (SFTKHash) mmm ## _Update; \
1220 context->end = (SFTKEnd) mmm ## _End; \
1221 context->destroy = (SFTKDestroy) mmm ## _DestroyContext; \
1222 context->maxLen = mmm ## _LENGTH; \
1224 mmm ## _Begin(mmm ## _ctx); \
1226 crv = CKR_HOST_MEMORY; \
1230 switch(pMechanism
->mechanism
) {
1231 INIT_MECH(CKM_MD2
, MD2
)
1232 INIT_MECH(CKM_MD5
, MD5
)
1233 INIT_MECH(CKM_SHA_1
, SHA1
)
1234 INIT_MECH(CKM_SHA256
, SHA256
)
1235 INIT_MECH(CKM_SHA384
, SHA384
)
1236 INIT_MECH(CKM_SHA512
, SHA512
)
1239 crv
= CKR_MECHANISM_INVALID
;
1243 if (crv
!= CKR_OK
) {
1244 sftk_FreeContext(context
);
1245 sftk_FreeSession(session
);
1248 sftk_SetContextByType(session
, SFTK_HASH
, context
);
1249 sftk_FreeSession(session
);
1254 /* NSC_Digest digests data in a single part. */
1255 CK_RV
NSC_Digest(CK_SESSION_HANDLE hSession
,
1256 CK_BYTE_PTR pData
, CK_ULONG ulDataLen
, CK_BYTE_PTR pDigest
,
1257 CK_ULONG_PTR pulDigestLen
)
1259 SFTKSession
*session
;
1260 SFTKSessionContext
*context
;
1261 unsigned int digestLen
;
1262 unsigned int maxout
= *pulDigestLen
;
1267 /* make sure we're legal */
1268 crv
= sftk_GetContext(hSession
,&context
,SFTK_HASH
,PR_FALSE
,&session
);
1269 if (crv
!= CKR_OK
) return crv
;
1271 if (pDigest
== NULL
) {
1272 *pulDigestLen
= context
->maxLen
;
1277 (*context
->hashUpdate
)(context
->cipherInfo
, pData
, ulDataLen
);
1278 /* NOTE: this assumes buf size is bigenough for the algorithm */
1279 (*context
->end
)(context
->cipherInfo
, pDigest
, &digestLen
,maxout
);
1280 *pulDigestLen
= digestLen
;
1282 sftk_SetContextByType(session
, SFTK_HASH
, NULL
);
1283 sftk_FreeContext(context
);
1285 sftk_FreeSession(session
);
1290 /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
1291 CK_RV
NSC_DigestUpdate(CK_SESSION_HANDLE hSession
,CK_BYTE_PTR pPart
,
1294 SFTKSessionContext
*context
;
1299 /* make sure we're legal */
1300 crv
= sftk_GetContext(hSession
,&context
,SFTK_HASH
,PR_TRUE
,NULL
);
1301 if (crv
!= CKR_OK
) return crv
;
1303 (*context
->hashUpdate
)(context
->cipherInfo
, pPart
, ulPartLen
);
1308 /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
1309 CK_RV
NSC_DigestFinal(CK_SESSION_HANDLE hSession
,CK_BYTE_PTR pDigest
,
1310 CK_ULONG_PTR pulDigestLen
)
1312 SFTKSession
*session
;
1313 SFTKSessionContext
*context
;
1314 unsigned int maxout
= *pulDigestLen
;
1315 unsigned int digestLen
;
1320 /* make sure we're legal */
1321 crv
= sftk_GetContext(hSession
, &context
, SFTK_HASH
, PR_TRUE
, &session
);
1322 if (crv
!= CKR_OK
) return crv
;
1324 if (pDigest
!= NULL
) {
1325 (*context
->end
)(context
->cipherInfo
, pDigest
, &digestLen
, maxout
);
1326 *pulDigestLen
= digestLen
;
1327 sftk_SetContextByType(session
, SFTK_HASH
, NULL
);
1328 sftk_FreeContext(context
);
1330 *pulDigestLen
= context
->maxLen
;
1333 sftk_FreeSession(session
);
1338 * these helper functions are used by Generic Macing and Signing functions
1339 * that use hashes as part of their operations.
1341 #define DOSUB(mmm) \
1343 sftk_doSub ## mmm(SFTKSessionContext *context) { \
1344 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
1345 context->hashInfo = (void *) mmm ## _ctx; \
1346 context->hashUpdate = (SFTKHash) mmm ## _Update; \
1347 context->end = (SFTKEnd) mmm ## _End; \
1348 context->hashdestroy = (SFTKDestroy) mmm ## _DestroyContext; \
1349 if (!context->hashInfo) { \
1350 return CKR_HOST_MEMORY; \
1352 mmm ## _Begin( mmm ## _ctx ); \
1364 * HMAC General copies only a portion of the result. This update routine likes
1365 * the final HMAC output with the signature.
1368 sftk_HMACCopy(CK_ULONG
*copyLen
,unsigned char *sig
,unsigned int *sigLen
,
1369 unsigned int maxLen
,unsigned char *hash
, unsigned int hashLen
)
1371 if (maxLen
< *copyLen
) return SECFailure
;
1372 PORT_Memcpy(sig
,hash
,*copyLen
);
1377 /* Verify is just a compare for HMAC */
1379 sftk_HMACCmp(CK_ULONG
*copyLen
,unsigned char *sig
,unsigned int sigLen
,
1380 unsigned char *hash
, unsigned int hashLen
)
1382 return (PORT_Memcmp(sig
,hash
,*copyLen
) == 0) ? SECSuccess
: SECFailure
;
1386 * common HMAC initalization routine
1389 sftk_doHMACInit(SFTKSessionContext
*context
,HASH_HashType hash
,
1390 SFTKObject
*key
, CK_ULONG mac_size
)
1392 SFTKAttribute
*keyval
;
1393 HMACContext
*HMACcontext
;
1394 CK_ULONG
*intpointer
;
1395 const SECHashObject
*hashObj
= HASH_GetRawHashObject(hash
);
1396 PRBool isFIPS
= (key
->slot
->slotID
== FIPS_SLOT_ID
);
1398 /* required by FIPS 198 Section 4 */
1399 if (isFIPS
&& (mac_size
< 4 || mac_size
< hashObj
->length
/2)) {
1400 return CKR_BUFFER_TOO_SMALL
;
1403 keyval
= sftk_FindAttribute(key
,CKA_VALUE
);
1404 if (keyval
== NULL
) return CKR_KEY_SIZE_RANGE
;
1406 HMACcontext
= HMAC_Create(hashObj
,
1407 (const unsigned char*)keyval
->attrib
.pValue
,
1408 keyval
->attrib
.ulValueLen
, isFIPS
);
1409 context
->hashInfo
= HMACcontext
;
1410 context
->multi
= PR_TRUE
;
1411 sftk_FreeAttribute(keyval
);
1412 if (context
->hashInfo
== NULL
) {
1413 if (PORT_GetError() == SEC_ERROR_INVALID_ARGS
) {
1414 return CKR_KEY_SIZE_RANGE
;
1416 return CKR_HOST_MEMORY
;
1418 context
->hashUpdate
= (SFTKHash
) HMAC_Update
;
1419 context
->end
= (SFTKEnd
) HMAC_Finish
;
1421 context
->hashdestroy
= (SFTKDestroy
) HMAC_Destroy
;
1422 intpointer
= (CK_ULONG
*) PORT_Alloc(sizeof(CK_ULONG
));
1423 if (intpointer
== NULL
) {
1424 return CKR_HOST_MEMORY
;
1426 *intpointer
= mac_size
;
1427 context
->cipherInfo
= (void *) intpointer
;
1428 context
->destroy
= (SFTKDestroy
) sftk_Space
;
1429 context
->update
= (SFTKCipher
) sftk_HMACCopy
;
1430 context
->verify
= (SFTKVerify
) sftk_HMACCmp
;
1431 context
->maxLen
= hashObj
->length
;
1432 HMAC_Begin(HMACcontext
);
1437 * SSL Macing support. SSL Macs are inited, then update with the base
1438 * hashing algorithm, then finalized in sign and verify
1443 * 60 bytes is 3 times the maximum length MAC size that is supported.
1444 * We probably should have one copy of this table. We still need this table
1445 * in ssl to 'sign' the handshake hashes.
1447 static unsigned char ssl_pad_1
[60] = {
1448 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1449 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1450 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1451 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1452 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1453 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1454 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1455 0x36, 0x36, 0x36, 0x36
1457 static unsigned char ssl_pad_2
[60] = {
1458 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1459 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1460 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1461 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1462 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1463 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1464 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1465 0x5c, 0x5c, 0x5c, 0x5c
1469 sftk_SSLMACSign(SFTKSSLMACInfo
*info
,unsigned char *sig
,unsigned int *sigLen
,
1470 unsigned int maxLen
,unsigned char *hash
, unsigned int hashLen
)
1472 unsigned char tmpBuf
[SFTK_MAX_MAC_LENGTH
];
1475 info
->begin(info
->hashContext
);
1476 info
->update(info
->hashContext
,info
->key
,info
->keySize
);
1477 info
->update(info
->hashContext
,ssl_pad_2
,info
->padSize
);
1478 info
->update(info
->hashContext
,hash
,hashLen
);
1479 info
->end(info
->hashContext
,tmpBuf
,&out
,SFTK_MAX_MAC_LENGTH
);
1480 PORT_Memcpy(sig
,tmpBuf
,info
->macSize
);
1481 *sigLen
= info
->macSize
;
1486 sftk_SSLMACVerify(SFTKSSLMACInfo
*info
,unsigned char *sig
,unsigned int sigLen
,
1487 unsigned char *hash
, unsigned int hashLen
)
1489 unsigned char tmpBuf
[SFTK_MAX_MAC_LENGTH
];
1492 info
->begin(info
->hashContext
);
1493 info
->update(info
->hashContext
,info
->key
,info
->keySize
);
1494 info
->update(info
->hashContext
,ssl_pad_2
,info
->padSize
);
1495 info
->update(info
->hashContext
,hash
,hashLen
);
1496 info
->end(info
->hashContext
,tmpBuf
,&out
,SFTK_MAX_MAC_LENGTH
);
1497 return (PORT_Memcmp(sig
,tmpBuf
,info
->macSize
) == 0) ?
1498 SECSuccess
: SECFailure
;
1502 * common HMAC initalization routine
1505 sftk_doSSLMACInit(SFTKSessionContext
*context
,SECOidTag oid
,
1506 SFTKObject
*key
, CK_ULONG mac_size
)
1508 SFTKAttribute
*keyval
;
1511 SFTKSSLMACInfo
*sslmacinfo
;
1512 CK_RV crv
= CKR_MECHANISM_INVALID
;
1514 if (oid
== SEC_OID_SHA1
) {
1515 crv
= sftk_doSubSHA1(context
);
1516 if (crv
!= CKR_OK
) return crv
;
1517 begin
= (SFTKBegin
) SHA1_Begin
;
1520 crv
= sftk_doSubMD5(context
);
1521 if (crv
!= CKR_OK
) return crv
;
1522 begin
= (SFTKBegin
) MD5_Begin
;
1525 context
->multi
= PR_TRUE
;
1527 keyval
= sftk_FindAttribute(key
,CKA_VALUE
);
1528 if (keyval
== NULL
) return CKR_KEY_SIZE_RANGE
;
1530 context
->hashUpdate(context
->hashInfo
,keyval
->attrib
.pValue
,
1531 keyval
->attrib
.ulValueLen
);
1532 context
->hashUpdate(context
->hashInfo
,ssl_pad_1
,padSize
);
1533 sslmacinfo
= (SFTKSSLMACInfo
*) PORT_Alloc(sizeof(SFTKSSLMACInfo
));
1534 if (sslmacinfo
== NULL
) {
1535 sftk_FreeAttribute(keyval
);
1536 return CKR_HOST_MEMORY
;
1538 sslmacinfo
->macSize
= mac_size
;
1539 sslmacinfo
->hashContext
= context
->hashInfo
;
1540 PORT_Memcpy(sslmacinfo
->key
,keyval
->attrib
.pValue
,
1541 keyval
->attrib
.ulValueLen
);
1542 sslmacinfo
->keySize
= keyval
->attrib
.ulValueLen
;
1543 sslmacinfo
->begin
= begin
;
1544 sslmacinfo
->end
= context
->end
;
1545 sslmacinfo
->update
= context
->hashUpdate
;
1546 sslmacinfo
->padSize
= padSize
;
1547 sftk_FreeAttribute(keyval
);
1548 context
->cipherInfo
= (void *) sslmacinfo
;
1549 context
->destroy
= (SFTKDestroy
) sftk_Space
;
1550 context
->update
= (SFTKCipher
) sftk_SSLMACSign
;
1551 context
->verify
= (SFTKVerify
) sftk_SSLMACVerify
;
1552 context
->maxLen
= mac_size
;
1557 ************** Crypto Functions: Sign ************************
1561 * Check if We're using CBCMacing and initialize the session context if we are.
1564 sftk_InitCBCMac(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
1565 CK_OBJECT_HANDLE hKey
, CK_ATTRIBUTE_TYPE keyUsage
,
1566 SFTKContextType contextType
)
1569 CK_MECHANISM cbc_mechanism
;
1570 CK_ULONG mac_bytes
= SFTK_INVALID_MAC_SIZE
;
1571 CK_RC2_CBC_PARAMS rc2_params
;
1572 #if NSS_SOFTOKEN_DOES_RC5
1573 CK_RC5_CBC_PARAMS rc5_params
;
1574 CK_RC5_MAC_GENERAL_PARAMS
*rc5_mac
;
1576 unsigned char ivBlock
[SFTK_MAX_BLOCK_SIZE
];
1577 SFTKSessionContext
*context
;
1581 switch (pMechanism
->mechanism
) {
1582 case CKM_RC2_MAC_GENERAL
:
1584 ((CK_RC2_MAC_GENERAL_PARAMS
*)pMechanism
->pParameter
)->ulMacLength
;
1587 /* this works because ulEffectiveBits is in the same place in both the
1588 * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
1589 rc2_params
.ulEffectiveBits
= ((CK_RC2_MAC_GENERAL_PARAMS
*)
1590 pMechanism
->pParameter
)->ulEffectiveBits
;
1591 PORT_Memset(rc2_params
.iv
,0,sizeof(rc2_params
.iv
));
1592 cbc_mechanism
.mechanism
= CKM_RC2_CBC
;
1593 cbc_mechanism
.pParameter
= &rc2_params
;
1594 cbc_mechanism
.ulParameterLen
= sizeof(rc2_params
);
1597 #if NSS_SOFTOKEN_DOES_RC5
1598 case CKM_RC5_MAC_GENERAL
:
1600 ((CK_RC5_MAC_GENERAL_PARAMS
*)pMechanism
->pParameter
)->ulMacLength
;
1603 /* this works because ulEffectiveBits is in the same place in both the
1604 * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
1605 rc5_mac
= (CK_RC5_MAC_GENERAL_PARAMS
*)pMechanism
->pParameter
;
1606 rc5_params
.ulWordsize
= rc5_mac
->ulWordsize
;
1607 rc5_params
.ulRounds
= rc5_mac
->ulRounds
;
1608 rc5_params
.pIv
= ivBlock
;
1609 blockSize
= rc5_mac
->ulWordsize
*2;
1610 rc5_params
.ulIvLen
= blockSize
;
1611 PORT_Memset(ivBlock
,0,blockSize
);
1612 cbc_mechanism
.mechanism
= CKM_RC5_CBC
;
1613 cbc_mechanism
.pParameter
= &rc5_params
;
1614 cbc_mechanism
.ulParameterLen
= sizeof(rc5_params
);
1617 /* add cast and idea later */
1618 case CKM_DES_MAC_GENERAL
:
1619 mac_bytes
= *(CK_ULONG
*)pMechanism
->pParameter
;
1623 PORT_Memset(ivBlock
,0,blockSize
);
1624 cbc_mechanism
.mechanism
= CKM_DES_CBC
;
1625 cbc_mechanism
.pParameter
= &ivBlock
;
1626 cbc_mechanism
.ulParameterLen
= blockSize
;
1628 case CKM_DES3_MAC_GENERAL
:
1629 mac_bytes
= *(CK_ULONG
*)pMechanism
->pParameter
;
1633 PORT_Memset(ivBlock
,0,blockSize
);
1634 cbc_mechanism
.mechanism
= CKM_DES3_CBC
;
1635 cbc_mechanism
.pParameter
= &ivBlock
;
1636 cbc_mechanism
.ulParameterLen
= blockSize
;
1638 case CKM_CDMF_MAC_GENERAL
:
1639 mac_bytes
= *(CK_ULONG
*)pMechanism
->pParameter
;
1643 PORT_Memset(ivBlock
,0,blockSize
);
1644 cbc_mechanism
.mechanism
= CKM_CDMF_CBC
;
1645 cbc_mechanism
.pParameter
= &ivBlock
;
1646 cbc_mechanism
.ulParameterLen
= blockSize
;
1648 case CKM_CAMELLIA_MAC_GENERAL
:
1649 mac_bytes
= *(CK_ULONG
*)pMechanism
->pParameter
;
1651 case CKM_CAMELLIA_MAC
:
1653 PORT_Memset(ivBlock
,0,blockSize
);
1654 cbc_mechanism
.mechanism
= CKM_CAMELLIA_CBC
;
1655 cbc_mechanism
.pParameter
= &ivBlock
;
1656 cbc_mechanism
.ulParameterLen
= blockSize
;
1658 case CKM_AES_MAC_GENERAL
:
1659 mac_bytes
= *(CK_ULONG
*)pMechanism
->pParameter
;
1663 PORT_Memset(ivBlock
,0,blockSize
);
1664 cbc_mechanism
.mechanism
= CKM_AES_CBC
;
1665 cbc_mechanism
.pParameter
= &ivBlock
;
1666 cbc_mechanism
.ulParameterLen
= blockSize
;
1669 return CKR_FUNCTION_NOT_SUPPORTED
;
1672 crv
= sftk_CryptInit(hSession
, &cbc_mechanism
, hKey
, keyUsage
,
1673 contextType
, PR_TRUE
);
1674 if (crv
!= CKR_OK
) return crv
;
1675 crv
= sftk_GetContext(hSession
,&context
,contextType
,PR_TRUE
,NULL
);
1677 /* this shouldn't happen! */
1678 PORT_Assert(crv
== CKR_OK
);
1679 if (crv
!= CKR_OK
) return crv
;
1680 context
->blockSize
= blockSize
;
1681 if (mac_bytes
== SFTK_INVALID_MAC_SIZE
) mac_bytes
= blockSize
/2;
1682 context
->macSize
= mac_bytes
;
1687 * encode RSA PKCS #1 Signature data before signing...
1690 sftk_HashSign(SFTKHashSignInfo
*info
,unsigned char *sig
,unsigned int *sigLen
,
1691 unsigned int maxLen
,unsigned char *hash
, unsigned int hashLen
)
1693 return RSA_HashSign(info
->hashOid
,info
->key
,sig
,sigLen
,maxLen
,
1697 /* XXX Old template; want to expunge it eventually. */
1698 static DERTemplate SECAlgorithmIDTemplate
[] = {
1700 0, NULL
, sizeof(SECAlgorithmID
) },
1702 offsetof(SECAlgorithmID
,algorithm
), },
1703 { DER_OPTIONAL
| DER_ANY
,
1704 offsetof(SECAlgorithmID
,parameters
), },
1709 * XXX OLD Template. Once all uses have been switched over to new one,
1712 static DERTemplate SGNDigestInfoTemplate
[] = {
1714 0, NULL
, sizeof(SGNDigestInfo
) },
1716 offsetof(SGNDigestInfo
,digestAlgorithm
),
1717 SECAlgorithmIDTemplate
, },
1719 offsetof(SGNDigestInfo
,digest
), },
1724 RSA_HashSign(SECOidTag hashOid
, NSSLOWKEYPrivateKey
*key
,
1725 unsigned char *sig
, unsigned int *sigLen
, unsigned int maxLen
,
1726 unsigned char *hash
, unsigned int hashLen
)
1729 SECStatus rv
= SECFailure
;
1731 PLArenaPool
*arena
= NULL
;
1732 SGNDigestInfo
*di
= NULL
;
1736 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1737 if ( !arena
) { goto loser
; }
1739 /* Construct digest info */
1740 di
= SGN_CreateDigestInfo(hashOid
, hash
, hashLen
);
1741 if (!di
) { goto loser
; }
1743 /* Der encode the digest as a DigestInfo */
1744 rv
= DER_Encode(arena
, &digder
, SGNDigestInfoTemplate
, di
);
1745 if (rv
!= SECSuccess
) {
1750 ** Encrypt signature after constructing appropriate PKCS#1 signature
1753 rv
= RSA_Sign(key
,sig
,sigLen
,maxLen
,digder
.data
,digder
.len
);
1756 SGN_DestroyDigestInfo(di
);
1757 if (arena
!= NULL
) {
1758 PORT_FreeArena(arena
, PR_FALSE
);
1764 nsc_DSA_Verify_Stub(void *ctx
, void *sigBuf
, unsigned int sigLen
,
1765 void *dataBuf
, unsigned int dataLen
)
1767 SECItem signature
, digest
;
1768 NSSLOWKEYPublicKey
*key
= (NSSLOWKEYPublicKey
*)ctx
;
1770 signature
.data
= (unsigned char *)sigBuf
;
1771 signature
.len
= sigLen
;
1772 digest
.data
= (unsigned char *)dataBuf
;
1773 digest
.len
= dataLen
;
1774 return DSA_VerifyDigest(&(key
->u
.dsa
), &signature
, &digest
);
1778 nsc_DSA_Sign_Stub(void *ctx
, void *sigBuf
,
1779 unsigned int *sigLen
, unsigned int maxSigLen
,
1780 void *dataBuf
, unsigned int dataLen
)
1782 SECItem signature
, digest
;
1784 NSSLOWKEYPrivateKey
*key
= (NSSLOWKEYPrivateKey
*)ctx
;
1786 signature
.data
= (unsigned char *)sigBuf
;
1787 signature
.len
= maxSigLen
;
1788 digest
.data
= (unsigned char *)dataBuf
;
1789 digest
.len
= dataLen
;
1790 rv
= DSA_SignDigest(&(key
->u
.dsa
), &signature
, &digest
);
1791 if (rv
!= SECSuccess
&& PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE
) {
1792 sftk_fatalError
= PR_TRUE
;
1794 *sigLen
= signature
.len
;
1798 #ifdef NSS_ENABLE_ECC
1800 nsc_ECDSAVerifyStub(void *ctx
, void *sigBuf
, unsigned int sigLen
,
1801 void *dataBuf
, unsigned int dataLen
)
1803 SECItem signature
, digest
;
1804 NSSLOWKEYPublicKey
*key
= (NSSLOWKEYPublicKey
*)ctx
;
1806 signature
.data
= (unsigned char *)sigBuf
;
1807 signature
.len
= sigLen
;
1808 digest
.data
= (unsigned char *)dataBuf
;
1809 digest
.len
= dataLen
;
1810 return ECDSA_VerifyDigest(&(key
->u
.ec
), &signature
, &digest
);
1814 nsc_ECDSASignStub(void *ctx
, void *sigBuf
,
1815 unsigned int *sigLen
, unsigned int maxSigLen
,
1816 void *dataBuf
, unsigned int dataLen
)
1818 SECItem signature
, digest
;
1820 NSSLOWKEYPrivateKey
*key
= (NSSLOWKEYPrivateKey
*)ctx
;
1822 signature
.data
= (unsigned char *)sigBuf
;
1823 signature
.len
= maxSigLen
;
1824 digest
.data
= (unsigned char *)dataBuf
;
1825 digest
.len
= dataLen
;
1826 rv
= ECDSA_SignDigest(&(key
->u
.ec
), &signature
, &digest
);
1827 if (rv
!= SECSuccess
&& PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE
) {
1828 sftk_fatalError
= PR_TRUE
;
1830 *sigLen
= signature
.len
;
1833 #endif /* NSS_ENABLE_ECC */
1835 /* NSC_SignInit setups up the signing operations. There are three basic
1837 * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
1838 * to data in a single Sign operation (which often looks a lot like an
1839 * encrypt, with data coming in and data going out).
1840 * (2) Hash based signing, where we continually hash the data, then apply
1841 * some sort of signature to the end.
1842 * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
1843 * and only the final block is part of the mac.
1845 * For case number 3, we initialize a context much like the Encryption Context
1846 * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
1847 * C_Final by the following method... if it's not multi-part, and it's doesn't
1848 * have a hash context, it must be a block Encryption CBC MAC.
1850 * For case number 2, we initialize a hash structure, as well as make it
1851 * multi-part. Updates are simple calls to the hash update function. Final
1852 * calls the hashend, then passes the result to the 'update' function (which
1853 * operates as a final signature function). In some hash based MAC'ing (as
1854 * opposed to hash base signatures), the update function is can be simply a
1855 * copy (as is the case with HMAC).
1857 CK_RV
NSC_SignInit(CK_SESSION_HANDLE hSession
,
1858 CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
)
1860 SFTKSession
*session
;
1862 SFTKSessionContext
*context
;
1863 CK_KEY_TYPE key_type
;
1865 NSSLOWKEYPrivateKey
*privKey
;
1866 SFTKHashSignInfo
*info
= NULL
;
1870 /* Block Cipher MACing Algorithms use a different Context init method..*/
1871 crv
= sftk_InitCBCMac(hSession
, pMechanism
, hKey
, CKA_SIGN
, SFTK_SIGN
);
1872 if (crv
!= CKR_FUNCTION_NOT_SUPPORTED
) return crv
;
1874 /* we're not using a block cipher mac */
1875 session
= sftk_SessionFromHandle(hSession
);
1876 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
1877 crv
= sftk_InitGeneric(session
,&context
,SFTK_SIGN
,&key
,hKey
,&key_type
,
1878 CKO_PRIVATE_KEY
,CKA_SIGN
);
1879 if (crv
!= CKR_OK
) {
1880 sftk_FreeSession(session
);
1884 context
->multi
= PR_FALSE
;
1886 #define INIT_RSA_SIGN_MECH(mmm) \
1887 case CKM_ ## mmm ## _RSA_PKCS: \
1888 context->multi = PR_TRUE; \
1889 crv = sftk_doSub ## mmm (context); \
1890 if (crv != CKR_OK) break; \
1891 context->update = (SFTKCipher) sftk_HashSign; \
1892 info = PORT_New(SFTKHashSignInfo); \
1893 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \
1894 info->hashOid = SEC_OID_ ## mmm ; \
1897 switch(pMechanism
->mechanism
) {
1898 INIT_RSA_SIGN_MECH(MD5
)
1899 INIT_RSA_SIGN_MECH(MD2
)
1900 INIT_RSA_SIGN_MECH(SHA1
)
1901 INIT_RSA_SIGN_MECH(SHA256
)
1902 INIT_RSA_SIGN_MECH(SHA384
)
1903 INIT_RSA_SIGN_MECH(SHA512
)
1906 context
->update
= (SFTKCipher
) RSA_Sign
;
1909 context
->update
= (SFTKCipher
) RSA_SignRaw
;
1911 if (key_type
!= CKK_RSA
) {
1912 if (info
) PORT_Free(info
);
1913 crv
= CKR_KEY_TYPE_INCONSISTENT
;
1916 privKey
= sftk_GetPrivKey(key
,CKK_RSA
,&crv
);
1917 if (privKey
== NULL
) {
1918 if (info
) PORT_Free(info
);
1921 /* OK, info is allocated only if we're doing hash and sign mechanism.
1922 * It's necessary to be able to set the correct OID in the final
1926 info
->key
= privKey
;
1927 context
->cipherInfo
= info
;
1928 context
->destroy
= (SFTKDestroy
)sftk_Space
;
1930 context
->cipherInfo
= privKey
;
1931 context
->destroy
= (SFTKDestroy
)sftk_Null
;
1933 context
->maxLen
= nsslowkey_PrivateModulusLen(privKey
);
1937 context
->multi
= PR_TRUE
;
1938 crv
= sftk_doSubSHA1(context
);
1939 if (crv
!= CKR_OK
) break;
1942 if (key_type
!= CKK_DSA
) {
1943 crv
= CKR_KEY_TYPE_INCONSISTENT
;
1946 privKey
= sftk_GetPrivKey(key
,CKK_DSA
,&crv
);
1947 if (privKey
== NULL
) {
1950 context
->cipherInfo
= privKey
;
1951 context
->update
= (SFTKCipher
) nsc_DSA_Sign_Stub
;
1952 context
->destroy
= (privKey
== key
->objectInfo
) ?
1953 (SFTKDestroy
) sftk_Null
:(SFTKDestroy
)sftk_FreePrivKey
;
1954 context
->maxLen
= DSA_SIGNATURE_LEN
;
1958 #ifdef NSS_ENABLE_ECC
1959 case CKM_ECDSA_SHA1
:
1960 context
->multi
= PR_TRUE
;
1961 crv
= sftk_doSubSHA1(context
);
1962 if (crv
!= CKR_OK
) break;
1965 if (key_type
!= CKK_EC
) {
1966 crv
= CKR_KEY_TYPE_INCONSISTENT
;
1969 privKey
= sftk_GetPrivKey(key
,CKK_EC
,&crv
);
1970 if (privKey
== NULL
) {
1971 crv
= CKR_HOST_MEMORY
;
1974 context
->cipherInfo
= privKey
;
1975 context
->update
= (SFTKCipher
) nsc_ECDSASignStub
;
1976 context
->destroy
= (privKey
== key
->objectInfo
) ?
1977 (SFTKDestroy
) sftk_Null
:(SFTKDestroy
)sftk_FreePrivKey
;
1978 context
->maxLen
= MAX_ECKEY_LEN
* 2;
1981 #endif /* NSS_ENABLE_ECC */
1983 #define INIT_HMAC_MECH(mmm) \
1984 case CKM_ ## mmm ## _HMAC_GENERAL: \
1985 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, \
1986 *(CK_ULONG *)pMechanism->pParameter); \
1988 case CKM_ ## mmm ## _HMAC: \
1989 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, mmm ## _LENGTH); \
1994 INIT_HMAC_MECH(SHA256
)
1995 INIT_HMAC_MECH(SHA384
)
1996 INIT_HMAC_MECH(SHA512
)
1998 case CKM_SHA_1_HMAC_GENERAL
:
1999 crv
= sftk_doHMACInit(context
,HASH_AlgSHA1
,key
,
2000 *(CK_ULONG
*)pMechanism
->pParameter
);
2002 case CKM_SHA_1_HMAC
:
2003 crv
= sftk_doHMACInit(context
,HASH_AlgSHA1
,key
,SHA1_LENGTH
);
2006 case CKM_SSL3_MD5_MAC
:
2007 crv
= sftk_doSSLMACInit(context
,SEC_OID_MD5
,key
,
2008 *(CK_ULONG
*)pMechanism
->pParameter
);
2010 case CKM_SSL3_SHA1_MAC
:
2011 crv
= sftk_doSSLMACInit(context
,SEC_OID_SHA1
,key
,
2012 *(CK_ULONG
*)pMechanism
->pParameter
);
2014 case CKM_TLS_PRF_GENERAL
:
2015 crv
= sftk_TLSPRFInit(context
, key
, key_type
);
2018 crv
= CKR_MECHANISM_INVALID
;
2022 if (crv
!= CKR_OK
) {
2023 sftk_FreeContext(context
);
2024 sftk_FreeSession(session
);
2027 sftk_SetContextByType(session
, SFTK_SIGN
, context
);
2028 sftk_FreeSession(session
);
2033 /* MACUpdate is the common implementation for SignUpdate and VerifyUpdate.
2034 * (sign and verify only very in their setup and final operations) */
2036 sftk_MACUpdate(CK_SESSION_HANDLE hSession
,CK_BYTE_PTR pPart
,
2037 CK_ULONG ulPartLen
,SFTKContextType type
)
2039 unsigned int outlen
;
2040 SFTKSessionContext
*context
;
2044 /* make sure we're legal */
2045 crv
= sftk_GetContext(hSession
,&context
,type
,PR_TRUE
,NULL
);
2046 if (crv
!= CKR_OK
) return crv
;
2048 if (context
->hashInfo
) {
2049 (*context
->hashUpdate
)(context
->hashInfo
, pPart
, ulPartLen
);
2053 /* must be block cipher macing */
2055 /* deal with previous buffered data */
2056 if (context
->padDataLength
!= 0) {
2058 /* fill in the padded to a full block size */
2059 for (i
=context
->padDataLength
; (ulPartLen
!= 0) &&
2060 i
< (int)context
->blockSize
; i
++) {
2061 context
->padBuf
[i
] = *pPart
++;
2063 context
->padDataLength
++;
2066 /* not enough data to encrypt yet? then return */
2067 if (context
->padDataLength
!= context
->blockSize
) return CKR_OK
;
2068 /* encrypt the current padded data */
2069 rv
= (*context
->update
)(context
->cipherInfo
,context
->macBuf
,&outlen
,
2070 SFTK_MAX_BLOCK_SIZE
,context
->padBuf
,context
->blockSize
);
2071 if (rv
!= SECSuccess
) return CKR_DEVICE_ERROR
;
2074 /* save the residual */
2075 context
->padDataLength
= ulPartLen
% context
->blockSize
;
2076 if (context
->padDataLength
) {
2077 PORT_Memcpy(context
->padBuf
,
2078 &pPart
[ulPartLen
-context
->padDataLength
],
2079 context
->padDataLength
);
2080 ulPartLen
-= context
->padDataLength
;
2083 /* if we've exhausted our new buffer, we're done */
2084 if (ulPartLen
== 0) { return CKR_OK
; }
2086 /* run the data through out encrypter */
2088 rv
= (*context
->update
)(context
->cipherInfo
, context
->padBuf
, &outlen
,
2089 SFTK_MAX_BLOCK_SIZE
, pPart
, context
->blockSize
);
2090 if (rv
!= SECSuccess
) return CKR_DEVICE_ERROR
;
2091 /* paranoia.. make sure we exit the loop */
2092 PORT_Assert(ulPartLen
>= context
->blockSize
);
2093 if (ulPartLen
< context
->blockSize
) break;
2094 ulPartLen
-= context
->blockSize
;
2101 /* NSC_SignUpdate continues a multiple-part signature operation,
2102 * where the signature is (will be) an appendix to the data,
2103 * and plaintext cannot be recovered from the signature */
2104 CK_RV
NSC_SignUpdate(CK_SESSION_HANDLE hSession
,CK_BYTE_PTR pPart
,
2109 return sftk_MACUpdate(hSession
, pPart
, ulPartLen
, SFTK_SIGN
);
2113 /* NSC_SignFinal finishes a multiple-part signature operation,
2114 * returning the signature. */
2115 CK_RV
NSC_SignFinal(CK_SESSION_HANDLE hSession
,CK_BYTE_PTR pSignature
,
2116 CK_ULONG_PTR pulSignatureLen
)
2118 SFTKSession
*session
;
2119 SFTKSessionContext
*context
;
2120 unsigned int outlen
;
2121 unsigned int digestLen
;
2122 unsigned int maxoutlen
= *pulSignatureLen
;
2123 unsigned char tmpbuf
[SFTK_MAX_MAC_LENGTH
];
2125 SECStatus rv
= SECSuccess
;
2129 /* make sure we're legal */
2130 *pulSignatureLen
= 0;
2131 crv
= sftk_GetContext(hSession
,&context
,SFTK_SIGN
,PR_TRUE
,&session
);
2132 if (crv
!= CKR_OK
) return crv
;
2135 *pulSignatureLen
= context
->maxLen
;
2137 } else if (context
->hashInfo
) {
2138 (*context
->end
)(context
->hashInfo
, tmpbuf
, &digestLen
, sizeof(tmpbuf
));
2139 rv
= (*context
->update
)(context
->cipherInfo
, pSignature
,
2140 &outlen
, maxoutlen
, tmpbuf
, digestLen
);
2141 *pulSignatureLen
= (CK_ULONG
) outlen
;
2143 /* deal with the last block if any residual */
2144 if (context
->padDataLength
) {
2145 /* fill out rest of pad buffer with pad magic*/
2147 for (i
=context
->padDataLength
; i
< (int)context
->blockSize
; i
++) {
2148 context
->padBuf
[i
] = 0;
2150 rv
= (*context
->update
)(context
->cipherInfo
,context
->macBuf
,
2151 &outlen
,SFTK_MAX_BLOCK_SIZE
,context
->padBuf
,context
->blockSize
);
2153 if (rv
== SECSuccess
) {
2154 PORT_Memcpy(pSignature
,context
->macBuf
,context
->macSize
);
2155 *pulSignatureLen
= context
->macSize
;
2159 sftk_FreeContext(context
);
2160 sftk_SetContextByType(session
, SFTK_SIGN
, NULL
);
2163 sftk_FreeSession(session
);
2165 return (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
2168 /* NSC_Sign signs (encrypts with private key) data in a single part,
2169 * where the signature is (will be) an appendix to the data,
2170 * and plaintext cannot be recovered from the signature */
2171 CK_RV
NSC_Sign(CK_SESSION_HANDLE hSession
,
2172 CK_BYTE_PTR pData
,CK_ULONG ulDataLen
,CK_BYTE_PTR pSignature
,
2173 CK_ULONG_PTR pulSignatureLen
)
2175 SFTKSession
*session
;
2176 SFTKSessionContext
*context
;
2177 unsigned int outlen
;
2178 unsigned int maxoutlen
= *pulSignatureLen
;
2180 SECStatus rv
= SECSuccess
;
2184 /* make sure we're legal */
2185 crv
= sftk_GetContext(hSession
,&context
,SFTK_SIGN
,PR_FALSE
,&session
);
2186 if (crv
!= CKR_OK
) return crv
;
2189 *pulSignatureLen
= context
->maxLen
;
2193 /* multi part Signing are completely implemented by SignUpdate and
2195 if (context
->multi
) {
2196 sftk_FreeSession(session
);
2197 crv
= NSC_SignUpdate(hSession
,pData
,ulDataLen
);
2198 if (crv
!= CKR_OK
) *pulSignatureLen
= 0;
2199 crv2
= NSC_SignFinal(hSession
, pSignature
, pulSignatureLen
);
2200 return crv
== CKR_OK
? crv2
:crv
;
2203 rv
= (*context
->update
)(context
->cipherInfo
, pSignature
,
2204 &outlen
, maxoutlen
, pData
, ulDataLen
);
2205 *pulSignatureLen
= (CK_ULONG
) outlen
;
2206 sftk_FreeContext(context
);
2207 sftk_SetContextByType(session
, SFTK_SIGN
, NULL
);
2210 sftk_FreeSession(session
);
2212 return (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
2217 ************** Crypto Functions: Sign Recover ************************
2219 /* NSC_SignRecoverInit initializes a signature operation,
2220 * where the (digest) data can be recovered from the signature.
2221 * E.g. encryption with the user's private key */
2222 CK_RV
NSC_SignRecoverInit(CK_SESSION_HANDLE hSession
,
2223 CK_MECHANISM_PTR pMechanism
,CK_OBJECT_HANDLE hKey
)
2227 switch (pMechanism
->mechanism
) {
2230 return NSC_SignInit(hSession
,pMechanism
,hKey
);
2234 return CKR_MECHANISM_INVALID
;
2238 /* NSC_SignRecover signs data in a single operation
2239 * where the (digest) data can be recovered from the signature.
2240 * E.g. encryption with the user's private key */
2241 CK_RV
NSC_SignRecover(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pData
,
2242 CK_ULONG ulDataLen
, CK_BYTE_PTR pSignature
, CK_ULONG_PTR pulSignatureLen
)
2246 return NSC_Sign(hSession
,pData
,ulDataLen
,pSignature
,pulSignatureLen
);
2250 ************** Crypto Functions: verify ************************
2253 /* Handle RSA Signature formatting */
2255 sftk_hashCheckSign(SFTKHashVerifyInfo
*info
, unsigned char *sig
,
2256 unsigned int sigLen
, unsigned char *digest
, unsigned int digestLen
)
2258 return RSA_HashCheckSign(info
->hashOid
, info
->key
, sig
, sigLen
,
2263 RSA_HashCheckSign(SECOidTag hashOid
, NSSLOWKEYPublicKey
*key
,
2264 unsigned char *sig
, unsigned int sigLen
,
2265 unsigned char *digest
, unsigned int digestLen
)
2269 SGNDigestInfo
*di
= NULL
;
2270 SECStatus rv
= SECSuccess
;
2274 if (key
== NULL
) goto loser
;
2276 it
.len
= nsslowkey_PublicModulusLen(key
);
2277 if (!it
.len
) goto loser
;
2279 it
.data
= (unsigned char *) PORT_Alloc(it
.len
);
2280 if (it
.data
== NULL
) goto loser
;
2282 /* decrypt the block */
2283 rv
= RSA_CheckSignRecover(key
, it
.data
, &it
.len
, it
.len
, sig
, sigLen
);
2284 if (rv
!= SECSuccess
) goto loser
;
2286 di
= SGN_DecodeDigestInfo(&it
);
2287 if (di
== NULL
) goto loser
;
2288 if (di
->digest
.len
!= digestLen
) goto loser
;
2290 /* make sure the tag is OK */
2291 if (SECOID_GetAlgorithmTag(&di
->digestAlgorithm
) != hashOid
) {
2294 /* make sure the "parameters" are not too bogus. */
2295 if (di
->digestAlgorithm
.parameters
.len
> 2) {
2298 /* Now check the signature */
2299 if (PORT_Memcmp(digest
, di
->digest
.data
, di
->digest
.len
) == 0) {
2304 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
2308 if (it
.data
!= NULL
) PORT_Free(it
.data
);
2309 if (di
!= NULL
) SGN_DestroyDigestInfo(di
);
2314 /* NSC_VerifyInit initializes a verification operation,
2315 * where the signature is an appendix to the data,
2316 * and plaintext cannot be recovered from the signature (e.g. DSA) */
2317 CK_RV
NSC_VerifyInit(CK_SESSION_HANDLE hSession
,
2318 CK_MECHANISM_PTR pMechanism
,CK_OBJECT_HANDLE hKey
)
2320 SFTKSession
*session
;
2322 SFTKSessionContext
*context
;
2323 CK_KEY_TYPE key_type
;
2325 NSSLOWKEYPublicKey
*pubKey
;
2326 SFTKHashVerifyInfo
*info
= NULL
;
2330 /* Block Cipher MACing Algorithms use a different Context init method..*/
2331 crv
= sftk_InitCBCMac(hSession
, pMechanism
, hKey
, CKA_VERIFY
, SFTK_VERIFY
);
2332 if (crv
!= CKR_FUNCTION_NOT_SUPPORTED
) return crv
;
2334 session
= sftk_SessionFromHandle(hSession
);
2335 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
2336 crv
= sftk_InitGeneric(session
,&context
,SFTK_VERIFY
,&key
,hKey
,&key_type
,
2337 CKO_PUBLIC_KEY
,CKA_VERIFY
);
2338 if (crv
!= CKR_OK
) {
2339 sftk_FreeSession(session
);
2343 context
->multi
= PR_FALSE
;
2345 #define INIT_RSA_VFY_MECH(mmm) \
2346 case CKM_ ## mmm ## _RSA_PKCS: \
2347 context->multi = PR_TRUE; \
2348 crv = sftk_doSub ## mmm (context); \
2349 if (crv != CKR_OK) break; \
2350 context->verify = (SFTKVerify) sftk_hashCheckSign; \
2351 info = PORT_New(SFTKHashVerifyInfo); \
2352 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \
2353 info->hashOid = SEC_OID_ ## mmm ; \
2356 switch(pMechanism
->mechanism
) {
2357 INIT_RSA_VFY_MECH(MD5
)
2358 INIT_RSA_VFY_MECH(MD2
)
2359 INIT_RSA_VFY_MECH(SHA1
)
2360 INIT_RSA_VFY_MECH(SHA256
)
2361 INIT_RSA_VFY_MECH(SHA384
)
2362 INIT_RSA_VFY_MECH(SHA512
)
2365 context
->verify
= (SFTKVerify
) RSA_CheckSign
;
2368 context
->verify
= (SFTKVerify
) RSA_CheckSignRaw
;
2370 if (key_type
!= CKK_RSA
) {
2371 crv
= CKR_KEY_TYPE_INCONSISTENT
;
2374 pubKey
= sftk_GetPubKey(key
,CKK_RSA
,&crv
);
2375 if (pubKey
== NULL
) {
2380 context
->cipherInfo
= info
;
2381 context
->destroy
= sftk_Space
;
2383 context
->cipherInfo
= pubKey
;
2384 context
->destroy
= sftk_Null
;
2388 context
->multi
= PR_TRUE
;
2389 crv
= sftk_doSubSHA1(context
);
2390 if (crv
!= CKR_OK
) break;
2393 if (key_type
!= CKK_DSA
) {
2394 crv
= CKR_KEY_TYPE_INCONSISTENT
;
2397 pubKey
= sftk_GetPubKey(key
,CKK_DSA
,&crv
);
2398 if (pubKey
== NULL
) {
2401 context
->cipherInfo
= pubKey
;
2402 context
->verify
= (SFTKVerify
) nsc_DSA_Verify_Stub
;
2403 context
->destroy
= sftk_Null
;
2405 #ifdef NSS_ENABLE_ECC
2406 case CKM_ECDSA_SHA1
:
2407 context
->multi
= PR_TRUE
;
2408 crv
= sftk_doSubSHA1(context
);
2409 if (crv
!= CKR_OK
) break;
2412 if (key_type
!= CKK_EC
) {
2413 crv
= CKR_KEY_TYPE_INCONSISTENT
;
2416 pubKey
= sftk_GetPubKey(key
,CKK_EC
,&crv
);
2417 if (pubKey
== NULL
) {
2418 crv
= CKR_HOST_MEMORY
;
2421 context
->cipherInfo
= pubKey
;
2422 context
->verify
= (SFTKVerify
) nsc_ECDSAVerifyStub
;
2423 context
->destroy
= sftk_Null
;
2425 #endif /* NSS_ENABLE_ECC */
2429 INIT_HMAC_MECH(SHA256
)
2430 INIT_HMAC_MECH(SHA384
)
2431 INIT_HMAC_MECH(SHA512
)
2433 case CKM_SHA_1_HMAC_GENERAL
:
2434 crv
= sftk_doHMACInit(context
,HASH_AlgSHA1
,key
,
2435 *(CK_ULONG
*)pMechanism
->pParameter
);
2437 case CKM_SHA_1_HMAC
:
2438 crv
= sftk_doHMACInit(context
,HASH_AlgSHA1
,key
,SHA1_LENGTH
);
2441 case CKM_SSL3_MD5_MAC
:
2442 crv
= sftk_doSSLMACInit(context
,SEC_OID_MD5
,key
,
2443 *(CK_ULONG
*)pMechanism
->pParameter
);
2445 case CKM_SSL3_SHA1_MAC
:
2446 crv
= sftk_doSSLMACInit(context
,SEC_OID_SHA1
,key
,
2447 *(CK_ULONG
*)pMechanism
->pParameter
);
2449 case CKM_TLS_PRF_GENERAL
:
2450 crv
= sftk_TLSPRFInit(context
, key
, key_type
);
2454 crv
= CKR_MECHANISM_INVALID
;
2458 if (crv
!= CKR_OK
) {
2459 if (info
) PORT_Free(info
);
2461 sftk_FreeSession(session
);
2464 sftk_SetContextByType(session
, SFTK_VERIFY
, context
);
2465 sftk_FreeSession(session
);
2469 /* NSC_Verify verifies a signature in a single-part operation,
2470 * where the signature is an appendix to the data,
2471 * and plaintext cannot be recovered from the signature */
2472 CK_RV
NSC_Verify(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pData
,
2473 CK_ULONG ulDataLen
, CK_BYTE_PTR pSignature
, CK_ULONG ulSignatureLen
)
2475 SFTKSession
*session
;
2476 SFTKSessionContext
*context
;
2482 /* make sure we're legal */
2483 crv
= sftk_GetContext(hSession
,&context
,SFTK_VERIFY
,PR_FALSE
,&session
);
2484 if (crv
!= CKR_OK
) return crv
;
2486 /* multi part Verifying are completely implemented by VerifyUpdate and
2488 if (context
->multi
) {
2489 sftk_FreeSession(session
);
2490 crv
= NSC_VerifyUpdate(hSession
, pData
, ulDataLen
);
2491 crv2
= NSC_VerifyFinal(hSession
, pSignature
, ulSignatureLen
);
2492 return crv
== CKR_OK
? crv2
:crv
;
2495 rv
= (*context
->verify
)(context
->cipherInfo
,pSignature
, ulSignatureLen
,
2497 sftk_FreeContext(context
);
2498 sftk_SetContextByType(session
, SFTK_VERIFY
, NULL
);
2499 sftk_FreeSession(session
);
2501 return (rv
== SECSuccess
) ? CKR_OK
: CKR_SIGNATURE_INVALID
;
2506 /* NSC_VerifyUpdate continues a multiple-part verification operation,
2507 * where the signature is an appendix to the data,
2508 * and plaintext cannot be recovered from the signature */
2509 CK_RV
NSC_VerifyUpdate( CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pPart
,
2514 return sftk_MACUpdate(hSession
, pPart
, ulPartLen
, SFTK_VERIFY
);
2518 /* NSC_VerifyFinal finishes a multiple-part verification operation,
2519 * checking the signature. */
2520 CK_RV
NSC_VerifyFinal(CK_SESSION_HANDLE hSession
,
2521 CK_BYTE_PTR pSignature
,CK_ULONG ulSignatureLen
)
2523 SFTKSession
*session
;
2524 SFTKSessionContext
*context
;
2525 unsigned int outlen
;
2526 unsigned int digestLen
;
2527 unsigned char tmpbuf
[SFTK_MAX_MAC_LENGTH
];
2529 SECStatus rv
= SECSuccess
;
2533 /* make sure we're legal */
2534 crv
= sftk_GetContext(hSession
,&context
,SFTK_VERIFY
,PR_TRUE
,&session
);
2535 if (crv
!= CKR_OK
) return crv
;
2537 if (context
->hashInfo
) {
2538 (*context
->end
)(context
->hashInfo
, tmpbuf
, &digestLen
, sizeof(tmpbuf
));
2539 rv
= (*context
->verify
)(context
->cipherInfo
, pSignature
,
2540 ulSignatureLen
, tmpbuf
, digestLen
);
2542 if (context
->padDataLength
) {
2543 /* fill out rest of pad buffer with pad magic*/
2545 for (i
=context
->padDataLength
; i
< (int)context
->blockSize
; i
++) {
2546 context
->padBuf
[i
] = 0;
2548 rv
= (*context
->update
)(context
->cipherInfo
,context
->macBuf
,
2549 &outlen
,SFTK_MAX_BLOCK_SIZE
,context
->padBuf
,context
->blockSize
);
2551 if (rv
== SECSuccess
) {
2552 rv
=(PORT_Memcmp(pSignature
,context
->macBuf
,context
->macSize
) == 0)
2553 ? SECSuccess
: SECFailure
;
2557 sftk_FreeContext(context
);
2558 sftk_SetContextByType(session
, SFTK_VERIFY
, NULL
);
2559 sftk_FreeSession(session
);
2560 return (rv
== SECSuccess
) ? CKR_OK
: CKR_SIGNATURE_INVALID
;
2565 ************** Crypto Functions: Verify Recover ************************
2568 /* NSC_VerifyRecoverInit initializes a signature verification operation,
2569 * where the data is recovered from the signature.
2570 * E.g. Decryption with the user's public key */
2571 CK_RV
NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession
,
2572 CK_MECHANISM_PTR pMechanism
,CK_OBJECT_HANDLE hKey
)
2574 SFTKSession
*session
;
2576 SFTKSessionContext
*context
;
2577 CK_KEY_TYPE key_type
;
2579 NSSLOWKEYPublicKey
*pubKey
;
2583 session
= sftk_SessionFromHandle(hSession
);
2584 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
2585 crv
= sftk_InitGeneric(session
,&context
,SFTK_VERIFY_RECOVER
,
2586 &key
,hKey
,&key_type
,CKO_PUBLIC_KEY
,CKA_VERIFY_RECOVER
);
2587 if (crv
!= CKR_OK
) {
2588 sftk_FreeSession(session
);
2592 context
->multi
= PR_TRUE
;
2594 switch(pMechanism
->mechanism
) {
2597 if (key_type
!= CKK_RSA
) {
2598 crv
= CKR_KEY_TYPE_INCONSISTENT
;
2601 context
->multi
= PR_FALSE
;
2602 pubKey
= sftk_GetPubKey(key
,CKK_RSA
,&crv
);
2603 if (pubKey
== NULL
) {
2606 context
->cipherInfo
= pubKey
;
2607 context
->update
= (SFTKCipher
) (pMechanism
->mechanism
== CKM_RSA_X_509
2608 ? RSA_CheckSignRecoverRaw
: RSA_CheckSignRecover
);
2609 context
->destroy
= sftk_Null
;
2612 crv
= CKR_MECHANISM_INVALID
;
2616 if (crv
!= CKR_OK
) {
2618 sftk_FreeSession(session
);
2621 sftk_SetContextByType(session
, SFTK_VERIFY_RECOVER
, context
);
2622 sftk_FreeSession(session
);
2627 /* NSC_VerifyRecover verifies a signature in a single-part operation,
2628 * where the data is recovered from the signature.
2629 * E.g. Decryption with the user's public key */
2630 CK_RV
NSC_VerifyRecover(CK_SESSION_HANDLE hSession
,
2631 CK_BYTE_PTR pSignature
,CK_ULONG ulSignatureLen
,
2632 CK_BYTE_PTR pData
,CK_ULONG_PTR pulDataLen
)
2634 SFTKSession
*session
;
2635 SFTKSessionContext
*context
;
2636 unsigned int outlen
;
2637 unsigned int maxoutlen
= *pulDataLen
;
2643 /* make sure we're legal */
2644 crv
= sftk_GetContext(hSession
,&context
,SFTK_VERIFY_RECOVER
,
2646 if (crv
!= CKR_OK
) return crv
;
2647 if (pData
== NULL
) {
2648 /* to return the actual size, we need to do the decrypt, just return
2649 * the max size, which is the size of the input signature. */
2650 *pulDataLen
= ulSignatureLen
;
2655 rv
= (*context
->update
)(context
->cipherInfo
, pData
, &outlen
, maxoutlen
,
2656 pSignature
, ulSignatureLen
);
2657 *pulDataLen
= (CK_ULONG
) outlen
;
2659 sftk_FreeContext(context
);
2660 sftk_SetContextByType(session
, SFTK_VERIFY_RECOVER
, NULL
);
2662 sftk_FreeSession(session
);
2663 return (rv
== SECSuccess
) ? CKR_OK
: CKR_SIGNATURE_INVALID
;
2667 **************************** Random Functions: ************************
2670 /* NSC_SeedRandom mixes additional seed material into the token's random number
2672 CK_RV
NSC_SeedRandom(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pSeed
,
2679 rv
= RNG_RandomUpdate(pSeed
, ulSeedLen
);
2680 return (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
2683 /* NSC_GenerateRandom generates random data. */
2684 CK_RV
NSC_GenerateRandom(CK_SESSION_HANDLE hSession
,
2685 CK_BYTE_PTR pRandomData
, CK_ULONG ulRandomLen
)
2691 rv
= RNG_GenerateGlobalRandomBytes(pRandomData
, ulRandomLen
);
2692 return (rv
== SECSuccess
) ? CKR_OK
: CKR_DEVICE_ERROR
;
2696 **************************** Key Functions: ************************
2701 * generate a password based encryption key. This code uses
2702 * PKCS5 to do the work.
2705 nsc_pbe_key_gen(NSSPKCS5PBEParameter
*pkcs5_pbe
, CK_MECHANISM_PTR pMechanism
,
2706 void *buf
, CK_ULONG
*key_length
, PRBool faulty3DES
)
2708 SECItem
*pbe_key
= NULL
, iv
, pwitem
;
2709 CK_PBE_PARAMS
*pbe_params
= NULL
;
2710 CK_PKCS5_PBKD2_PARAMS
*pbkd2_params
= NULL
;
2713 iv
.data
= NULL
; iv
.len
= 0;
2715 if (pMechanism
->mechanism
== CKM_PKCS5_PBKD2
) {
2716 pbkd2_params
= (CK_PKCS5_PBKD2_PARAMS
*)pMechanism
->pParameter
;
2717 pwitem
.data
= (unsigned char *)pbkd2_params
->pPassword
;
2718 /* was this a typo in the PKCS #11 spec? */
2719 pwitem
.len
= *pbkd2_params
->ulPasswordLen
;
2721 pbe_params
= (CK_PBE_PARAMS
*)pMechanism
->pParameter
;
2722 pwitem
.data
= (unsigned char *)pbe_params
->pPassword
;
2723 pwitem
.len
= pbe_params
->ulPasswordLen
;
2725 pbe_key
= nsspkcs5_ComputeKeyAndIV(pkcs5_pbe
, &pwitem
, &iv
, faulty3DES
);
2726 if (pbe_key
== NULL
) {
2727 return CKR_HOST_MEMORY
;
2730 PORT_Memcpy(buf
, pbe_key
->data
, pbe_key
->len
);
2731 *key_length
= pbe_key
->len
;
2732 SECITEM_ZfreeItem(pbe_key
, PR_TRUE
);
2736 if (pbe_params
&& pbe_params
->pInitVector
!= NULL
) {
2737 PORT_Memcpy(pbe_params
->pInitVector
, iv
.data
, iv
.len
);
2745 nsc_parameter_gen(CK_KEY_TYPE key_type
, SFTKObject
*key
)
2747 SFTKAttribute
*attribute
;
2749 unsigned int seedBits
= 0;
2750 unsigned int primeBits
;
2753 PQGParams
*params
= NULL
;
2754 PQGVerify
*vfy
= NULL
;
2757 attribute
= sftk_FindAttribute(key
, CKA_PRIME_BITS
);
2758 if (attribute
== NULL
) {
2759 return CKR_TEMPLATE_INCOMPLETE
;
2761 primeBits
= (unsigned int) *(CK_ULONG
*)attribute
->attrib
.pValue
;
2762 sftk_FreeAttribute(attribute
);
2763 j
= PQG_PBITS_TO_INDEX(primeBits
);
2764 if (j
== (unsigned int)-1) {
2765 return CKR_ATTRIBUTE_VALUE_INVALID
;
2768 attribute
= sftk_FindAttribute(key
, CKA_NETSCAPE_PQG_SEED_BITS
);
2769 if (attribute
!= NULL
) {
2770 seedBits
= (unsigned int) *(CK_ULONG
*)attribute
->attrib
.pValue
;
2771 sftk_FreeAttribute(attribute
);
2774 sftk_DeleteAttributeType(key
,CKA_PRIME_BITS
);
2775 sftk_DeleteAttributeType(key
,CKA_NETSCAPE_PQG_SEED_BITS
);
2777 if (seedBits
== 0) {
2778 rv
= PQG_ParamGen(j
, ¶ms
, &vfy
);
2780 rv
= PQG_ParamGenSeedLen(j
,seedBits
/8, ¶ms
, &vfy
);
2783 if (rv
!= SECSuccess
) {
2784 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE
) {
2785 sftk_fatalError
= PR_TRUE
;
2787 return CKR_DEVICE_ERROR
;
2789 crv
= sftk_AddAttributeType(key
,CKA_PRIME
,
2790 params
->prime
.data
, params
->prime
.len
);
2791 if (crv
!= CKR_OK
) goto loser
;
2792 crv
= sftk_AddAttributeType(key
,CKA_SUBPRIME
,
2793 params
->subPrime
.data
, params
->subPrime
.len
);
2794 if (crv
!= CKR_OK
) goto loser
;
2795 crv
= sftk_AddAttributeType(key
,CKA_BASE
,
2796 params
->base
.data
, params
->base
.len
);
2797 if (crv
!= CKR_OK
) goto loser
;
2798 counter
= vfy
->counter
;
2799 crv
= sftk_AddAttributeType(key
,CKA_NETSCAPE_PQG_COUNTER
,
2800 &counter
, sizeof(counter
));
2801 crv
= sftk_AddAttributeType(key
,CKA_NETSCAPE_PQG_SEED
,
2802 vfy
->seed
.data
, vfy
->seed
.len
);
2803 if (crv
!= CKR_OK
) goto loser
;
2804 crv
= sftk_AddAttributeType(key
,CKA_NETSCAPE_PQG_H
,
2805 vfy
->h
.data
, vfy
->h
.len
);
2806 if (crv
!= CKR_OK
) goto loser
;
2810 PQG_DestroyParams(params
);
2813 PQG_DestroyVerify(vfy
);
2820 nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism
, CK_KEY_TYPE
*key_type
,
2821 CK_ULONG
*key_length
)
2825 switch (mechanism
) {
2826 case CKM_RC2_KEY_GEN
:
2827 *key_type
= CKK_RC2
;
2828 if (*key_length
== 0) crv
= CKR_TEMPLATE_INCOMPLETE
;
2830 #if NSS_SOFTOKEN_DOES_RC5
2831 case CKM_RC5_KEY_GEN
:
2832 *key_type
= CKK_RC5
;
2833 if (*key_length
== 0) crv
= CKR_TEMPLATE_INCOMPLETE
;
2836 case CKM_RC4_KEY_GEN
:
2837 *key_type
= CKK_RC4
;
2838 if (*key_length
== 0) crv
= CKR_TEMPLATE_INCOMPLETE
;
2840 case CKM_GENERIC_SECRET_KEY_GEN
:
2841 *key_type
= CKK_GENERIC_SECRET
;
2842 if (*key_length
== 0) crv
= CKR_TEMPLATE_INCOMPLETE
;
2844 case CKM_CDMF_KEY_GEN
:
2845 *key_type
= CKK_CDMF
;
2848 case CKM_DES_KEY_GEN
:
2849 *key_type
= CKK_DES
;
2852 case CKM_DES2_KEY_GEN
:
2853 *key_type
= CKK_DES2
;
2856 case CKM_DES3_KEY_GEN
:
2857 *key_type
= CKK_DES3
;
2860 case CKM_CAMELLIA_KEY_GEN
:
2861 *key_type
= CKK_CAMELLIA
;
2862 if (*key_length
== 0) crv
= CKR_TEMPLATE_INCOMPLETE
;
2864 case CKM_AES_KEY_GEN
:
2865 *key_type
= CKK_AES
;
2866 if (*key_length
== 0) crv
= CKR_TEMPLATE_INCOMPLETE
;
2870 crv
= CKR_MECHANISM_INVALID
;
2878 nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism
, NSSPKCS5PBEParameter
**pbe
)
2881 CK_PBE_PARAMS
*pbe_params
= NULL
;
2882 NSSPKCS5PBEParameter
*params
;
2883 PRArenaPool
*arena
= NULL
;
2888 arena
= PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE
);
2889 if (arena
== NULL
) {
2890 return CKR_HOST_MEMORY
;
2893 params
= (NSSPKCS5PBEParameter
*) PORT_ArenaZAlloc(arena
,
2894 sizeof(NSSPKCS5PBEParameter
));
2895 if (params
== NULL
) {
2896 PORT_FreeArena(arena
,PR_TRUE
);
2897 return CKR_HOST_MEMORY
;
2900 params
->poolp
= arena
;
2902 params
->pbeType
= NSSPKCS5_PKCS12_V2
;
2903 params
->hashType
= HASH_AlgSHA1
;
2904 params
->encAlg
= SEC_OID_SHA1
; /* any invalid value */
2905 params
->is2KeyDES
= PR_FALSE
;
2906 params
->keyID
= pbeBitGenIntegrityKey
;
2907 pbe_params
= (CK_PBE_PARAMS
*)pMechanism
->pParameter
;
2908 params
->iter
= pbe_params
->ulIteration
;
2910 salt
.data
= (unsigned char *)pbe_params
->pSalt
;
2911 salt
.len
= (unsigned int)pbe_params
->ulSaltLen
;
2912 rv
= SECITEM_CopyItem(arena
,¶ms
->salt
,&salt
);
2913 if (rv
!= SECSuccess
) {
2914 PORT_FreeArena(arena
,PR_TRUE
);
2915 return CKR_HOST_MEMORY
;
2917 switch (pMechanism
->mechanism
) {
2918 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN
:
2919 case CKM_PBA_SHA1_WITH_SHA1_HMAC
:
2920 params
->hashType
= HASH_AlgSHA1
;
2921 params
->keyLen
= 20;
2923 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN
:
2924 params
->hashType
= HASH_AlgMD5
;
2925 params
->keyLen
= 16;
2927 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN
:
2928 params
->hashType
= HASH_AlgMD2
;
2929 params
->keyLen
= 16;
2932 PORT_FreeArena(arena
,PR_TRUE
);
2933 return CKR_MECHANISM_INVALID
;
2939 /* maybe this should be table driven? */
2941 nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism
, NSSPKCS5PBEParameter
**pbe
,
2942 CK_KEY_TYPE
*key_type
, CK_ULONG
*key_length
)
2946 CK_PBE_PARAMS
*pbe_params
= NULL
;
2947 NSSPKCS5PBEParameter
*params
= NULL
;
2948 CK_PKCS5_PBKD2_PARAMS
*pbkd2_params
= NULL
;
2950 CK_ULONG iteration
= 0;
2954 oid
= SECOID_FindOIDByMechanism(pMechanism
->mechanism
);
2956 return CKR_MECHANISM_INVALID
;
2959 if (pMechanism
->mechanism
== CKM_PKCS5_PBKD2
) {
2960 pbkd2_params
= (CK_PKCS5_PBKD2_PARAMS
*)pMechanism
->pParameter
;
2961 if (pbkd2_params
->saltSource
!= CKZ_SALT_SPECIFIED
) {
2962 return CKR_MECHANISM_PARAM_INVALID
;
2964 salt
.data
= (unsigned char *)pbkd2_params
->pSaltSourceData
;
2965 salt
.len
= (unsigned int)pbkd2_params
->ulSaltSourceDataLen
;
2966 iteration
= pbkd2_params
->iterations
;
2968 pbe_params
= (CK_PBE_PARAMS
*)pMechanism
->pParameter
;
2969 salt
.data
= (unsigned char *)pbe_params
->pSalt
;
2970 salt
.len
= (unsigned int)pbe_params
->ulSaltLen
;
2971 iteration
= pbe_params
->ulIteration
;
2973 params
=nsspkcs5_NewParam(oid
->offset
, &salt
, iteration
);
2974 if (params
== NULL
) {
2975 return CKR_MECHANISM_INVALID
;
2978 switch (params
->encAlg
) {
2979 case SEC_OID_DES_CBC
:
2980 *key_type
= CKK_DES
;
2981 *key_length
= params
->keyLen
;
2983 case SEC_OID_DES_EDE3_CBC
:
2984 *key_type
= params
->is2KeyDES
? CKK_DES2
: CKK_DES3
;
2985 *key_length
= params
->keyLen
;
2987 case SEC_OID_RC2_CBC
:
2988 *key_type
= CKK_RC2
;
2989 *key_length
= params
->keyLen
;
2992 *key_type
= CKK_RC4
;
2993 *key_length
= params
->keyLen
;
2995 case SEC_OID_PKCS5_PBKDF2
:
2996 /* sigh, PKCS #11 currently only defines SHA1 for the KDF hash type.
2997 * we do the check here because this where we would handle multiple
2998 * hash types in the future */
2999 if (pbkd2_params
== NULL
||
3000 pbkd2_params
->prf
!= CKP_PKCS5_PBKD2_HMAC_SHA1
) {
3001 crv
= CKR_MECHANISM_PARAM_INVALID
;
3004 /* key type must already be set */
3005 if (*key_type
== CKK_INVALID_KEY_TYPE
) {
3006 crv
= CKR_TEMPLATE_INCOMPLETE
;
3009 /* PBKDF2 needs to calculate the key length from the other parameters
3011 if (*key_length
== 0) {
3012 *key_length
= sftk_MapKeySize(*key_type
);
3014 if (*key_length
== 0) {
3015 crv
= CKR_TEMPLATE_INCOMPLETE
;
3018 params
->keyLen
= *key_length
;
3021 crv
= CKR_MECHANISM_INVALID
;
3022 nsspkcs5_DestroyPBEParameter(params
);
3025 if (crv
== CKR_OK
) {
3031 /* NSC_GenerateKey generates a secret key, creating a new key object. */
3032 CK_RV
NSC_GenerateKey(CK_SESSION_HANDLE hSession
,
3033 CK_MECHANISM_PTR pMechanism
,CK_ATTRIBUTE_PTR pTemplate
,CK_ULONG ulCount
,
3034 CK_OBJECT_HANDLE_PTR phKey
)
3037 SFTKSession
*session
;
3038 PRBool checkWeak
= PR_FALSE
;
3039 CK_ULONG key_length
= 0;
3040 CK_KEY_TYPE key_type
= CKK_INVALID_KEY_TYPE
;
3041 CK_OBJECT_CLASS objclass
= CKO_SECRET_KEY
;
3043 CK_BBOOL cktrue
= CK_TRUE
;
3045 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
3046 unsigned char buf
[MAX_KEY_LEN
];
3047 enum {nsc_pbe
, nsc_ssl
, nsc_bulk
, nsc_param
} key_gen_type
;
3048 NSSPKCS5PBEParameter
*pbe_param
;
3049 SSL3RSAPreMasterSecret
*rsa_pms
;
3050 CK_VERSION
*version
;
3051 /* in very old versions of NSS, there were implementation errors with key
3052 * generation methods. We want to beable to read these, but not
3053 * produce them any more. The affected algorithm was 3DES.
3055 PRBool faultyPBE3DES
= PR_FALSE
;
3060 return CKR_SESSION_HANDLE_INVALID
;
3063 * now lets create an object to hang the attributes off of
3065 key
= sftk_NewObject(slot
); /* fill in the handle later */
3067 return CKR_HOST_MEMORY
;
3071 * load the template values into the object
3073 for (i
=0; i
< (int) ulCount
; i
++) {
3074 if (pTemplate
[i
].type
== CKA_VALUE_LEN
) {
3075 key_length
= *(CK_ULONG
*)pTemplate
[i
].pValue
;
3078 /* some algorithms need keytype specified */
3079 if (pTemplate
[i
].type
== CKA_KEY_TYPE
) {
3080 key_type
= *(CK_ULONG
*)pTemplate
[i
].pValue
;
3084 crv
= sftk_AddAttributeType(key
,sftk_attr_expand(&pTemplate
[i
]));
3085 if (crv
!= CKR_OK
) break;
3087 if (crv
!= CKR_OK
) {
3088 sftk_FreeObject(key
);
3092 /* make sure we don't have any class, key_type, or value fields */
3093 sftk_DeleteAttributeType(key
,CKA_CLASS
);
3094 sftk_DeleteAttributeType(key
,CKA_KEY_TYPE
);
3095 sftk_DeleteAttributeType(key
,CKA_VALUE
);
3097 /* Now Set up the parameters to generate the key (based on mechanism) */
3098 key_gen_type
= nsc_bulk
; /* bulk key by default */
3099 switch (pMechanism
->mechanism
) {
3100 case CKM_CDMF_KEY_GEN
:
3101 case CKM_DES_KEY_GEN
:
3102 case CKM_DES2_KEY_GEN
:
3103 case CKM_DES3_KEY_GEN
:
3104 checkWeak
= PR_TRUE
;
3105 case CKM_RC2_KEY_GEN
:
3106 case CKM_RC4_KEY_GEN
:
3107 case CKM_GENERIC_SECRET_KEY_GEN
:
3108 case CKM_CAMELLIA_KEY_GEN
:
3109 case CKM_AES_KEY_GEN
:
3110 #if NSS_SOFTOKEN_DOES_RC5
3111 case CKM_RC5_KEY_GEN
:
3113 crv
= nsc_SetupBulkKeyGen(pMechanism
->mechanism
,&key_type
,&key_length
);
3115 case CKM_SSL3_PRE_MASTER_KEY_GEN
:
3116 key_type
= CKK_GENERIC_SECRET
;
3118 key_gen_type
= nsc_ssl
;
3120 case CKM_PBA_SHA1_WITH_SHA1_HMAC
:
3121 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN
:
3122 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN
:
3123 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN
:
3124 key_gen_type
= nsc_pbe
;
3125 key_type
= CKK_GENERIC_SECRET
;
3126 crv
= nsc_SetupHMACKeyGen(pMechanism
, &pbe_param
);
3128 case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC
:
3129 faultyPBE3DES
= PR_TRUE
;
3130 case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC
:
3131 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC
:
3132 case CKM_NETSCAPE_PBE_SHA1_DES_CBC
:
3133 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC
:
3134 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4
:
3135 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4
:
3136 case CKM_PBE_SHA1_DES3_EDE_CBC
:
3137 case CKM_PBE_SHA1_DES2_EDE_CBC
:
3138 case CKM_PBE_SHA1_RC2_128_CBC
:
3139 case CKM_PBE_SHA1_RC2_40_CBC
:
3140 case CKM_PBE_SHA1_RC4_128
:
3141 case CKM_PBE_SHA1_RC4_40
:
3142 case CKM_PBE_MD5_DES_CBC
:
3143 case CKM_PBE_MD2_DES_CBC
:
3144 case CKM_PKCS5_PBKD2
:
3145 key_gen_type
= nsc_pbe
;
3146 crv
= nsc_SetupPBEKeyGen(pMechanism
,&pbe_param
, &key_type
, &key_length
);
3148 case CKM_DSA_PARAMETER_GEN
:
3149 key_gen_type
= nsc_param
;
3151 objclass
= CKO_KG_PARAMETERS
;
3155 crv
= CKR_MECHANISM_INVALID
;
3159 /* make sure we aren't going to overflow the buffer */
3160 if (sizeof(buf
) < key_length
) {
3161 /* someone is getting pretty optimistic about how big their key can
3163 crv
= CKR_TEMPLATE_INCONSISTENT
;
3166 if (crv
!= CKR_OK
) { sftk_FreeObject(key
); return crv
; }
3168 /* if there was no error,
3169 * key_type *MUST* be set in the switch statement above */
3170 PORT_Assert( key_type
!= CKK_INVALID_KEY_TYPE
);
3173 * now to the actual key gen.
3175 switch (key_gen_type
) {
3177 crv
= nsc_pbe_key_gen(pbe_param
, pMechanism
, buf
, &key_length
,
3179 nsspkcs5_DestroyPBEParameter(pbe_param
);
3182 rsa_pms
= (SSL3RSAPreMasterSecret
*)buf
;
3183 version
= (CK_VERSION
*)pMechanism
->pParameter
;
3184 rsa_pms
->client_version
[0] = version
->major
;
3185 rsa_pms
->client_version
[1] = version
->minor
;
3187 NSC_GenerateRandom(0,&rsa_pms
->random
[0], sizeof(rsa_pms
->random
));
3190 /* get the key, check for weak keys and repeat if found */
3192 crv
= NSC_GenerateRandom(0, buf
, key_length
);
3193 } while (crv
== CKR_OK
&& checkWeak
&& sftk_IsWeakKey(buf
,key_type
));
3196 /* generate parameters */
3198 crv
= nsc_parameter_gen(key_type
,key
);
3202 if (crv
!= CKR_OK
) { sftk_FreeObject(key
); return crv
; }
3204 /* Add the class, key_type, and value */
3205 crv
= sftk_AddAttributeType(key
,CKA_CLASS
,&objclass
,sizeof(CK_OBJECT_CLASS
));
3206 if (crv
!= CKR_OK
) { sftk_FreeObject(key
); return crv
; }
3207 crv
= sftk_AddAttributeType(key
,CKA_KEY_TYPE
,&key_type
,sizeof(CK_KEY_TYPE
));
3208 if (crv
!= CKR_OK
) { sftk_FreeObject(key
); return crv
; }
3209 if (key_length
!= 0) {
3210 crv
= sftk_AddAttributeType(key
,CKA_VALUE
,buf
,key_length
);
3211 if (crv
!= CKR_OK
) { sftk_FreeObject(key
); return crv
; }
3214 /* get the session */
3215 session
= sftk_SessionFromHandle(hSession
);
3216 if (session
== NULL
) {
3217 sftk_FreeObject(key
);
3218 return CKR_SESSION_HANDLE_INVALID
;
3222 * handle the base object stuff
3224 crv
= sftk_handleObject(key
,session
);
3225 sftk_FreeSession(session
);
3226 if (sftk_isTrue(key
,CKA_SENSITIVE
)) {
3227 sftk_forceAttribute(key
,CKA_ALWAYS_SENSITIVE
,&cktrue
,sizeof(CK_BBOOL
));
3229 if (!sftk_isTrue(key
,CKA_EXTRACTABLE
)) {
3230 sftk_forceAttribute(key
,CKA_NEVER_EXTRACTABLE
,&cktrue
,sizeof(CK_BBOOL
));
3233 *phKey
= key
->handle
;
3234 sftk_FreeObject(key
);
3238 #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */
3239 #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */
3242 * FIPS 140-2 pairwise consistency check utilized to validate key pair.
3244 * This function returns
3245 * CKR_OK if pairwise consistency check passed
3246 * CKR_GENERAL_ERROR if pairwise consistency check failed
3247 * other error codes if paiswise consistency check could not be
3248 * performed, for example, CKR_HOST_MEMORY.
3251 sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession
,
3252 SFTKObject
*publicKey
, SFTKObject
*privateKey
, CK_KEY_TYPE keyType
)
3255 * Key type Mechanism type
3256 * --------------------------------
3257 * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS
3258 * others => CKM_INVALID_MECHANISM
3260 * For sign/verify: CKK_RSA => CKM_RSA_PKCS
3261 * CKK_DSA => CKM_DSA
3262 * CKK_EC => CKM_ECDSA
3263 * others => CKM_INVALID_MECHANISM
3265 * None of these mechanisms has a parameter.
3267 CK_MECHANISM mech
= {0, NULL
, 0};
3269 CK_ULONG modulusLen
;
3270 PRBool isEncryptable
= PR_FALSE
;
3271 PRBool canSignVerify
= PR_FALSE
;
3272 PRBool isDerivable
= PR_FALSE
;
3275 /* Variables used for Encrypt/Decrypt functions. */
3276 unsigned char *known_message
= (unsigned char *)"Known Crypto Message";
3277 unsigned char plaintext
[PAIRWISE_MESSAGE_LENGTH
];
3278 CK_ULONG bytes_decrypted
;
3279 unsigned char *ciphertext
;
3280 unsigned char *text_compared
;
3281 CK_ULONG bytes_encrypted
;
3282 CK_ULONG bytes_compared
;
3284 /* Variables used for Signature/Verification functions. */
3285 /* always uses SHA-1 digest */
3286 unsigned char *known_digest
= (unsigned char *)"Mozilla Rules World!";
3287 unsigned char *signature
;
3288 CK_ULONG signature_length
;
3290 if (keyType
== CKK_RSA
) {
3291 SFTKAttribute
*attribute
;
3293 /* Get modulus length of private key. */
3294 attribute
= sftk_FindAttribute(privateKey
, CKA_MODULUS
);
3295 if (attribute
== NULL
) {
3296 return CKR_DEVICE_ERROR
;
3298 modulusLen
= attribute
->attrib
.ulValueLen
;
3299 if (*(unsigned char *)attribute
->attrib
.pValue
== 0) {
3302 sftk_FreeAttribute(attribute
);
3305 /**************************************************/
3306 /* Pairwise Consistency Check of Encrypt/Decrypt. */
3307 /**************************************************/
3309 isEncryptable
= sftk_isTrue(privateKey
, CKA_DECRYPT
);
3312 * If the decryption attribute is set, attempt to encrypt
3313 * with the public key and decrypt with the private key.
3315 if (isEncryptable
) {
3316 if (keyType
!= CKK_RSA
) {
3317 return CKR_DEVICE_ERROR
;
3319 bytes_encrypted
= modulusLen
;
3320 mech
.mechanism
= CKM_RSA_PKCS
;
3322 /* Allocate space for ciphertext. */
3323 ciphertext
= (unsigned char *) PORT_ZAlloc(bytes_encrypted
);
3324 if (ciphertext
== NULL
) {
3325 return CKR_HOST_MEMORY
;
3328 /* Prepare for encryption using the public key. */
3329 crv
= NSC_EncryptInit(hSession
, &mech
, publicKey
->handle
);
3330 if (crv
!= CKR_OK
) {
3331 PORT_Free(ciphertext
);
3335 /* Encrypt using the public key. */
3336 crv
= NSC_Encrypt(hSession
,
3338 PAIRWISE_MESSAGE_LENGTH
,
3341 if (crv
!= CKR_OK
) {
3342 PORT_Free(ciphertext
);
3346 /* Always use the smaller of these two values . . . */
3347 bytes_compared
= PR_MIN(bytes_encrypted
, PAIRWISE_MESSAGE_LENGTH
);
3350 * If there was a failure, the plaintext
3351 * goes at the end, therefore . . .
3353 text_compared
= ciphertext
+ bytes_encrypted
- bytes_compared
;
3356 * Check to ensure that ciphertext does
3357 * NOT EQUAL known input message text
3358 * per FIPS PUB 140-2 directive.
3360 if (PORT_Memcmp(text_compared
, known_message
,
3361 bytes_compared
) == 0) {
3362 /* Set error to Invalid PRIVATE Key. */
3363 PORT_SetError(SEC_ERROR_INVALID_KEY
);
3364 PORT_Free(ciphertext
);
3365 return CKR_GENERAL_ERROR
;
3368 /* Prepare for decryption using the private key. */
3369 crv
= NSC_DecryptInit(hSession
, &mech
, privateKey
->handle
);
3370 if (crv
!= CKR_OK
) {
3371 PORT_Free(ciphertext
);
3375 memset(plaintext
, 0, PAIRWISE_MESSAGE_LENGTH
);
3378 * Initialize bytes decrypted to be the
3379 * expected PAIRWISE_MESSAGE_LENGTH.
3381 bytes_decrypted
= PAIRWISE_MESSAGE_LENGTH
;
3384 * Decrypt using the private key.
3385 * NOTE: No need to reset the
3386 * value of bytes_encrypted.
3388 crv
= NSC_Decrypt(hSession
,
3394 /* Finished with ciphertext; free it. */
3395 PORT_Free(ciphertext
);
3397 if (crv
!= CKR_OK
) {
3402 * Check to ensure that the output plaintext
3403 * does EQUAL known input message text.
3405 if ((bytes_decrypted
!= PAIRWISE_MESSAGE_LENGTH
) ||
3406 (PORT_Memcmp(plaintext
, known_message
,
3407 PAIRWISE_MESSAGE_LENGTH
) != 0)) {
3408 /* Set error to Bad PUBLIC Key. */
3409 PORT_SetError(SEC_ERROR_BAD_KEY
);
3410 return CKR_GENERAL_ERROR
;
3414 /**********************************************/
3415 /* Pairwise Consistency Check of Sign/Verify. */
3416 /**********************************************/
3418 canSignVerify
= sftk_isTrue(privateKey
, CKA_SIGN
);
3420 if (canSignVerify
) {
3421 /* Determine length of signature. */
3424 signature_length
= modulusLen
;
3425 mech
.mechanism
= CKM_RSA_PKCS
;
3428 signature_length
= DSA_SIGNATURE_LEN
;
3429 mech
.mechanism
= CKM_DSA
;
3431 #ifdef NSS_ENABLE_ECC
3433 signature_length
= MAX_ECKEY_LEN
* 2;
3434 mech
.mechanism
= CKM_ECDSA
;
3438 return CKR_DEVICE_ERROR
;
3441 /* Allocate space for signature data. */
3442 signature
= (unsigned char *) PORT_ZAlloc(signature_length
);
3443 if (signature
== NULL
) {
3444 return CKR_HOST_MEMORY
;
3447 /* Sign the known hash using the private key. */
3448 crv
= NSC_SignInit(hSession
, &mech
, privateKey
->handle
);
3449 if (crv
!= CKR_OK
) {
3450 PORT_Free(signature
);
3454 crv
= NSC_Sign(hSession
,
3456 PAIRWISE_DIGEST_LENGTH
,
3459 if (crv
!= CKR_OK
) {
3460 PORT_Free(signature
);
3464 /* Verify the known hash using the public key. */
3465 crv
= NSC_VerifyInit(hSession
, &mech
, publicKey
->handle
);
3466 if (crv
!= CKR_OK
) {
3467 PORT_Free(signature
);
3471 crv
= NSC_Verify(hSession
,
3473 PAIRWISE_DIGEST_LENGTH
,
3477 /* Free signature data. */
3478 PORT_Free(signature
);
3480 if ((crv
== CKR_SIGNATURE_LEN_RANGE
) ||
3481 (crv
== CKR_SIGNATURE_INVALID
)) {
3482 return CKR_GENERAL_ERROR
;
3484 if (crv
!= CKR_OK
) {
3489 /**********************************************/
3490 /* Pairwise Consistency Check for Derivation */
3491 /**********************************************/
3493 isDerivable
= sftk_isTrue(privateKey
, CKA_DERIVE
);
3497 * We are not doing consistency check for Diffie-Hellman Key -
3498 * otherwise it would be here
3499 * This is also true for Elliptic Curve Diffie-Hellman keys
3500 * NOTE: EC keys are currently subjected to pairwise
3501 * consistency check for signing/verification.
3504 * FIPS 140-2 had the following pairwise consistency test for
3505 * public and private keys used for key agreement:
3506 * If the keys are used to perform key agreement, then the
3507 * cryptographic module shall create a second, compatible
3508 * key pair. The cryptographic module shall perform both
3509 * sides of the key agreement algorithm and shall compare
3510 * the resulting shared values. If the shared values are
3511 * not equal, the test shall fail.
3512 * This test was removed in Change Notice 3.
3520 /* NSC_GenerateKeyPair generates a public-key/private-key pair,
3521 * creating new key objects. */
3522 CK_RV
NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession
,
3523 CK_MECHANISM_PTR pMechanism
, CK_ATTRIBUTE_PTR pPublicKeyTemplate
,
3524 CK_ULONG ulPublicKeyAttributeCount
, CK_ATTRIBUTE_PTR pPrivateKeyTemplate
,
3525 CK_ULONG ulPrivateKeyAttributeCount
, CK_OBJECT_HANDLE_PTR phPublicKey
,
3526 CK_OBJECT_HANDLE_PTR phPrivateKey
)
3528 SFTKObject
* publicKey
,*privateKey
;
3529 SFTKSession
* session
;
3530 CK_KEY_TYPE key_type
;
3532 CK_BBOOL cktrue
= CK_TRUE
;
3534 CK_OBJECT_CLASS pubClass
= CKO_PUBLIC_KEY
;
3535 CK_OBJECT_CLASS privClass
= CKO_PRIVATE_KEY
;
3537 SFTKSlot
* slot
= sftk_SlotFromSessionHandle(hSession
);
3538 unsigned int bitSize
;
3541 int public_modulus_bits
= 0;
3543 RSAPrivateKey
* rsaPriv
;
3548 DSAPrivateKey
* dsaPriv
;
3550 /* Diffie Hellman */
3551 int private_value_bits
= 0;
3552 DHPrivateKey
* dhPriv
;
3554 #ifdef NSS_ENABLE_ECC
3555 /* Elliptic Curve Cryptography */
3556 SECItem ecEncodedParams
; /* DER Encoded parameters */
3557 ECPrivateKey
* ecPriv
;
3558 ECParams
* ecParams
;
3559 #endif /* NSS_ENABLE_ECC */
3564 return CKR_SESSION_HANDLE_INVALID
;
3567 * now lets create an object to hang the attributes off of
3569 publicKey
= sftk_NewObject(slot
); /* fill in the handle later */
3570 if (publicKey
== NULL
) {
3571 return CKR_HOST_MEMORY
;
3575 * load the template values into the publicKey
3577 for (i
=0; i
< (int) ulPublicKeyAttributeCount
; i
++) {
3578 if (pPublicKeyTemplate
[i
].type
== CKA_MODULUS_BITS
) {
3579 public_modulus_bits
= *(CK_ULONG
*)pPublicKeyTemplate
[i
].pValue
;
3583 crv
= sftk_AddAttributeType(publicKey
,
3584 sftk_attr_expand(&pPublicKeyTemplate
[i
]));
3585 if (crv
!= CKR_OK
) break;
3588 if (crv
!= CKR_OK
) {
3589 sftk_FreeObject(publicKey
);
3590 return CKR_HOST_MEMORY
;
3593 privateKey
= sftk_NewObject(slot
); /* fill in the handle later */
3594 if (privateKey
== NULL
) {
3595 sftk_FreeObject(publicKey
);
3596 return CKR_HOST_MEMORY
;
3599 * now load the private key template
3601 for (i
=0; i
< (int) ulPrivateKeyAttributeCount
; i
++) {
3602 if (pPrivateKeyTemplate
[i
].type
== CKA_VALUE_BITS
) {
3603 private_value_bits
= *(CK_ULONG
*)pPrivateKeyTemplate
[i
].pValue
;
3607 crv
= sftk_AddAttributeType(privateKey
,
3608 sftk_attr_expand(&pPrivateKeyTemplate
[i
]));
3609 if (crv
!= CKR_OK
) break;
3612 if (crv
!= CKR_OK
) {
3613 sftk_FreeObject(publicKey
);
3614 sftk_FreeObject(privateKey
);
3615 return CKR_HOST_MEMORY
;
3617 sftk_DeleteAttributeType(privateKey
,CKA_CLASS
);
3618 sftk_DeleteAttributeType(privateKey
,CKA_KEY_TYPE
);
3619 sftk_DeleteAttributeType(privateKey
,CKA_VALUE
);
3620 sftk_DeleteAttributeType(publicKey
,CKA_CLASS
);
3621 sftk_DeleteAttributeType(publicKey
,CKA_KEY_TYPE
);
3622 sftk_DeleteAttributeType(publicKey
,CKA_VALUE
);
3624 /* Now Set up the parameters to generate the key (based on mechanism) */
3625 switch (pMechanism
->mechanism
) {
3626 case CKM_RSA_PKCS_KEY_PAIR_GEN
:
3627 /* format the keys */
3628 sftk_DeleteAttributeType(publicKey
,CKA_MODULUS
);
3629 sftk_DeleteAttributeType(privateKey
,CKA_NETSCAPE_DB
);
3630 sftk_DeleteAttributeType(privateKey
,CKA_MODULUS
);
3631 sftk_DeleteAttributeType(privateKey
,CKA_PRIVATE_EXPONENT
);
3632 sftk_DeleteAttributeType(privateKey
,CKA_PUBLIC_EXPONENT
);
3633 sftk_DeleteAttributeType(privateKey
,CKA_PRIME_1
);
3634 sftk_DeleteAttributeType(privateKey
,CKA_PRIME_2
);
3635 sftk_DeleteAttributeType(privateKey
,CKA_EXPONENT_1
);
3636 sftk_DeleteAttributeType(privateKey
,CKA_EXPONENT_2
);
3637 sftk_DeleteAttributeType(privateKey
,CKA_COEFFICIENT
);
3639 if (public_modulus_bits
== 0) {
3640 crv
= CKR_TEMPLATE_INCOMPLETE
;
3643 if (public_modulus_bits
< RSA_MIN_MODULUS_BITS
) {
3644 crv
= CKR_ATTRIBUTE_VALUE_INVALID
;
3647 if (public_modulus_bits
% 2 != 0) {
3648 crv
= CKR_ATTRIBUTE_VALUE_INVALID
;
3652 /* extract the exponent */
3653 crv
=sftk_Attribute2SSecItem(NULL
,&pubExp
,publicKey
,CKA_PUBLIC_EXPONENT
);
3654 if (crv
!= CKR_OK
) break;
3655 bitSize
= sftk_GetLengthInBits(pubExp
.data
, pubExp
.len
);
3657 crv
= CKR_ATTRIBUTE_VALUE_INVALID
;
3660 crv
= sftk_AddAttributeType(privateKey
,CKA_PUBLIC_EXPONENT
,
3661 sftk_item_expand(&pubExp
));
3662 if (crv
!= CKR_OK
) {
3663 PORT_Free(pubExp
.data
);
3667 rsaPriv
= RSA_NewKey(public_modulus_bits
, &pubExp
);
3668 PORT_Free(pubExp
.data
);
3669 if (rsaPriv
== NULL
) {
3670 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE
) {
3671 sftk_fatalError
= PR_TRUE
;
3673 crv
= CKR_DEVICE_ERROR
;
3676 /* now fill in the RSA dependent paramenters in the public key */
3677 crv
= sftk_AddAttributeType(publicKey
,CKA_MODULUS
,
3678 sftk_item_expand(&rsaPriv
->modulus
));
3679 if (crv
!= CKR_OK
) goto kpg_done
;
3680 /* now fill in the RSA dependent paramenters in the private key */
3681 crv
= sftk_AddAttributeType(privateKey
,CKA_NETSCAPE_DB
,
3682 sftk_item_expand(&rsaPriv
->modulus
));
3683 if (crv
!= CKR_OK
) goto kpg_done
;
3684 crv
= sftk_AddAttributeType(privateKey
,CKA_MODULUS
,
3685 sftk_item_expand(&rsaPriv
->modulus
));
3686 if (crv
!= CKR_OK
) goto kpg_done
;
3687 crv
= sftk_AddAttributeType(privateKey
,CKA_PRIVATE_EXPONENT
,
3688 sftk_item_expand(&rsaPriv
->privateExponent
));
3689 if (crv
!= CKR_OK
) goto kpg_done
;
3690 crv
= sftk_AddAttributeType(privateKey
,CKA_PRIME_1
,
3691 sftk_item_expand(&rsaPriv
->prime1
));
3692 if (crv
!= CKR_OK
) goto kpg_done
;
3693 crv
= sftk_AddAttributeType(privateKey
,CKA_PRIME_2
,
3694 sftk_item_expand(&rsaPriv
->prime2
));
3695 if (crv
!= CKR_OK
) goto kpg_done
;
3696 crv
= sftk_AddAttributeType(privateKey
,CKA_EXPONENT_1
,
3697 sftk_item_expand(&rsaPriv
->exponent1
));
3698 if (crv
!= CKR_OK
) goto kpg_done
;
3699 crv
= sftk_AddAttributeType(privateKey
,CKA_EXPONENT_2
,
3700 sftk_item_expand(&rsaPriv
->exponent2
));
3701 if (crv
!= CKR_OK
) goto kpg_done
;
3702 crv
= sftk_AddAttributeType(privateKey
,CKA_COEFFICIENT
,
3703 sftk_item_expand(&rsaPriv
->coefficient
));
3705 /* Should zeroize the contents first, since this func doesn't. */
3706 PORT_FreeArena(rsaPriv
->arena
, PR_TRUE
);
3708 case CKM_DSA_KEY_PAIR_GEN
:
3709 sftk_DeleteAttributeType(publicKey
,CKA_VALUE
);
3710 sftk_DeleteAttributeType(privateKey
,CKA_NETSCAPE_DB
);
3711 sftk_DeleteAttributeType(privateKey
,CKA_PRIME
);
3712 sftk_DeleteAttributeType(privateKey
,CKA_SUBPRIME
);
3713 sftk_DeleteAttributeType(privateKey
,CKA_BASE
);
3716 /* extract the necessary paramters and copy them to the private key */
3717 crv
=sftk_Attribute2SSecItem(NULL
,&pqgParam
.prime
,publicKey
,CKA_PRIME
);
3718 if (crv
!= CKR_OK
) break;
3719 crv
=sftk_Attribute2SSecItem(NULL
,&pqgParam
.subPrime
,publicKey
,
3721 if (crv
!= CKR_OK
) {
3722 PORT_Free(pqgParam
.prime
.data
);
3725 crv
=sftk_Attribute2SSecItem(NULL
,&pqgParam
.base
,publicKey
,CKA_BASE
);
3726 if (crv
!= CKR_OK
) {
3727 PORT_Free(pqgParam
.prime
.data
);
3728 PORT_Free(pqgParam
.subPrime
.data
);
3731 crv
= sftk_AddAttributeType(privateKey
,CKA_PRIME
,
3732 sftk_item_expand(&pqgParam
.prime
));
3733 if (crv
!= CKR_OK
) {
3734 PORT_Free(pqgParam
.prime
.data
);
3735 PORT_Free(pqgParam
.subPrime
.data
);
3736 PORT_Free(pqgParam
.base
.data
);
3739 crv
= sftk_AddAttributeType(privateKey
,CKA_SUBPRIME
,
3740 sftk_item_expand(&pqgParam
.subPrime
));
3741 if (crv
!= CKR_OK
) {
3742 PORT_Free(pqgParam
.prime
.data
);
3743 PORT_Free(pqgParam
.subPrime
.data
);
3744 PORT_Free(pqgParam
.base
.data
);
3747 crv
= sftk_AddAttributeType(privateKey
,CKA_BASE
,
3748 sftk_item_expand(&pqgParam
.base
));
3749 if (crv
!= CKR_OK
) {
3750 PORT_Free(pqgParam
.prime
.data
);
3751 PORT_Free(pqgParam
.subPrime
.data
);
3752 PORT_Free(pqgParam
.base
.data
);
3756 bitSize
= sftk_GetLengthInBits(pqgParam
.subPrime
.data
,
3757 pqgParam
.subPrime
.len
);
3758 if (bitSize
!= DSA_Q_BITS
) {
3759 crv
= CKR_TEMPLATE_INCOMPLETE
;
3760 PORT_Free(pqgParam
.prime
.data
);
3761 PORT_Free(pqgParam
.subPrime
.data
);
3762 PORT_Free(pqgParam
.base
.data
);
3765 bitSize
= sftk_GetLengthInBits(pqgParam
.prime
.data
,pqgParam
.prime
.len
);
3766 if ((bitSize
< DSA_MIN_P_BITS
) || (bitSize
> DSA_MAX_P_BITS
)) {
3767 crv
= CKR_TEMPLATE_INCOMPLETE
;
3768 PORT_Free(pqgParam
.prime
.data
);
3769 PORT_Free(pqgParam
.subPrime
.data
);
3770 PORT_Free(pqgParam
.base
.data
);
3773 bitSize
= sftk_GetLengthInBits(pqgParam
.base
.data
,pqgParam
.base
.len
);
3774 if ((bitSize
< 1) || (bitSize
> DSA_MAX_P_BITS
)) {
3775 crv
= CKR_TEMPLATE_INCOMPLETE
;
3776 PORT_Free(pqgParam
.prime
.data
);
3777 PORT_Free(pqgParam
.subPrime
.data
);
3778 PORT_Free(pqgParam
.base
.data
);
3782 /* Generate the key */
3783 rv
= DSA_NewKey(&pqgParam
, &dsaPriv
);
3785 PORT_Free(pqgParam
.prime
.data
);
3786 PORT_Free(pqgParam
.subPrime
.data
);
3787 PORT_Free(pqgParam
.base
.data
);
3789 if (rv
!= SECSuccess
) {
3790 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE
) {
3791 sftk_fatalError
= PR_TRUE
;
3793 crv
= CKR_DEVICE_ERROR
;
3797 /* store the generated key into the attributes */
3798 crv
= sftk_AddAttributeType(publicKey
,CKA_VALUE
,
3799 sftk_item_expand(&dsaPriv
->publicValue
));
3800 if (crv
!= CKR_OK
) goto dsagn_done
;
3802 /* now fill in the RSA dependent paramenters in the private key */
3803 crv
= sftk_AddAttributeType(privateKey
,CKA_NETSCAPE_DB
,
3804 sftk_item_expand(&dsaPriv
->publicValue
));
3805 if (crv
!= CKR_OK
) goto dsagn_done
;
3806 crv
= sftk_AddAttributeType(privateKey
,CKA_VALUE
,
3807 sftk_item_expand(&dsaPriv
->privateValue
));
3810 /* should zeroize, since this function doesn't. */
3811 PORT_FreeArena(dsaPriv
->params
.arena
, PR_TRUE
);
3814 case CKM_DH_PKCS_KEY_PAIR_GEN
:
3815 sftk_DeleteAttributeType(privateKey
,CKA_PRIME
);
3816 sftk_DeleteAttributeType(privateKey
,CKA_BASE
);
3817 sftk_DeleteAttributeType(privateKey
,CKA_VALUE
);
3818 sftk_DeleteAttributeType(privateKey
,CKA_NETSCAPE_DB
);
3821 /* extract the necessary parameters and copy them to private keys */
3822 crv
= sftk_Attribute2SSecItem(NULL
, &dhParam
.prime
, publicKey
,
3824 if (crv
!= CKR_OK
) break;
3825 crv
= sftk_Attribute2SSecItem(NULL
, &dhParam
.base
, publicKey
, CKA_BASE
);
3826 if (crv
!= CKR_OK
) {
3827 PORT_Free(dhParam
.prime
.data
);
3830 crv
= sftk_AddAttributeType(privateKey
, CKA_PRIME
,
3831 sftk_item_expand(&dhParam
.prime
));
3832 if (crv
!= CKR_OK
) {
3833 PORT_Free(dhParam
.prime
.data
);
3834 PORT_Free(dhParam
.base
.data
);
3837 crv
= sftk_AddAttributeType(privateKey
, CKA_BASE
,
3838 sftk_item_expand(&dhParam
.base
));
3839 if (crv
!= CKR_OK
) {
3840 PORT_Free(dhParam
.prime
.data
);
3841 PORT_Free(dhParam
.base
.data
);
3844 bitSize
= sftk_GetLengthInBits(dhParam
.prime
.data
,dhParam
.prime
.len
);
3845 if ((bitSize
< DH_MIN_P_BITS
) || (bitSize
> DH_MAX_P_BITS
)) {
3846 crv
= CKR_TEMPLATE_INCOMPLETE
;
3847 PORT_Free(dhParam
.prime
.data
);
3848 PORT_Free(dhParam
.base
.data
);
3851 bitSize
= sftk_GetLengthInBits(dhParam
.base
.data
,dhParam
.base
.len
);
3852 if ((bitSize
< 1) || (bitSize
> DH_MAX_P_BITS
)) {
3853 crv
= CKR_TEMPLATE_INCOMPLETE
;
3854 PORT_Free(dhParam
.prime
.data
);
3855 PORT_Free(dhParam
.base
.data
);
3859 rv
= DH_NewKey(&dhParam
, &dhPriv
);
3860 PORT_Free(dhParam
.prime
.data
);
3861 PORT_Free(dhParam
.base
.data
);
3862 if (rv
!= SECSuccess
) {
3863 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE
) {
3864 sftk_fatalError
= PR_TRUE
;
3866 crv
= CKR_DEVICE_ERROR
;
3870 crv
=sftk_AddAttributeType(publicKey
, CKA_VALUE
,
3871 sftk_item_expand(&dhPriv
->publicValue
));
3872 if (crv
!= CKR_OK
) goto dhgn_done
;
3874 crv
= sftk_AddAttributeType(privateKey
,CKA_NETSCAPE_DB
,
3875 sftk_item_expand(&dhPriv
->publicValue
));
3876 if (crv
!= CKR_OK
) goto dhgn_done
;
3878 crv
=sftk_AddAttributeType(privateKey
, CKA_VALUE
,
3879 sftk_item_expand(&dhPriv
->privateValue
));
3882 /* should zeroize, since this function doesn't. */
3883 PORT_FreeArena(dhPriv
->arena
, PR_TRUE
);
3886 #ifdef NSS_ENABLE_ECC
3887 case CKM_EC_KEY_PAIR_GEN
:
3888 sftk_DeleteAttributeType(privateKey
,CKA_EC_PARAMS
);
3889 sftk_DeleteAttributeType(privateKey
,CKA_VALUE
);
3890 sftk_DeleteAttributeType(privateKey
,CKA_NETSCAPE_DB
);
3893 /* extract the necessary parameters and copy them to private keys */
3894 crv
= sftk_Attribute2SSecItem(NULL
, &ecEncodedParams
, publicKey
,
3896 if (crv
!= CKR_OK
) break;
3898 crv
= sftk_AddAttributeType(privateKey
, CKA_EC_PARAMS
,
3899 sftk_item_expand(&ecEncodedParams
));
3900 if (crv
!= CKR_OK
) {
3901 PORT_Free(ecEncodedParams
.data
);
3905 /* Decode ec params before calling EC_NewKey */
3906 rv
= EC_DecodeParams(&ecEncodedParams
, &ecParams
);
3907 PORT_Free(ecEncodedParams
.data
);
3908 if (rv
!= SECSuccess
) {
3909 crv
= CKR_DEVICE_ERROR
;
3912 rv
= EC_NewKey(ecParams
, &ecPriv
);
3913 PORT_FreeArena(ecParams
->arena
, PR_TRUE
);
3914 if (rv
!= SECSuccess
) {
3915 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE
) {
3916 sftk_fatalError
= PR_TRUE
;
3918 crv
= CKR_DEVICE_ERROR
;
3922 crv
= sftk_AddAttributeType(publicKey
, CKA_EC_POINT
,
3923 sftk_item_expand(&ecPriv
->publicValue
));
3924 if (crv
!= CKR_OK
) goto ecgn_done
;
3926 crv
= sftk_AddAttributeType(privateKey
, CKA_VALUE
,
3927 sftk_item_expand(&ecPriv
->privateValue
));
3928 if (crv
!= CKR_OK
) goto ecgn_done
;
3930 crv
= sftk_AddAttributeType(privateKey
,CKA_NETSCAPE_DB
,
3931 sftk_item_expand(&ecPriv
->publicValue
));
3933 /* should zeroize, since this function doesn't. */
3934 PORT_FreeArena(ecPriv
->ecParams
.arena
, PR_TRUE
);
3936 #endif /* NSS_ENABLE_ECC */
3939 crv
= CKR_MECHANISM_INVALID
;
3942 if (crv
!= CKR_OK
) {
3943 sftk_FreeObject(privateKey
);
3944 sftk_FreeObject(publicKey
);
3949 /* Add the class, key_type The loop lets us check errors blow out
3950 * on errors and clean up at the bottom */
3951 session
= NULL
; /* make pedtantic happy... session cannot leave the*/
3952 /* loop below NULL unless an error is set... */
3954 crv
= sftk_AddAttributeType(privateKey
,CKA_CLASS
,&privClass
,
3955 sizeof(CK_OBJECT_CLASS
));
3956 if (crv
!= CKR_OK
) break;
3957 crv
= sftk_AddAttributeType(publicKey
,CKA_CLASS
,&pubClass
,
3958 sizeof(CK_OBJECT_CLASS
));
3959 if (crv
!= CKR_OK
) break;
3960 crv
= sftk_AddAttributeType(privateKey
,CKA_KEY_TYPE
,&key_type
,
3961 sizeof(CK_KEY_TYPE
));
3962 if (crv
!= CKR_OK
) break;
3963 crv
= sftk_AddAttributeType(publicKey
,CKA_KEY_TYPE
,&key_type
,
3964 sizeof(CK_KEY_TYPE
));
3965 if (crv
!= CKR_OK
) break;
3966 session
= sftk_SessionFromHandle(hSession
);
3967 if (session
== NULL
) crv
= CKR_SESSION_HANDLE_INVALID
;
3970 if (crv
!= CKR_OK
) {
3971 sftk_FreeObject(privateKey
);
3972 sftk_FreeObject(publicKey
);
3977 * handle the base object cleanup for the public Key
3979 crv
= sftk_handleObject(privateKey
,session
);
3980 if (crv
!= CKR_OK
) {
3981 sftk_FreeSession(session
);
3982 sftk_FreeObject(privateKey
);
3983 sftk_FreeObject(publicKey
);
3988 * handle the base object cleanup for the private Key
3989 * If we have any problems, we destroy the public Key we've
3990 * created and linked.
3992 crv
= sftk_handleObject(publicKey
,session
);
3993 sftk_FreeSession(session
);
3994 if (crv
!= CKR_OK
) {
3995 sftk_FreeObject(publicKey
);
3996 NSC_DestroyObject(hSession
,privateKey
->handle
);
3997 sftk_FreeObject(privateKey
);
4000 if (sftk_isTrue(privateKey
,CKA_SENSITIVE
)) {
4001 sftk_forceAttribute(privateKey
,CKA_ALWAYS_SENSITIVE
,
4002 &cktrue
,sizeof(CK_BBOOL
));
4004 if (sftk_isTrue(publicKey
,CKA_SENSITIVE
)) {
4005 sftk_forceAttribute(publicKey
,CKA_ALWAYS_SENSITIVE
,
4006 &cktrue
,sizeof(CK_BBOOL
));
4008 if (!sftk_isTrue(privateKey
,CKA_EXTRACTABLE
)) {
4009 sftk_forceAttribute(privateKey
,CKA_NEVER_EXTRACTABLE
,
4010 &cktrue
,sizeof(CK_BBOOL
));
4012 if (!sftk_isTrue(publicKey
,CKA_EXTRACTABLE
)) {
4013 sftk_forceAttribute(publicKey
,CKA_NEVER_EXTRACTABLE
,
4014 &cktrue
,sizeof(CK_BBOOL
));
4017 /* Perform FIPS 140-2 pairwise consistency check. */
4018 crv
= sftk_PairwiseConsistencyCheck(hSession
,
4019 publicKey
, privateKey
, key_type
);
4020 if (crv
!= CKR_OK
) {
4021 NSC_DestroyObject(hSession
,publicKey
->handle
);
4022 sftk_FreeObject(publicKey
);
4023 NSC_DestroyObject(hSession
,privateKey
->handle
);
4024 sftk_FreeObject(privateKey
);
4025 if (sftk_audit_enabled
) {
4027 PR_snprintf(msg
,sizeof msg
,
4028 "C_GenerateKeyPair(hSession=0x%08lX, "
4029 "pMechanism->mechanism=0x%08lX)=0x%08lX "
4030 "self-test: pair-wise consistency test failed",
4031 (PRUint32
)hSession
,(PRUint32
)pMechanism
->mechanism
,
4033 sftk_LogAuditMessage(NSS_AUDIT_ERROR
, msg
);
4038 *phPrivateKey
= privateKey
->handle
;
4039 *phPublicKey
= publicKey
->handle
;
4040 sftk_FreeObject(publicKey
);
4041 sftk_FreeObject(privateKey
);
4046 static SECItem
*sftk_PackagePrivateKey(SFTKObject
*key
, CK_RV
*crvp
)
4048 NSSLOWKEYPrivateKey
*lk
= NULL
;
4049 NSSLOWKEYPrivateKeyInfo
*pki
= NULL
;
4050 SFTKAttribute
*attribute
= NULL
;
4051 PLArenaPool
*arena
= NULL
;
4052 SECOidTag algorithm
= SEC_OID_UNKNOWN
;
4053 void *dummy
, *param
= NULL
;
4054 SECStatus rv
= SECSuccess
;
4055 SECItem
*encodedKey
= NULL
;
4056 #ifdef NSS_ENABLE_ECC
4062 *crvp
= CKR_KEY_HANDLE_INVALID
; /* really can't happen */
4066 attribute
= sftk_FindAttribute(key
, CKA_KEY_TYPE
);
4068 *crvp
= CKR_KEY_TYPE_INCONSISTENT
;
4072 lk
= sftk_GetPrivKey(key
, *(CK_KEY_TYPE
*)attribute
->attrib
.pValue
, crvp
);
4073 sftk_FreeAttribute(attribute
);
4078 arena
= PORT_NewArena(2048); /* XXX different size? */
4080 *crvp
= CKR_HOST_MEMORY
;
4085 pki
= (NSSLOWKEYPrivateKeyInfo
*)PORT_ArenaZAlloc(arena
,
4086 sizeof(NSSLOWKEYPrivateKeyInfo
));
4088 *crvp
= CKR_HOST_MEMORY
;
4095 switch(lk
->keyType
) {
4096 case NSSLOWKEYRSAKey
:
4097 prepare_low_rsa_priv_key_for_asn1(lk
);
4098 dummy
= SEC_ASN1EncodeItem(arena
, &pki
->privateKey
, lk
,
4099 nsslowkey_RSAPrivateKeyTemplate
);
4100 algorithm
= SEC_OID_PKCS1_RSA_ENCRYPTION
;
4102 case NSSLOWKEYDSAKey
:
4103 prepare_low_dsa_priv_key_export_for_asn1(lk
);
4104 dummy
= SEC_ASN1EncodeItem(arena
, &pki
->privateKey
, lk
,
4105 nsslowkey_DSAPrivateKeyExportTemplate
);
4106 prepare_low_pqg_params_for_asn1(&lk
->u
.dsa
.params
);
4107 param
= SEC_ASN1EncodeItem(NULL
, NULL
, &(lk
->u
.dsa
.params
),
4108 nsslowkey_PQGParamsTemplate
);
4109 algorithm
= SEC_OID_ANSIX9_DSA_SIGNATURE
;
4111 #ifdef NSS_ENABLE_ECC
4112 case NSSLOWKEYECKey
:
4113 prepare_low_ec_priv_key_for_asn1(lk
);
4114 /* Public value is encoded as a bit string so adjust length
4115 * to be in bits before ASN encoding and readjust
4116 * immediately after.
4118 * Since the SECG specification recommends not including the
4119 * parameters as part of ECPrivateKey, we zero out the curveOID
4120 * length before encoding and restore it later.
4122 lk
->u
.ec
.publicValue
.len
<<= 3;
4123 savelen
= lk
->u
.ec
.ecParams
.curveOID
.len
;
4124 lk
->u
.ec
.ecParams
.curveOID
.len
= 0;
4125 dummy
= SEC_ASN1EncodeItem(arena
, &pki
->privateKey
, lk
,
4126 nsslowkey_ECPrivateKeyTemplate
);
4127 lk
->u
.ec
.ecParams
.curveOID
.len
= savelen
;
4128 lk
->u
.ec
.publicValue
.len
>>= 3;
4130 fordebug
= &pki
->privateKey
;
4131 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk
->keyType
,
4134 param
= SECITEM_DupItem(&lk
->u
.ec
.ecParams
.DEREncoding
);
4136 algorithm
= SEC_OID_ANSIX962_EC_PUBLIC_KEY
;
4138 #endif /* NSS_ENABLE_ECC */
4139 case NSSLOWKEYDHKey
:
4145 if(!dummy
|| ((lk
->keyType
== NSSLOWKEYDSAKey
) && !param
)) {
4146 *crvp
= CKR_DEVICE_ERROR
; /* should map NSS SECError */
4151 rv
= SECOID_SetAlgorithmID(arena
, &pki
->algorithm
, algorithm
,
4153 if(rv
!= SECSuccess
) {
4154 *crvp
= CKR_DEVICE_ERROR
; /* should map NSS SECError */
4159 dummy
= SEC_ASN1EncodeInteger(arena
, &pki
->version
,
4160 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION
);
4162 *crvp
= CKR_DEVICE_ERROR
; /* should map NSS SECError */
4167 encodedKey
= SEC_ASN1EncodeItem(NULL
, NULL
, pki
,
4168 nsslowkey_PrivateKeyInfoTemplate
);
4169 *crvp
= encodedKey
? CKR_OK
: CKR_DEVICE_ERROR
;
4171 #ifdef NSS_ENABLE_ECC
4172 fordebug
= encodedKey
;
4173 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk
->keyType
,
4178 PORT_FreeArena(arena
, PR_TRUE
);
4181 if(lk
&& (lk
!= key
->objectInfo
)) {
4182 nsslowkey_DestroyPrivateKey(lk
);
4186 SECITEM_ZfreeItem((SECItem
*)param
, PR_TRUE
);
4189 if(rv
!= SECSuccess
) {
4196 /* it doesn't matter yet, since we colapse error conditions in the
4197 * level above, but we really should map those few key error differences */
4199 sftk_mapWrap(CK_RV crv
)
4202 case CKR_ENCRYPTED_DATA_INVALID
: crv
= CKR_WRAPPED_KEY_INVALID
; break;
4207 /* NSC_WrapKey wraps (i.e., encrypts) a key. */
4208 CK_RV
NSC_WrapKey(CK_SESSION_HANDLE hSession
,
4209 CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hWrappingKey
,
4210 CK_OBJECT_HANDLE hKey
, CK_BYTE_PTR pWrappedKey
,
4211 CK_ULONG_PTR pulWrappedKeyLen
)
4213 SFTKSession
*session
;
4214 SFTKAttribute
*attribute
;
4220 session
= sftk_SessionFromHandle(hSession
);
4221 if (session
== NULL
) {
4222 return CKR_SESSION_HANDLE_INVALID
;
4225 key
= sftk_ObjectFromHandle(hKey
,session
);
4226 sftk_FreeSession(session
);
4228 return CKR_KEY_HANDLE_INVALID
;
4231 switch(key
->objclass
) {
4232 case CKO_SECRET_KEY
:
4234 SFTKSessionContext
*context
= NULL
;
4237 attribute
= sftk_FindAttribute(key
,CKA_VALUE
);
4239 if (attribute
== NULL
) {
4240 crv
= CKR_KEY_TYPE_INCONSISTENT
;
4243 crv
= sftk_CryptInit(hSession
, pMechanism
, hWrappingKey
,
4244 CKA_WRAP
, SFTK_ENCRYPT
, PR_TRUE
);
4245 if (crv
!= CKR_OK
) {
4246 sftk_FreeAttribute(attribute
);
4250 pText
.type
= siBuffer
;
4251 pText
.data
= (unsigned char *)attribute
->attrib
.pValue
;
4252 pText
.len
= attribute
->attrib
.ulValueLen
;
4254 /* Find out if this is a block cipher. */
4255 crv
= sftk_GetContext(hSession
,&context
,SFTK_ENCRYPT
,PR_FALSE
,NULL
);
4256 if (crv
!= CKR_OK
|| !context
)
4258 if (context
->blockSize
> 1) {
4259 unsigned int remainder
= pText
.len
% context
->blockSize
;
4260 if (!context
->doPad
&& remainder
) {
4261 /* When wrapping secret keys with unpadded block ciphers,
4262 ** the keys are zero padded, if necessary, to fill out
4265 pText
.len
+= context
->blockSize
- remainder
;
4266 pText
.data
= PORT_ZAlloc(pText
.len
);
4268 memcpy(pText
.data
, attribute
->attrib
.pValue
,
4269 attribute
->attrib
.ulValueLen
);
4271 crv
= CKR_HOST_MEMORY
;
4277 crv
= NSC_Encrypt(hSession
, (CK_BYTE_PTR
)pText
.data
,
4278 pText
.len
, pWrappedKey
, pulWrappedKeyLen
);
4279 /* always force a finalize, both on errors and when
4280 * we are just getting the size */
4281 if (crv
!= CKR_OK
|| pWrappedKey
== NULL
) {
4283 lcrv
= sftk_GetContext(hSession
,&context
,
4284 SFTK_ENCRYPT
,PR_FALSE
,NULL
);
4285 sftk_SetContextByType(session
, SFTK_ENCRYPT
, NULL
);
4286 if (lcrv
== CKR_OK
&& context
) {
4287 sftk_FreeContext(context
);
4291 if (pText
.data
!= (unsigned char *)attribute
->attrib
.pValue
)
4292 PORT_ZFree(pText
.data
, pText
.len
);
4293 sftk_FreeAttribute(attribute
);
4297 case CKO_PRIVATE_KEY
:
4299 SECItem
*bpki
= sftk_PackagePrivateKey(key
, &crv
);
4300 SFTKSessionContext
*context
= NULL
;
4306 crv
= sftk_CryptInit(hSession
, pMechanism
, hWrappingKey
,
4307 CKA_WRAP
, SFTK_ENCRYPT
, PR_TRUE
);
4309 SECITEM_ZfreeItem(bpki
, PR_TRUE
);
4310 crv
= CKR_KEY_TYPE_INCONSISTENT
;
4314 crv
= NSC_Encrypt(hSession
, bpki
->data
, bpki
->len
,
4315 pWrappedKey
, pulWrappedKeyLen
);
4316 /* always force a finalize */
4317 if (crv
!= CKR_OK
|| pWrappedKey
== NULL
) {
4319 lcrv
= sftk_GetContext(hSession
,&context
,
4320 SFTK_ENCRYPT
,PR_FALSE
,NULL
);
4321 sftk_SetContextByType(session
, SFTK_ENCRYPT
, NULL
);
4322 if (lcrv
== CKR_OK
&& context
) {
4323 sftk_FreeContext(context
);
4326 SECITEM_ZfreeItem(bpki
, PR_TRUE
);
4331 crv
= CKR_KEY_TYPE_INCONSISTENT
;
4334 sftk_FreeObject(key
);
4336 return sftk_mapWrap(crv
);
4340 * import a pprivate key info into the desired slot
4343 sftk_unwrapPrivateKey(SFTKObject
*key
, SECItem
*bpki
)
4345 CK_BBOOL cktrue
= CK_TRUE
;
4346 CK_KEY_TYPE keyType
= CKK_RSA
;
4347 SECStatus rv
= SECFailure
;
4348 const SEC_ASN1Template
*keyTemplate
, *paramTemplate
;
4349 void *paramDest
= NULL
;
4351 NSSLOWKEYPrivateKey
*lpk
= NULL
;
4352 NSSLOWKEYPrivateKeyInfo
*pki
= NULL
;
4353 CK_RV crv
= CKR_KEY_TYPE_INCONSISTENT
;
4355 arena
= PORT_NewArena(2048);
4360 pki
= (NSSLOWKEYPrivateKeyInfo
*)PORT_ArenaZAlloc(arena
,
4361 sizeof(NSSLOWKEYPrivateKeyInfo
));
4363 PORT_FreeArena(arena
, PR_FALSE
);
4367 if(SEC_ASN1DecodeItem(arena
, pki
, nsslowkey_PrivateKeyInfoTemplate
, bpki
)
4369 PORT_FreeArena(arena
, PR_TRUE
);
4373 lpk
= (NSSLOWKEYPrivateKey
*)PORT_ArenaZAlloc(arena
,
4374 sizeof(NSSLOWKEYPrivateKey
));
4380 switch(SECOID_GetAlgorithmTag(&pki
->algorithm
)) {
4381 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
4382 keyTemplate
= nsslowkey_RSAPrivateKeyTemplate
;
4383 paramTemplate
= NULL
;
4385 lpk
->keyType
= NSSLOWKEYRSAKey
;
4386 prepare_low_rsa_priv_key_for_asn1(lpk
);
4388 case SEC_OID_ANSIX9_DSA_SIGNATURE
:
4389 keyTemplate
= nsslowkey_DSAPrivateKeyExportTemplate
;
4390 paramTemplate
= nsslowkey_PQGParamsTemplate
;
4391 paramDest
= &(lpk
->u
.dsa
.params
);
4392 lpk
->keyType
= NSSLOWKEYDSAKey
;
4393 prepare_low_dsa_priv_key_export_for_asn1(lpk
);
4394 prepare_low_pqg_params_for_asn1(&lpk
->u
.dsa
.params
);
4396 /* case NSSLOWKEYDHKey: */
4397 #ifdef NSS_ENABLE_ECC
4398 case SEC_OID_ANSIX962_EC_PUBLIC_KEY
:
4399 keyTemplate
= nsslowkey_ECPrivateKeyTemplate
;
4400 paramTemplate
= NULL
;
4401 paramDest
= &(lpk
->u
.ec
.ecParams
.DEREncoding
);
4402 lpk
->keyType
= NSSLOWKEYECKey
;
4403 prepare_low_ec_priv_key_for_asn1(lpk
);
4404 prepare_low_ecparams_for_asn1(&lpk
->u
.ec
.ecParams
);
4406 #endif /* NSS_ENABLE_ECC */
4409 paramTemplate
= NULL
;
4418 /* decode the private key and any algorithm parameters */
4419 rv
= SEC_QuickDERDecodeItem(arena
, lpk
, keyTemplate
, &pki
->privateKey
);
4421 #ifdef NSS_ENABLE_ECC
4422 if (lpk
->keyType
== NSSLOWKEYECKey
) {
4423 /* convert length in bits to length in bytes */
4424 lpk
->u
.ec
.publicValue
.len
>>= 3;
4425 rv
= SECITEM_CopyItem(arena
,
4426 &(lpk
->u
.ec
.ecParams
.DEREncoding
),
4427 &(pki
->algorithm
.parameters
));
4428 if(rv
!= SECSuccess
) {
4432 #endif /* NSS_ENABLE_ECC */
4434 if(rv
!= SECSuccess
) {
4437 if(paramDest
&& paramTemplate
) {
4438 rv
= SEC_QuickDERDecodeItem(arena
, paramDest
, paramTemplate
,
4439 &(pki
->algorithm
.parameters
));
4440 if(rv
!= SECSuccess
) {
4447 switch (lpk
->keyType
) {
4448 case NSSLOWKEYRSAKey
:
4450 if(sftk_hasAttribute(key
, CKA_NETSCAPE_DB
)) {
4451 sftk_DeleteAttributeType(key
, CKA_NETSCAPE_DB
);
4453 crv
= sftk_AddAttributeType(key
, CKA_KEY_TYPE
, &keyType
,
4455 if(crv
!= CKR_OK
) break;
4456 crv
= sftk_AddAttributeType(key
, CKA_UNWRAP
, &cktrue
,
4458 if(crv
!= CKR_OK
) break;
4459 crv
= sftk_AddAttributeType(key
, CKA_DECRYPT
, &cktrue
,
4461 if(crv
!= CKR_OK
) break;
4462 crv
= sftk_AddAttributeType(key
, CKA_SIGN
, &cktrue
,
4464 if(crv
!= CKR_OK
) break;
4465 crv
= sftk_AddAttributeType(key
, CKA_SIGN_RECOVER
, &cktrue
,
4467 if(crv
!= CKR_OK
) break;
4468 crv
= sftk_AddAttributeType(key
, CKA_MODULUS
,
4469 sftk_item_expand(&lpk
->u
.rsa
.modulus
));
4470 if(crv
!= CKR_OK
) break;
4471 crv
= sftk_AddAttributeType(key
, CKA_PUBLIC_EXPONENT
,
4472 sftk_item_expand(&lpk
->u
.rsa
.publicExponent
));
4473 if(crv
!= CKR_OK
) break;
4474 crv
= sftk_AddAttributeType(key
, CKA_PRIVATE_EXPONENT
,
4475 sftk_item_expand(&lpk
->u
.rsa
.privateExponent
));
4476 if(crv
!= CKR_OK
) break;
4477 crv
= sftk_AddAttributeType(key
, CKA_PRIME_1
,
4478 sftk_item_expand(&lpk
->u
.rsa
.prime1
));
4479 if(crv
!= CKR_OK
) break;
4480 crv
= sftk_AddAttributeType(key
, CKA_PRIME_2
,
4481 sftk_item_expand(&lpk
->u
.rsa
.prime2
));
4482 if(crv
!= CKR_OK
) break;
4483 crv
= sftk_AddAttributeType(key
, CKA_EXPONENT_1
,
4484 sftk_item_expand(&lpk
->u
.rsa
.exponent1
));
4485 if(crv
!= CKR_OK
) break;
4486 crv
= sftk_AddAttributeType(key
, CKA_EXPONENT_2
,
4487 sftk_item_expand(&lpk
->u
.rsa
.exponent2
));
4488 if(crv
!= CKR_OK
) break;
4489 crv
= sftk_AddAttributeType(key
, CKA_COEFFICIENT
,
4490 sftk_item_expand(&lpk
->u
.rsa
.coefficient
));
4492 case NSSLOWKEYDSAKey
:
4494 crv
= (sftk_hasAttribute(key
, CKA_NETSCAPE_DB
)) ? CKR_OK
:
4495 CKR_KEY_TYPE_INCONSISTENT
;
4496 if(crv
!= CKR_OK
) break;
4497 crv
= sftk_AddAttributeType(key
, CKA_KEY_TYPE
, &keyType
,
4499 if(crv
!= CKR_OK
) break;
4500 crv
= sftk_AddAttributeType(key
, CKA_SIGN
, &cktrue
,
4502 if(crv
!= CKR_OK
) break;
4503 crv
= sftk_AddAttributeType(key
, CKA_SIGN_RECOVER
, &cktrue
,
4505 if(crv
!= CKR_OK
) break;
4506 crv
= sftk_AddAttributeType(key
, CKA_PRIME
,
4507 sftk_item_expand(&lpk
->u
.dsa
.params
.prime
));
4508 if(crv
!= CKR_OK
) break;
4509 crv
= sftk_AddAttributeType(key
, CKA_SUBPRIME
,
4510 sftk_item_expand(&lpk
->u
.dsa
.params
.subPrime
));
4511 if(crv
!= CKR_OK
) break;
4512 crv
= sftk_AddAttributeType(key
, CKA_BASE
,
4513 sftk_item_expand(&lpk
->u
.dsa
.params
.base
));
4514 if(crv
!= CKR_OK
) break;
4515 crv
= sftk_AddAttributeType(key
, CKA_VALUE
,
4516 sftk_item_expand(&lpk
->u
.dsa
.privateValue
));
4517 if(crv
!= CKR_OK
) break;
4520 case NSSLOWKEYDHKey
:
4521 template = dhTemplate
;
4522 templateCount
= sizeof(dhTemplate
)/sizeof(CK_ATTRIBUTE
);
4526 /* what about fortezza??? */
4527 #ifdef NSS_ENABLE_ECC
4528 case NSSLOWKEYECKey
:
4530 crv
= (sftk_hasAttribute(key
, CKA_NETSCAPE_DB
)) ? CKR_OK
:
4531 CKR_KEY_TYPE_INCONSISTENT
;
4532 if(crv
!= CKR_OK
) break;
4533 crv
= sftk_AddAttributeType(key
, CKA_KEY_TYPE
, &keyType
,
4535 if(crv
!= CKR_OK
) break;
4536 crv
= sftk_AddAttributeType(key
, CKA_SIGN
, &cktrue
,
4538 if(crv
!= CKR_OK
) break;
4539 crv
= sftk_AddAttributeType(key
, CKA_SIGN_RECOVER
, &cktrue
,
4541 if(crv
!= CKR_OK
) break;
4542 crv
= sftk_AddAttributeType(key
, CKA_DERIVE
, &cktrue
,
4544 if(crv
!= CKR_OK
) break;
4545 crv
= sftk_AddAttributeType(key
, CKA_EC_PARAMS
,
4546 sftk_item_expand(&lpk
->u
.ec
.ecParams
.DEREncoding
));
4547 if(crv
!= CKR_OK
) break;
4548 crv
= sftk_AddAttributeType(key
, CKA_VALUE
,
4549 sftk_item_expand(&lpk
->u
.ec
.privateValue
));
4550 if(crv
!= CKR_OK
) break;
4551 /* XXX Do we need to decode the EC Params here ?? */
4553 #endif /* NSS_ENABLE_ECC */
4555 crv
= CKR_KEY_TYPE_INCONSISTENT
;
4561 nsslowkey_DestroyPrivateKey(lpk
);
4572 /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
4573 CK_RV
NSC_UnwrapKey(CK_SESSION_HANDLE hSession
,
4574 CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hUnwrappingKey
,
4575 CK_BYTE_PTR pWrappedKey
, CK_ULONG ulWrappedKeyLen
,
4576 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulAttributeCount
,
4577 CK_OBJECT_HANDLE_PTR phKey
)
4579 SFTKObject
*key
= NULL
;
4580 SFTKSession
*session
;
4581 CK_ULONG key_length
= 0;
4582 unsigned char * buf
= NULL
;
4585 CK_ULONG bsize
= ulWrappedKeyLen
;
4586 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
4588 CK_OBJECT_CLASS target_type
= CKO_SECRET_KEY
;
4593 return CKR_SESSION_HANDLE_INVALID
;
4596 * now lets create an object to hang the attributes off of
4598 key
= sftk_NewObject(slot
); /* fill in the handle later */
4600 return CKR_HOST_MEMORY
;
4604 * load the template values into the object
4606 for (i
=0; i
< (int) ulAttributeCount
; i
++) {
4607 if (pTemplate
[i
].type
== CKA_VALUE_LEN
) {
4608 key_length
= *(CK_ULONG
*)pTemplate
[i
].pValue
;
4611 if (pTemplate
[i
].type
== CKA_CLASS
) {
4612 target_type
= *(CK_OBJECT_CLASS
*)pTemplate
[i
].pValue
;
4614 crv
= sftk_AddAttributeType(key
,sftk_attr_expand(&pTemplate
[i
]));
4615 if (crv
!= CKR_OK
) break;
4617 if (crv
!= CKR_OK
) {
4618 sftk_FreeObject(key
);
4622 crv
= sftk_CryptInit(hSession
,pMechanism
,hUnwrappingKey
,CKA_UNWRAP
,
4623 SFTK_DECRYPT
, PR_FALSE
);
4624 if (crv
!= CKR_OK
) {
4625 sftk_FreeObject(key
);
4626 return sftk_mapWrap(crv
);
4629 /* allocate the buffer to decrypt into
4630 * this assumes the unwrapped key is never larger than the
4631 * wrapped key. For all the mechanisms we support this is true */
4632 buf
= (unsigned char *)PORT_Alloc( ulWrappedKeyLen
);
4633 bsize
= ulWrappedKeyLen
;
4635 crv
= NSC_Decrypt(hSession
, pWrappedKey
, ulWrappedKeyLen
, buf
, &bsize
);
4636 if (crv
!= CKR_OK
) {
4637 sftk_FreeObject(key
);
4639 return sftk_mapWrap(crv
);
4642 switch(target_type
) {
4643 case CKO_SECRET_KEY
:
4644 if (!sftk_hasAttribute(key
,CKA_KEY_TYPE
)) {
4645 crv
= CKR_TEMPLATE_INCOMPLETE
;
4649 if (key_length
== 0 || key_length
> bsize
) {
4652 if (key_length
> MAX_KEY_LEN
) {
4653 crv
= CKR_TEMPLATE_INCONSISTENT
;
4658 crv
= sftk_AddAttributeType(key
,CKA_VALUE
,buf
,key_length
);
4660 case CKO_PRIVATE_KEY
:
4661 bpki
.data
= (unsigned char *)buf
;
4664 if(sftk_unwrapPrivateKey(key
, &bpki
) != SECSuccess
) {
4665 crv
= CKR_TEMPLATE_INCOMPLETE
;
4669 crv
= CKR_TEMPLATE_INCONSISTENT
;
4673 PORT_ZFree(buf
, bsize
);
4674 if (crv
!= CKR_OK
) { sftk_FreeObject(key
); return crv
; }
4676 /* get the session */
4677 session
= sftk_SessionFromHandle(hSession
);
4678 if (session
== NULL
) {
4679 sftk_FreeObject(key
);
4680 return CKR_SESSION_HANDLE_INVALID
;
4684 * handle the base object stuff
4686 crv
= sftk_handleObject(key
,session
);
4687 *phKey
= key
->handle
;
4688 sftk_FreeSession(session
);
4689 sftk_FreeObject(key
);
4696 * The SSL key gen mechanism create's lots of keys. This function handles the
4697 * details of each of these key creation.
4700 sftk_buildSSLKey(CK_SESSION_HANDLE hSession
, SFTKObject
*baseKey
,
4701 PRBool isMacKey
, unsigned char *keyBlock
, unsigned int keySize
,
4702 CK_OBJECT_HANDLE
*keyHandle
)
4705 SFTKSession
*session
;
4706 CK_KEY_TYPE keyType
= CKK_GENERIC_SECRET
;
4707 CK_BBOOL cktrue
= CK_TRUE
;
4708 CK_BBOOL ckfalse
= CK_FALSE
;
4709 CK_RV crv
= CKR_HOST_MEMORY
;
4712 * now lets create an object to hang the attributes off of
4714 *keyHandle
= CK_INVALID_HANDLE
;
4715 key
= sftk_NewObject(baseKey
->slot
);
4716 if (key
== NULL
) return CKR_HOST_MEMORY
;
4717 sftk_narrowToSessionObject(key
)->wasDerived
= PR_TRUE
;
4719 crv
= sftk_CopyObject(key
,baseKey
);
4720 if (crv
!= CKR_OK
) goto loser
;
4722 crv
= sftk_forceAttribute(key
,CKA_KEY_TYPE
,&keyType
,sizeof(keyType
));
4723 if (crv
!= CKR_OK
) goto loser
;
4724 crv
= sftk_forceAttribute(key
,CKA_DERIVE
,&cktrue
,sizeof(CK_BBOOL
));
4725 if (crv
!= CKR_OK
) goto loser
;
4726 crv
= sftk_forceAttribute(key
,CKA_ENCRYPT
,&ckfalse
,sizeof(CK_BBOOL
));
4727 if (crv
!= CKR_OK
) goto loser
;
4728 crv
= sftk_forceAttribute(key
,CKA_DECRYPT
,&ckfalse
,sizeof(CK_BBOOL
));
4729 if (crv
!= CKR_OK
) goto loser
;
4730 crv
= sftk_forceAttribute(key
,CKA_SIGN
,&cktrue
,sizeof(CK_BBOOL
));
4731 if (crv
!= CKR_OK
) goto loser
;
4732 crv
= sftk_forceAttribute(key
,CKA_VERIFY
,&cktrue
,sizeof(CK_BBOOL
));
4733 if (crv
!= CKR_OK
) goto loser
;
4734 crv
= sftk_forceAttribute(key
,CKA_WRAP
,&ckfalse
,sizeof(CK_BBOOL
));
4735 if (crv
!= CKR_OK
) goto loser
;
4736 crv
= sftk_forceAttribute(key
,CKA_UNWRAP
,&ckfalse
,sizeof(CK_BBOOL
));
4737 if (crv
!= CKR_OK
) goto loser
;
4739 crv
= sftk_forceAttribute(key
,CKA_VALUE
,keyBlock
,keySize
);
4740 if (crv
!= CKR_OK
) goto loser
;
4742 /* get the session */
4743 crv
= CKR_HOST_MEMORY
;
4744 session
= sftk_SessionFromHandle(hSession
);
4745 if (session
== NULL
) { goto loser
; }
4747 crv
= sftk_handleObject(key
,session
);
4748 sftk_FreeSession(session
);
4749 *keyHandle
= key
->handle
;
4751 if (key
) sftk_FreeObject(key
);
4756 * if there is an error, we need to free the keys we already created in SSL
4757 * This is the routine that will do it..
4760 sftk_freeSSLKeys(CK_SESSION_HANDLE session
,
4761 CK_SSL3_KEY_MAT_OUT
*returnedMaterial
)
4763 if (returnedMaterial
->hClientMacSecret
!= CK_INVALID_HANDLE
) {
4764 NSC_DestroyObject(session
,returnedMaterial
->hClientMacSecret
);
4766 if (returnedMaterial
->hServerMacSecret
!= CK_INVALID_HANDLE
) {
4767 NSC_DestroyObject(session
, returnedMaterial
->hServerMacSecret
);
4769 if (returnedMaterial
->hClientKey
!= CK_INVALID_HANDLE
) {
4770 NSC_DestroyObject(session
, returnedMaterial
->hClientKey
);
4772 if (returnedMaterial
->hServerKey
!= CK_INVALID_HANDLE
) {
4773 NSC_DestroyObject(session
, returnedMaterial
->hServerKey
);
4778 * when deriving from sensitive and extractable keys, we need to preserve some
4779 * of the semantics in the derived key. This helper routine maintains these
4783 sftk_DeriveSensitiveCheck(SFTKObject
*baseKey
,SFTKObject
*destKey
)
4785 PRBool hasSensitive
;
4786 PRBool sensitive
= PR_FALSE
;
4787 PRBool hasExtractable
;
4788 PRBool extractable
= PR_TRUE
;
4792 hasSensitive
= PR_FALSE
;
4793 att
= sftk_FindAttribute(destKey
,CKA_SENSITIVE
);
4795 hasSensitive
= PR_TRUE
;
4796 sensitive
= (PRBool
) *(CK_BBOOL
*)att
->attrib
.pValue
;
4797 sftk_FreeAttribute(att
);
4800 hasExtractable
= PR_FALSE
;
4801 att
= sftk_FindAttribute(destKey
,CKA_EXTRACTABLE
);
4803 hasExtractable
= PR_TRUE
;
4804 extractable
= (PRBool
) *(CK_BBOOL
*)att
->attrib
.pValue
;
4805 sftk_FreeAttribute(att
);
4809 /* don't make a key more accessible */
4810 if (sftk_isTrue(baseKey
,CKA_SENSITIVE
) && hasSensitive
&&
4811 (sensitive
== PR_FALSE
)) {
4812 return CKR_KEY_FUNCTION_NOT_PERMITTED
;
4814 if (!sftk_isTrue(baseKey
,CKA_EXTRACTABLE
) && hasExtractable
&&
4815 (extractable
== PR_TRUE
)) {
4816 return CKR_KEY_FUNCTION_NOT_PERMITTED
;
4819 /* inherit parent's sensitivity */
4820 if (!hasSensitive
) {
4821 att
= sftk_FindAttribute(baseKey
,CKA_SENSITIVE
);
4822 if (att
== NULL
) return CKR_KEY_TYPE_INCONSISTENT
;
4823 crv
= sftk_defaultAttribute(destKey
,sftk_attr_expand(&att
->attrib
));
4824 sftk_FreeAttribute(att
);
4825 if (crv
!= CKR_OK
) return crv
;
4827 if (!hasExtractable
) {
4828 att
= sftk_FindAttribute(baseKey
,CKA_EXTRACTABLE
);
4829 if (att
== NULL
) return CKR_KEY_TYPE_INCONSISTENT
;
4830 crv
= sftk_defaultAttribute(destKey
,sftk_attr_expand(&att
->attrib
));
4831 sftk_FreeAttribute(att
);
4832 if (crv
!= CKR_OK
) return crv
;
4835 /* we should inherit the parent's always extractable/ never sensitive info,
4836 * but handleObject always forces this attributes, so we would need to do
4837 * something special. */
4842 * make known fixed PKCS #11 key types to their sizes in bytes
4845 sftk_MapKeySize(CK_KEY_TYPE keyType
)
4856 /* IDEA and CAST need to be added */
4864 * SSL Key generation given pre master secret
4866 #define NUM_MIXERS 9
4867 static const char * const mixers
[NUM_MIXERS
] = {
4877 #define SSL3_PMS_LENGTH 48
4878 #define SSL3_MASTER_SECRET_LENGTH 48
4879 #define SSL3_RANDOM_LENGTH 32
4882 /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
4883 CK_RV
NSC_DeriveKey( CK_SESSION_HANDLE hSession
,
4884 CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hBaseKey
,
4885 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulAttributeCount
,
4886 CK_OBJECT_HANDLE_PTR phKey
)
4888 SFTKSession
* session
;
4889 SFTKSlot
* slot
= sftk_SlotFromSessionHandle(hSession
);
4891 SFTKObject
* sourceKey
;
4892 SFTKAttribute
* att
;
4893 SFTKAttribute
* att2
;
4894 unsigned char * buf
;
4899 CK_ULONG tmpKeySize
;
4901 CK_ULONG keySize
= 0;
4903 CK_BBOOL cktrue
= CK_TRUE
;
4904 CK_KEY_TYPE keyType
= CKK_GENERIC_SECRET
;
4905 CK_OBJECT_CLASS classType
= CKO_SECRET_KEY
;
4906 CK_KEY_DERIVATION_STRING_DATA
*stringPtr
;
4907 PRBool isTLS
= PR_FALSE
;
4908 PRBool isDH
= PR_FALSE
;
4911 unsigned int outLen
;
4912 unsigned char sha_out
[SHA1_LENGTH
];
4913 unsigned char key_block
[NUM_MIXERS
* MD5_LENGTH
];
4914 unsigned char key_block2
[MD5_LENGTH
];
4920 return CKR_SESSION_HANDLE_INVALID
;
4923 * now lets create an object to hang the attributes off of
4925 if (phKey
) *phKey
= CK_INVALID_HANDLE
;
4927 key
= sftk_NewObject(slot
); /* fill in the handle later */
4929 return CKR_HOST_MEMORY
;
4931 isFIPS
= (slot
->slotID
== FIPS_SLOT_ID
);
4934 * load the template values into the object
4936 for (i
=0; i
< (int) ulAttributeCount
; i
++) {
4937 crv
= sftk_AddAttributeType(key
,sftk_attr_expand(&pTemplate
[i
]));
4938 if (crv
!= CKR_OK
) break;
4940 if (pTemplate
[i
].type
== CKA_KEY_TYPE
) {
4941 keyType
= *(CK_KEY_TYPE
*)pTemplate
[i
].pValue
;
4943 if (pTemplate
[i
].type
== CKA_VALUE_LEN
) {
4944 keySize
= *(CK_ULONG
*)pTemplate
[i
].pValue
;
4947 if (crv
!= CKR_OK
) { sftk_FreeObject(key
); return crv
; }
4950 keySize
= sftk_MapKeySize(keyType
);
4953 /* Derive can only create SECRET KEY's currently... */
4954 classType
= CKO_SECRET_KEY
;
4955 crv
= sftk_forceAttribute (key
,CKA_CLASS
,&classType
,sizeof(classType
));
4956 if (crv
!= CKR_OK
) {
4957 sftk_FreeObject(key
);
4961 /* look up the base key we're deriving with */
4962 session
= sftk_SessionFromHandle(hSession
);
4963 if (session
== NULL
) {
4964 sftk_FreeObject(key
);
4965 return CKR_SESSION_HANDLE_INVALID
;
4968 sourceKey
= sftk_ObjectFromHandle(hBaseKey
,session
);
4969 sftk_FreeSession(session
);
4970 if (sourceKey
== NULL
) {
4971 sftk_FreeObject(key
);
4972 return CKR_KEY_HANDLE_INVALID
;
4975 /* get the value of the base key */
4976 att
= sftk_FindAttribute(sourceKey
,CKA_VALUE
);
4978 sftk_FreeObject(key
);
4979 sftk_FreeObject(sourceKey
);
4980 return CKR_KEY_HANDLE_INVALID
;
4983 switch (pMechanism
->mechanism
) {
4985 * generate the master secret
4987 case CKM_TLS_MASTER_KEY_DERIVE
:
4988 case CKM_TLS_MASTER_KEY_DERIVE_DH
:
4991 case CKM_SSL3_MASTER_KEY_DERIVE
:
4992 case CKM_SSL3_MASTER_KEY_DERIVE_DH
:
4994 CK_SSL3_MASTER_KEY_DERIVE_PARAMS
*ssl3_master
;
4995 SSL3RSAPreMasterSecret
* rsa_pms
;
4996 unsigned char crsrdata
[SSL3_RANDOM_LENGTH
* 2];
4998 if ((pMechanism
->mechanism
== CKM_SSL3_MASTER_KEY_DERIVE_DH
) ||
4999 (pMechanism
->mechanism
== CKM_TLS_MASTER_KEY_DERIVE_DH
))
5002 /* first do the consistancy checks */
5003 if (!isDH
&& (att
->attrib
.ulValueLen
!= SSL3_PMS_LENGTH
)) {
5004 crv
= CKR_KEY_TYPE_INCONSISTENT
;
5007 att2
= sftk_FindAttribute(sourceKey
,CKA_KEY_TYPE
);
5008 if ((att2
== NULL
) || (*(CK_KEY_TYPE
*)att2
->attrib
.pValue
!=
5009 CKK_GENERIC_SECRET
)) {
5010 if (att2
) sftk_FreeAttribute(att2
);
5011 crv
= CKR_KEY_FUNCTION_NOT_PERMITTED
;
5014 sftk_FreeAttribute(att2
);
5015 if (keyType
!= CKK_GENERIC_SECRET
) {
5016 crv
= CKR_KEY_FUNCTION_NOT_PERMITTED
;
5019 if ((keySize
!= 0) && (keySize
!= SSL3_MASTER_SECRET_LENGTH
)) {
5020 crv
= CKR_KEY_FUNCTION_NOT_PERMITTED
;
5024 /* finally do the key gen */
5025 ssl3_master
= (CK_SSL3_MASTER_KEY_DERIVE_PARAMS
*)
5026 pMechanism
->pParameter
;
5028 PORT_Memcpy(crsrdata
,
5029 ssl3_master
->RandomInfo
.pClientRandom
, SSL3_RANDOM_LENGTH
);
5030 PORT_Memcpy(crsrdata
+ SSL3_RANDOM_LENGTH
,
5031 ssl3_master
->RandomInfo
.pServerRandom
, SSL3_RANDOM_LENGTH
);
5033 if (ssl3_master
->pVersion
) {
5034 SFTKSessionObject
*sessKey
= sftk_narrowToSessionObject(key
);
5035 rsa_pms
= (SSL3RSAPreMasterSecret
*) att
->attrib
.pValue
;
5036 /* don't leak more key material then necessary for SSL to work */
5037 if ((sessKey
== NULL
) || sessKey
->wasDerived
) {
5038 ssl3_master
->pVersion
->major
= 0xff;
5039 ssl3_master
->pVersion
->minor
= 0xff;
5041 ssl3_master
->pVersion
->major
= rsa_pms
->client_version
[0];
5042 ssl3_master
->pVersion
->minor
= rsa_pms
->client_version
[1];
5045 if (ssl3_master
->RandomInfo
.ulClientRandomLen
!= SSL3_RANDOM_LENGTH
) {
5046 crv
= CKR_MECHANISM_PARAM_INVALID
;
5049 if (ssl3_master
->RandomInfo
.ulServerRandomLen
!= SSL3_RANDOM_LENGTH
) {
5050 crv
= CKR_MECHANISM_PARAM_INVALID
;
5056 SECItem crsr
= { siBuffer
, NULL
, 0 };
5057 SECItem master
= { siBuffer
, NULL
, 0 };
5058 SECItem pms
= { siBuffer
, NULL
, 0 };
5060 crsr
.data
= crsrdata
;
5061 crsr
.len
= sizeof crsrdata
;
5062 master
.data
= key_block
;
5063 master
.len
= SSL3_MASTER_SECRET_LENGTH
;
5064 pms
.data
= (unsigned char*)att
->attrib
.pValue
;
5065 pms
.len
= att
->attrib
.ulValueLen
;
5067 status
= TLS_PRF(&pms
, "master secret", &crsr
, &master
, isFIPS
);
5068 if (status
!= SECSuccess
) {
5069 crv
= CKR_FUNCTION_FAILED
;
5073 /* now allocate the hash contexts */
5074 md5
= MD5_NewContext();
5076 crv
= CKR_HOST_MEMORY
;
5079 sha
= SHA1_NewContext();
5082 crv
= CKR_HOST_MEMORY
;
5085 for (i
= 0; i
< 3; i
++) {
5087 SHA1_Update(sha
, (unsigned char*) mixers
[i
], strlen(mixers
[i
]));
5088 SHA1_Update(sha
, (const unsigned char*)att
->attrib
.pValue
,
5089 att
->attrib
.ulValueLen
);
5090 SHA1_Update(sha
, crsrdata
, sizeof crsrdata
);
5091 SHA1_End(sha
, sha_out
, &outLen
, SHA1_LENGTH
);
5092 PORT_Assert(outLen
== SHA1_LENGTH
);
5095 MD5_Update(md5
, (const unsigned char*)att
->attrib
.pValue
,
5096 att
->attrib
.ulValueLen
);
5097 MD5_Update(md5
, sha_out
, outLen
);
5098 MD5_End(md5
, &key_block
[i
*MD5_LENGTH
], &outLen
, MD5_LENGTH
);
5099 PORT_Assert(outLen
== MD5_LENGTH
);
5105 /* store the results */
5106 crv
= sftk_forceAttribute
5107 (key
,CKA_VALUE
,key_block
,SSL3_MASTER_SECRET_LENGTH
);
5108 if (crv
!= CKR_OK
) break;
5109 keyType
= CKK_GENERIC_SECRET
;
5110 crv
= sftk_forceAttribute (key
,CKA_KEY_TYPE
,&keyType
,sizeof(keyType
));
5112 /* TLS's master secret is used to "sign" finished msgs with PRF. */
5113 /* XXX This seems like a hack. But SFTK_Derive only accepts
5114 * one "operation" argument. */
5115 crv
= sftk_forceAttribute(key
,CKA_SIGN
, &cktrue
,sizeof(CK_BBOOL
));
5116 if (crv
!= CKR_OK
) break;
5117 crv
= sftk_forceAttribute(key
,CKA_VERIFY
,&cktrue
,sizeof(CK_BBOOL
));
5118 if (crv
!= CKR_OK
) break;
5119 /* While we're here, we might as well force this, too. */
5120 crv
= sftk_forceAttribute(key
,CKA_DERIVE
,&cktrue
,sizeof(CK_BBOOL
));
5121 if (crv
!= CKR_OK
) break;
5126 case CKM_TLS_KEY_AND_MAC_DERIVE
:
5129 case CKM_SSL3_KEY_AND_MAC_DERIVE
:
5131 CK_SSL3_KEY_MAT_PARAMS
*ssl3_keys
;
5132 CK_SSL3_KEY_MAT_OUT
* ssl3_keys_out
;
5133 CK_ULONG effKeySize
;
5134 unsigned int block_needed
;
5135 unsigned char srcrdata
[SSL3_RANDOM_LENGTH
* 2];
5136 unsigned char crsrdata
[SSL3_RANDOM_LENGTH
* 2];
5138 crv
= sftk_DeriveSensitiveCheck(sourceKey
,key
);
5139 if (crv
!= CKR_OK
) break;
5141 if (att
->attrib
.ulValueLen
!= SSL3_MASTER_SECRET_LENGTH
) {
5142 crv
= CKR_KEY_FUNCTION_NOT_PERMITTED
;
5145 att2
= sftk_FindAttribute(sourceKey
,CKA_KEY_TYPE
);
5146 if ((att2
== NULL
) || (*(CK_KEY_TYPE
*)att2
->attrib
.pValue
!=
5147 CKK_GENERIC_SECRET
)) {
5148 if (att2
) sftk_FreeAttribute(att2
);
5149 crv
= CKR_KEY_FUNCTION_NOT_PERMITTED
;
5152 sftk_FreeAttribute(att2
);
5153 md5
= MD5_NewContext();
5155 crv
= CKR_HOST_MEMORY
;
5158 sha
= SHA1_NewContext();
5161 crv
= CKR_HOST_MEMORY
;
5164 ssl3_keys
= (CK_SSL3_KEY_MAT_PARAMS
*) pMechanism
->pParameter
;
5166 PORT_Memcpy(srcrdata
,
5167 ssl3_keys
->RandomInfo
.pServerRandom
, SSL3_RANDOM_LENGTH
);
5168 PORT_Memcpy(srcrdata
+ SSL3_RANDOM_LENGTH
,
5169 ssl3_keys
->RandomInfo
.pClientRandom
, SSL3_RANDOM_LENGTH
);
5171 PORT_Memcpy(crsrdata
,
5172 ssl3_keys
->RandomInfo
.pClientRandom
, SSL3_RANDOM_LENGTH
);
5173 PORT_Memcpy(crsrdata
+ SSL3_RANDOM_LENGTH
,
5174 ssl3_keys
->RandomInfo
.pServerRandom
, SSL3_RANDOM_LENGTH
);
5177 * clear out our returned keys so we can recover on failure
5179 ssl3_keys_out
= ssl3_keys
->pReturnedKeyMaterial
;
5180 ssl3_keys_out
->hClientMacSecret
= CK_INVALID_HANDLE
;
5181 ssl3_keys_out
->hServerMacSecret
= CK_INVALID_HANDLE
;
5182 ssl3_keys_out
->hClientKey
= CK_INVALID_HANDLE
;
5183 ssl3_keys_out
->hServerKey
= CK_INVALID_HANDLE
;
5186 * How much key material do we need?
5188 macSize
= ssl3_keys
->ulMacSizeInBits
/8;
5189 effKeySize
= ssl3_keys
->ulKeySizeInBits
/8;
5190 IVSize
= ssl3_keys
->ulIVSizeInBits
/8;
5192 effKeySize
= keySize
;
5194 block_needed
= 2 * (macSize
+ effKeySize
+
5195 ((!ssl3_keys
->bIsExport
) * IVSize
));
5196 PORT_Assert(block_needed
<= sizeof key_block
);
5197 if (block_needed
> sizeof key_block
)
5198 block_needed
= sizeof key_block
;
5201 * generate the key material: This looks amazingly similar to the
5202 * PMS code, and is clearly crying out for a function to provide it.
5206 SECItem srcr
= { siBuffer
, NULL
, 0 };
5207 SECItem keyblk
= { siBuffer
, NULL
, 0 };
5208 SECItem master
= { siBuffer
, NULL
, 0 };
5210 srcr
.data
= srcrdata
;
5211 srcr
.len
= sizeof srcrdata
;
5212 keyblk
.data
= key_block
;
5213 keyblk
.len
= block_needed
;
5214 master
.data
= (unsigned char*)att
->attrib
.pValue
;
5215 master
.len
= att
->attrib
.ulValueLen
;
5217 status
= TLS_PRF(&master
, "key expansion", &srcr
, &keyblk
,
5219 if (status
!= SECSuccess
) {
5220 goto key_and_mac_derive_fail
;
5223 unsigned int block_bytes
= 0;
5225 * MD5(master_secret + SHA('A' + master_secret +
5226 * ServerHello.random + ClientHello.random)) +
5227 * MD5(master_secret + SHA('BB' + master_secret +
5228 * ServerHello.random + ClientHello.random)) +
5229 * MD5(master_secret + SHA('CCC' + master_secret +
5230 * ServerHello.random + ClientHello.random)) +
5233 for (i
= 0; i
< NUM_MIXERS
&& block_bytes
< block_needed
; i
++) {
5235 SHA1_Update(sha
, (unsigned char*) mixers
[i
], strlen(mixers
[i
]));
5236 SHA1_Update(sha
, (const unsigned char*)att
->attrib
.pValue
,
5237 att
->attrib
.ulValueLen
);
5238 SHA1_Update(sha
, srcrdata
, sizeof srcrdata
);
5239 SHA1_End(sha
, sha_out
, &outLen
, SHA1_LENGTH
);
5240 PORT_Assert(outLen
== SHA1_LENGTH
);
5242 MD5_Update(md5
, (const unsigned char*)att
->attrib
.pValue
,
5243 att
->attrib
.ulValueLen
);
5244 MD5_Update(md5
, sha_out
, outLen
);
5245 MD5_End(md5
, &key_block
[i
*MD5_LENGTH
], &outLen
, MD5_LENGTH
);
5246 PORT_Assert(outLen
== MD5_LENGTH
);
5247 block_bytes
+= outLen
;
5252 * Put the key material where it goes.
5254 i
= 0; /* now shows how much consumed */
5257 * The key_block is partitioned as follows:
5258 * client_write_MAC_secret[CipherSpec.hash_size]
5260 crv
= sftk_buildSSLKey(hSession
,key
,PR_TRUE
,&key_block
[i
],macSize
,
5261 &ssl3_keys_out
->hClientMacSecret
);
5263 goto key_and_mac_derive_fail
;
5268 * server_write_MAC_secret[CipherSpec.hash_size]
5270 crv
= sftk_buildSSLKey(hSession
,key
,PR_TRUE
,&key_block
[i
],macSize
,
5271 &ssl3_keys_out
->hServerMacSecret
);
5272 if (crv
!= CKR_OK
) {
5273 goto key_and_mac_derive_fail
;
5278 if (!ssl3_keys
->bIsExport
) {
5280 ** Generate Domestic write keys and IVs.
5281 ** client_write_key[CipherSpec.key_material]
5283 crv
= sftk_buildSSLKey(hSession
,key
,PR_FALSE
,&key_block
[i
],
5284 keySize
, &ssl3_keys_out
->hClientKey
);
5285 if (crv
!= CKR_OK
) {
5286 goto key_and_mac_derive_fail
;
5291 ** server_write_key[CipherSpec.key_material]
5293 crv
= sftk_buildSSLKey(hSession
,key
,PR_FALSE
,&key_block
[i
],
5294 keySize
, &ssl3_keys_out
->hServerKey
);
5295 if (crv
!= CKR_OK
) {
5296 goto key_and_mac_derive_fail
;
5301 ** client_write_IV[CipherSpec.IV_size]
5304 PORT_Memcpy(ssl3_keys_out
->pIVClient
,
5305 &key_block
[i
], IVSize
);
5310 ** server_write_IV[CipherSpec.IV_size]
5313 PORT_Memcpy(ssl3_keys_out
->pIVServer
,
5314 &key_block
[i
], IVSize
);
5317 PORT_Assert(i
<= sizeof key_block
);
5319 } else if (!isTLS
) {
5322 ** Generate SSL3 Export write keys and IVs.
5323 ** client_write_key[CipherSpec.key_material]
5324 ** final_client_write_key = MD5(client_write_key +
5325 ** ClientHello.random + ServerHello.random);
5328 MD5_Update(md5
, &key_block
[i
], effKeySize
);
5329 MD5_Update(md5
, crsrdata
, sizeof crsrdata
);
5330 MD5_End(md5
, key_block2
, &outLen
, MD5_LENGTH
);
5332 crv
= sftk_buildSSLKey(hSession
,key
,PR_FALSE
,key_block2
,
5333 keySize
,&ssl3_keys_out
->hClientKey
);
5334 if (crv
!= CKR_OK
) {
5335 goto key_and_mac_derive_fail
;
5339 ** server_write_key[CipherSpec.key_material]
5340 ** final_server_write_key = MD5(server_write_key +
5341 ** ServerHello.random + ClientHello.random);
5344 MD5_Update(md5
, &key_block
[i
], effKeySize
);
5345 MD5_Update(md5
, srcrdata
, sizeof srcrdata
);
5346 MD5_End(md5
, key_block2
, &outLen
, MD5_LENGTH
);
5348 crv
= sftk_buildSSLKey(hSession
,key
,PR_FALSE
,key_block2
,
5349 keySize
,&ssl3_keys_out
->hServerKey
);
5350 if (crv
!= CKR_OK
) {
5351 goto key_and_mac_derive_fail
;
5355 ** client_write_IV =
5356 ** MD5(ClientHello.random + ServerHello.random);
5359 MD5_Update(md5
, crsrdata
, sizeof crsrdata
);
5360 MD5_End(md5
, key_block2
, &outLen
, MD5_LENGTH
);
5361 PORT_Memcpy(ssl3_keys_out
->pIVClient
, key_block2
, IVSize
);
5364 ** server_write_IV =
5365 ** MD5(ServerHello.random + ClientHello.random);
5368 MD5_Update(md5
, srcrdata
, sizeof srcrdata
);
5369 MD5_End(md5
, key_block2
, &outLen
, MD5_LENGTH
);
5370 PORT_Memcpy(ssl3_keys_out
->pIVServer
, key_block2
, IVSize
);
5375 ** Generate TLS Export write keys and IVs.
5378 SECItem secret
= { siBuffer
, NULL
, 0 };
5379 SECItem crsr
= { siBuffer
, NULL
, 0 };
5380 SECItem keyblk
= { siBuffer
, NULL
, 0 };
5383 ** client_write_key[CipherSpec.key_material]
5384 ** final_client_write_key = PRF(client_write_key,
5385 ** "client write key",
5386 ** client_random + server_random);
5388 secret
.data
= &key_block
[i
];
5389 secret
.len
= effKeySize
;
5391 crsr
.data
= crsrdata
;
5392 crsr
.len
= sizeof crsrdata
;
5393 keyblk
.data
= key_block2
;
5394 keyblk
.len
= sizeof key_block2
;
5395 status
= TLS_PRF(&secret
, "client write key", &crsr
, &keyblk
,
5397 if (status
!= SECSuccess
) {
5398 goto key_and_mac_derive_fail
;
5400 crv
= sftk_buildSSLKey(hSession
, key
, PR_FALSE
, key_block2
,
5401 keySize
, &ssl3_keys_out
->hClientKey
);
5402 if (crv
!= CKR_OK
) {
5403 goto key_and_mac_derive_fail
;
5407 ** server_write_key[CipherSpec.key_material]
5408 ** final_server_write_key = PRF(server_write_key,
5409 ** "server write key",
5410 ** client_random + server_random);
5412 secret
.data
= &key_block
[i
];
5413 secret
.len
= effKeySize
;
5415 keyblk
.data
= key_block2
;
5416 keyblk
.len
= sizeof key_block2
;
5417 status
= TLS_PRF(&secret
, "server write key", &crsr
, &keyblk
,
5419 if (status
!= SECSuccess
) {
5420 goto key_and_mac_derive_fail
;
5422 crv
= sftk_buildSSLKey(hSession
, key
, PR_FALSE
, key_block2
,
5423 keySize
, &ssl3_keys_out
->hServerKey
);
5424 if (crv
!= CKR_OK
) {
5425 goto key_and_mac_derive_fail
;
5429 ** iv_block = PRF("", "IV block",
5430 ** client_random + server_random);
5431 ** client_write_IV[SecurityParameters.IV_size]
5432 ** server_write_IV[SecurityParameters.IV_size]
5437 keyblk
.data
= &key_block
[i
];
5438 keyblk
.len
= 2 * IVSize
;
5439 status
= TLS_PRF(&secret
, "IV block", &crsr
, &keyblk
,
5441 if (status
!= SECSuccess
) {
5442 goto key_and_mac_derive_fail
;
5444 PORT_Memcpy(ssl3_keys_out
->pIVClient
, keyblk
.data
, IVSize
);
5445 PORT_Memcpy(ssl3_keys_out
->pIVServer
, keyblk
.data
+ IVSize
,
5454 key_and_mac_derive_fail
:
5456 crv
= CKR_FUNCTION_FAILED
;
5457 sftk_freeSSLKeys(hSession
, ssl3_keys_out
);
5459 MD5_DestroyContext(md5
, PR_TRUE
);
5460 SHA1_DestroyContext(sha
, PR_TRUE
);
5461 sftk_FreeObject(key
);
5466 case CKM_CONCATENATE_BASE_AND_KEY
:
5470 crv
= sftk_DeriveSensitiveCheck(sourceKey
,key
);
5471 if (crv
!= CKR_OK
) break;
5473 session
= sftk_SessionFromHandle(hSession
);
5474 if (session
== NULL
) {
5475 crv
= CKR_SESSION_HANDLE_INVALID
;
5479 newKey
= sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE
*)
5480 pMechanism
->pParameter
,session
);
5481 sftk_FreeSession(session
);
5482 if ( newKey
== NULL
) {
5483 crv
= CKR_KEY_HANDLE_INVALID
;
5487 if (sftk_isTrue(newKey
,CKA_SENSITIVE
)) {
5488 crv
= sftk_forceAttribute(newKey
,CKA_SENSITIVE
,&cktrue
,
5490 if (crv
!= CKR_OK
) {
5491 sftk_FreeObject(newKey
);
5496 att2
= sftk_FindAttribute(newKey
,CKA_VALUE
);
5498 sftk_FreeObject(newKey
);
5499 crv
= CKR_KEY_HANDLE_INVALID
;
5502 tmpKeySize
= att
->attrib
.ulValueLen
+att2
->attrib
.ulValueLen
;
5503 if (keySize
== 0) keySize
= tmpKeySize
;
5504 if (keySize
> tmpKeySize
) {
5505 sftk_FreeObject(newKey
);
5506 sftk_FreeAttribute(att2
);
5507 crv
= CKR_TEMPLATE_INCONSISTENT
;
5510 buf
= (unsigned char*)PORT_Alloc(tmpKeySize
);
5512 sftk_FreeAttribute(att2
);
5513 sftk_FreeObject(newKey
);
5514 crv
= CKR_HOST_MEMORY
;
5518 PORT_Memcpy(buf
,att
->attrib
.pValue
,att
->attrib
.ulValueLen
);
5519 PORT_Memcpy(buf
+att
->attrib
.ulValueLen
,
5520 att2
->attrib
.pValue
,att2
->attrib
.ulValueLen
);
5522 crv
= sftk_forceAttribute (key
,CKA_VALUE
,buf
,keySize
);
5523 PORT_ZFree(buf
,tmpKeySize
);
5524 sftk_FreeAttribute(att2
);
5525 sftk_FreeObject(newKey
);
5529 case CKM_CONCATENATE_BASE_AND_DATA
:
5530 crv
= sftk_DeriveSensitiveCheck(sourceKey
,key
);
5531 if (crv
!= CKR_OK
) break;
5533 stringPtr
= (CK_KEY_DERIVATION_STRING_DATA
*) pMechanism
->pParameter
;
5534 tmpKeySize
= att
->attrib
.ulValueLen
+stringPtr
->ulLen
;
5535 if (keySize
== 0) keySize
= tmpKeySize
;
5536 if (keySize
> tmpKeySize
) {
5537 crv
= CKR_TEMPLATE_INCONSISTENT
;
5540 buf
= (unsigned char*)PORT_Alloc(tmpKeySize
);
5542 crv
= CKR_HOST_MEMORY
;
5546 PORT_Memcpy(buf
,att
->attrib
.pValue
,att
->attrib
.ulValueLen
);
5547 PORT_Memcpy(buf
+att
->attrib
.ulValueLen
,stringPtr
->pData
,
5550 crv
= sftk_forceAttribute (key
,CKA_VALUE
,buf
,keySize
);
5551 PORT_ZFree(buf
,tmpKeySize
);
5553 case CKM_CONCATENATE_DATA_AND_BASE
:
5554 crv
= sftk_DeriveSensitiveCheck(sourceKey
,key
);
5555 if (crv
!= CKR_OK
) break;
5557 stringPtr
= (CK_KEY_DERIVATION_STRING_DATA
*)pMechanism
->pParameter
;
5558 tmpKeySize
= att
->attrib
.ulValueLen
+stringPtr
->ulLen
;
5559 if (keySize
== 0) keySize
= tmpKeySize
;
5560 if (keySize
> tmpKeySize
) {
5561 crv
= CKR_TEMPLATE_INCONSISTENT
;
5564 buf
= (unsigned char*)PORT_Alloc(tmpKeySize
);
5566 crv
= CKR_HOST_MEMORY
;
5570 PORT_Memcpy(buf
,stringPtr
->pData
,stringPtr
->ulLen
);
5571 PORT_Memcpy(buf
+stringPtr
->ulLen
,att
->attrib
.pValue
,
5572 att
->attrib
.ulValueLen
);
5574 crv
= sftk_forceAttribute (key
,CKA_VALUE
,buf
,keySize
);
5575 PORT_ZFree(buf
,tmpKeySize
);
5577 case CKM_XOR_BASE_AND_DATA
:
5578 crv
= sftk_DeriveSensitiveCheck(sourceKey
,key
);
5579 if (crv
!= CKR_OK
) break;
5581 stringPtr
= (CK_KEY_DERIVATION_STRING_DATA
*)pMechanism
->pParameter
;
5582 tmpKeySize
= PR_MIN(att
->attrib
.ulValueLen
,stringPtr
->ulLen
);
5583 if (keySize
== 0) keySize
= tmpKeySize
;
5584 if (keySize
> tmpKeySize
) {
5585 crv
= CKR_TEMPLATE_INCONSISTENT
;
5588 buf
= (unsigned char*)PORT_Alloc(keySize
);
5590 crv
= CKR_HOST_MEMORY
;
5595 PORT_Memcpy(buf
,att
->attrib
.pValue
,keySize
);
5596 for (i
=0; i
< (int)keySize
; i
++) {
5597 buf
[i
] ^= stringPtr
->pData
[i
];
5600 crv
= sftk_forceAttribute (key
,CKA_VALUE
,buf
,keySize
);
5601 PORT_ZFree(buf
,keySize
);
5604 case CKM_EXTRACT_KEY_FROM_KEY
:
5606 /* the following assumes 8 bits per byte */
5607 CK_ULONG extract
= *(CK_EXTRACT_PARAMS
*)pMechanism
->pParameter
;
5608 CK_ULONG shift
= extract
& 0x7; /* extract mod 8 the fast way */
5609 CK_ULONG offset
= extract
>> 3; /* extract div 8 the fast way */
5611 crv
= sftk_DeriveSensitiveCheck(sourceKey
,key
);
5612 if (crv
!= CKR_OK
) break;
5615 crv
= CKR_TEMPLATE_INCOMPLETE
;
5618 /* make sure we have enough bits in the original key */
5619 if (att
->attrib
.ulValueLen
<
5620 (offset
+ keySize
+ ((shift
!= 0)? 1 :0)) ) {
5621 crv
= CKR_MECHANISM_PARAM_INVALID
;
5624 buf
= (unsigned char*)PORT_Alloc(keySize
);
5626 crv
= CKR_HOST_MEMORY
;
5630 /* copy the bits we need into the new key */
5631 for (i
=0; i
< (int)keySize
; i
++) {
5632 unsigned char *value
=
5633 ((unsigned char *)att
->attrib
.pValue
)+offset
+i
;
5635 buf
[i
] = (value
[0] << (shift
)) | (value
[1] >> (8 - shift
));
5641 crv
= sftk_forceAttribute (key
,CKA_VALUE
,buf
,keySize
);
5642 PORT_ZFree(buf
,keySize
);
5645 case CKM_MD2_KEY_DERIVATION
:
5646 if (keySize
== 0) keySize
= MD2_LENGTH
;
5647 if (keySize
> MD2_LENGTH
) {
5648 crv
= CKR_TEMPLATE_INCONSISTENT
;
5651 /* now allocate the hash contexts */
5652 md2
= MD2_NewContext();
5654 crv
= CKR_HOST_MEMORY
;
5658 MD2_Update(md2
,(const unsigned char*)att
->attrib
.pValue
,
5659 att
->attrib
.ulValueLen
);
5660 MD2_End(md2
,key_block
,&outLen
,MD2_LENGTH
);
5661 MD2_DestroyContext(md2
, PR_TRUE
);
5663 crv
= sftk_forceAttribute (key
,CKA_VALUE
,key_block
,keySize
);
5665 case CKM_MD5_KEY_DERIVATION
:
5666 if (keySize
== 0) keySize
= MD5_LENGTH
;
5667 if (keySize
> MD5_LENGTH
) {
5668 crv
= CKR_TEMPLATE_INCONSISTENT
;
5671 /* now allocate the hash contexts */
5672 md5
= MD5_NewContext();
5674 crv
= CKR_HOST_MEMORY
;
5678 MD5_Update(md5
,(const unsigned char*)att
->attrib
.pValue
,
5679 att
->attrib
.ulValueLen
);
5680 MD5_End(md5
,key_block
,&outLen
,MD5_LENGTH
);
5681 MD5_DestroyContext(md5
, PR_TRUE
);
5683 crv
= sftk_forceAttribute (key
,CKA_VALUE
,key_block
,keySize
);
5685 case CKM_SHA1_KEY_DERIVATION
:
5686 if (keySize
== 0) keySize
= SHA1_LENGTH
;
5687 if (keySize
> SHA1_LENGTH
) {
5688 crv
= CKR_TEMPLATE_INCONSISTENT
;
5691 /* now allocate the hash contexts */
5692 sha
= SHA1_NewContext();
5694 crv
= CKR_HOST_MEMORY
;
5698 SHA1_Update(sha
,(const unsigned char*)att
->attrib
.pValue
,
5699 att
->attrib
.ulValueLen
);
5700 SHA1_End(sha
,key_block
,&outLen
,SHA1_LENGTH
);
5701 SHA1_DestroyContext(sha
, PR_TRUE
);
5703 crv
= sftk_forceAttribute(key
,CKA_VALUE
,key_block
,keySize
);
5706 case CKM_DH_PKCS_DERIVE
:
5708 SECItem derived
, dhPublic
;
5709 SECItem dhPrime
, dhValue
;
5710 /* sourceKey - values for the local existing low key */
5711 /* get prime and value attributes */
5712 crv
= sftk_Attribute2SecItem(NULL
, &dhPrime
, sourceKey
, CKA_PRIME
);
5713 if (crv
!= SECSuccess
) break;
5714 crv
= sftk_Attribute2SecItem(NULL
, &dhValue
, sourceKey
, CKA_VALUE
);
5715 if (crv
!= SECSuccess
) {
5716 PORT_Free(dhPrime
.data
);
5720 dhPublic
.data
= pMechanism
->pParameter
;
5721 dhPublic
.len
= pMechanism
->ulParameterLen
;
5723 /* calculate private value - oct */
5724 rv
= DH_Derive(&dhPublic
, &dhPrime
, &dhValue
, &derived
, keySize
);
5726 PORT_Free(dhPrime
.data
);
5727 PORT_Free(dhValue
.data
);
5729 if (rv
== SECSuccess
) {
5730 sftk_forceAttribute(key
, CKA_VALUE
, derived
.data
, derived
.len
);
5731 PORT_ZFree(derived
.data
, derived
.len
);
5733 crv
= CKR_HOST_MEMORY
;
5738 #ifdef NSS_ENABLE_ECC
5739 case CKM_ECDH1_DERIVE
:
5740 case CKM_ECDH1_COFACTOR_DERIVE
:
5742 SECItem ecScalar
, ecPoint
;
5744 PRBool withCofactor
= PR_FALSE
;
5745 unsigned char secret_hash
[20];
5746 unsigned char *secret
;
5747 unsigned char *keyData
= NULL
;
5749 CK_ECDH1_DERIVE_PARAMS
*mechParams
;
5750 NSSLOWKEYPrivateKey
*privKey
;
5752 /* Check mechanism parameters */
5753 mechParams
= (CK_ECDH1_DERIVE_PARAMS
*) pMechanism
->pParameter
;
5754 if ((pMechanism
->ulParameterLen
!= sizeof(CK_ECDH1_DERIVE_PARAMS
)) ||
5755 ((mechParams
->kdf
== CKD_NULL
) &&
5756 ((mechParams
->ulSharedDataLen
!= 0) ||
5757 (mechParams
->pSharedData
!= NULL
)))) {
5758 crv
= CKR_MECHANISM_PARAM_INVALID
;
5762 privKey
= sftk_GetPrivKey(sourceKey
, CKK_EC
, &crv
);
5763 if (privKey
== NULL
) {
5767 /* Now we are working with a non-NULL private key */
5768 SECITEM_CopyItem(NULL
, &ecScalar
, &privKey
->u
.ec
.privateValue
);
5770 ecPoint
.data
= mechParams
->pPublicData
;
5771 ecPoint
.len
= mechParams
->ulPublicDataLen
;
5773 if (pMechanism
->mechanism
== CKM_ECDH1_COFACTOR_DERIVE
) {
5774 withCofactor
= PR_TRUE
;
5776 /* When not using cofactor derivation, one should
5777 * validate the public key to avoid small subgroup
5780 if (EC_ValidatePublicKey(&privKey
->u
.ec
.ecParams
, &ecPoint
)
5782 crv
= CKR_ARGUMENTS_BAD
;
5783 PORT_Free(ecScalar
.data
);
5784 if (privKey
!= sourceKey
->objectInfo
)
5785 nsslowkey_DestroyPrivateKey(privKey
);
5790 rv
= ECDH_Derive(&ecPoint
, &privKey
->u
.ec
.ecParams
, &ecScalar
,
5791 withCofactor
, &tmp
);
5792 PORT_Free(ecScalar
.data
);
5793 if (privKey
!= sourceKey
->objectInfo
)
5794 nsslowkey_DestroyPrivateKey(privKey
);
5796 if (rv
!= SECSuccess
) {
5797 crv
= CKR_DEVICE_ERROR
;
5802 * tmp is the raw data created by ECDH_Derive,
5803 * secret and secretlen are the values we will eventually pass as our
5807 secretlen
= tmp
.len
;
5810 * apply the kdf function.
5812 if (mechParams
->kdf
== CKD_SHA1_KDF
) {
5813 /* Compute SHA1 hash */
5814 PORT_Memset(secret_hash
, 0, 20);
5815 rv
= SHA1_HashBuf(secret_hash
, tmp
.data
, tmp
.len
);
5816 if (rv
!= SECSuccess
) {
5817 PORT_ZFree(tmp
.data
, tmp
.len
);
5818 crv
= CKR_HOST_MEMORY
;
5821 secret
= secret_hash
;
5826 * if keySize is supplied, then we are generating a key of a specific
5827 * length. This is done by taking the least significant 'keySize'
5828 * bytes from the unsigned value calculated by ECDH. Note: this may
5829 * mean padding temp with extra leading zeros from what ECDH_Derive
5830 * already returned (which itself may contain leading zeros).
5833 if (secretlen
< keySize
) {
5834 keyData
= PORT_ZAlloc(keySize
);
5836 PORT_ZFree(tmp
.data
, tmp
.len
);
5837 crv
= CKR_HOST_MEMORY
;
5840 PORT_Memcpy(&keyData
[keySize
-secretlen
],secret
,secretlen
);
5843 secret
+= (secretlen
- keySize
);
5845 secretlen
= keySize
;
5848 sftk_forceAttribute(key
, CKA_VALUE
, secret
, secretlen
);
5849 PORT_ZFree(tmp
.data
, tmp
.len
);
5851 PORT_ZFree(keyData
, keySize
);
5853 PORT_Memset(secret_hash
, 0, 20);
5857 #endif /* NSS_ENABLE_ECC */
5860 crv
= CKR_MECHANISM_INVALID
;
5862 sftk_FreeAttribute(att
);
5863 sftk_FreeObject(sourceKey
);
5864 if (crv
!= CKR_OK
) {
5865 if (key
) sftk_FreeObject(key
);
5869 /* link the key object into the list */
5871 SFTKSessionObject
*sessKey
= sftk_narrowToSessionObject(key
);
5872 PORT_Assert(sessKey
);
5873 /* get the session */
5874 sessKey
->wasDerived
= PR_TRUE
;
5875 session
= sftk_SessionFromHandle(hSession
);
5876 if (session
== NULL
) {
5877 sftk_FreeObject(key
);
5878 return CKR_HOST_MEMORY
;
5881 crv
= sftk_handleObject(key
,session
);
5882 sftk_FreeSession(session
);
5883 *phKey
= key
->handle
;
5884 sftk_FreeObject(key
);
5890 /* NSC_GetFunctionStatus obtains an updated status of a function running
5891 * in parallel with an application. */
5892 CK_RV
NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession
)
5896 return CKR_FUNCTION_NOT_PARALLEL
;
5899 /* NSC_CancelFunction cancels a function running in parallel */
5900 CK_RV
NSC_CancelFunction(CK_SESSION_HANDLE hSession
)
5904 return CKR_FUNCTION_NOT_PARALLEL
;
5907 /* NSC_GetOperationState saves the state of the cryptographic
5908 *operation in a session.
5909 * NOTE: This code only works for digest functions for now. eventually need
5910 * to add full flatten/resurect to our state stuff so that all types of state
5912 CK_RV
NSC_GetOperationState(CK_SESSION_HANDLE hSession
,
5913 CK_BYTE_PTR pOperationState
, CK_ULONG_PTR pulOperationStateLen
)
5915 SFTKSessionContext
*context
;
5916 SFTKSession
*session
;
5918 CK_ULONG pOSLen
= *pulOperationStateLen
;
5922 /* make sure we're legal */
5923 crv
= sftk_GetContext(hSession
, &context
, SFTK_HASH
, PR_TRUE
, &session
);
5924 if (crv
!= CKR_OK
) return crv
;
5926 *pulOperationStateLen
= context
->cipherInfoLen
+ sizeof(CK_MECHANISM_TYPE
)
5927 + sizeof(SFTKContextType
);
5928 if (pOperationState
== NULL
) {
5929 sftk_FreeSession(session
);
5932 if (pOSLen
< *pulOperationStateLen
) {
5933 return CKR_BUFFER_TOO_SMALL
;
5936 PORT_Memcpy(pOperationState
,&context
->type
,sizeof(SFTKContextType
));
5937 pOperationState
+= sizeof(SFTKContextType
);
5938 PORT_Memcpy(pOperationState
,&context
->currentMech
,
5939 sizeof(CK_MECHANISM_TYPE
));
5940 pOperationState
+= sizeof(CK_MECHANISM_TYPE
);
5941 PORT_Memcpy(pOperationState
,context
->cipherInfo
,context
->cipherInfoLen
);
5942 sftk_FreeSession(session
);
5947 #define sftk_Decrement(stateSize,len) \
5948 stateSize = ((stateSize) > (CK_ULONG)(len)) ? \
5949 ((stateSize) - (CK_ULONG)(len)) : 0;
5951 /* NSC_SetOperationState restores the state of the cryptographic
5952 * operation in a session. This is coded like it can restore lots of
5953 * states, but it only works for truly flat cipher structures. */
5954 CK_RV
NSC_SetOperationState(CK_SESSION_HANDLE hSession
,
5955 CK_BYTE_PTR pOperationState
, CK_ULONG ulOperationStateLen
,
5956 CK_OBJECT_HANDLE hEncryptionKey
, CK_OBJECT_HANDLE hAuthenticationKey
)
5958 SFTKSessionContext
*context
;
5959 SFTKSession
*session
;
5960 SFTKContextType type
;
5966 while (ulOperationStateLen
!= 0) {
5967 /* get what type of state we're dealing with... */
5968 PORT_Memcpy(&type
,pOperationState
, sizeof(SFTKContextType
));
5970 /* fix up session contexts based on type */
5971 session
= sftk_SessionFromHandle(hSession
);
5972 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
5973 context
= sftk_ReturnContextByType(session
, type
);
5974 sftk_SetContextByType(session
, type
, NULL
);
5976 sftk_FreeContext(context
);
5978 pOperationState
+= sizeof(SFTKContextType
);
5979 sftk_Decrement(ulOperationStateLen
,sizeof(SFTKContextType
));
5982 /* get the mechanism structure */
5983 PORT_Memcpy(&mech
.mechanism
,pOperationState
,sizeof(CK_MECHANISM_TYPE
));
5984 pOperationState
+= sizeof(CK_MECHANISM_TYPE
);
5985 sftk_Decrement(ulOperationStateLen
, sizeof(CK_MECHANISM_TYPE
));
5986 /* should be filled in... but not necessary for hash */
5987 mech
.pParameter
= NULL
;
5988 mech
.ulParameterLen
= 0;
5991 crv
= NSC_DigestInit(hSession
,&mech
);
5992 if (crv
!= CKR_OK
) break;
5993 crv
= sftk_GetContext(hSession
, &context
, SFTK_HASH
, PR_TRUE
,
5995 if (crv
!= CKR_OK
) break;
5996 PORT_Memcpy(context
->cipherInfo
,pOperationState
,
5997 context
->cipherInfoLen
);
5998 pOperationState
+= context
->cipherInfoLen
;
5999 sftk_Decrement(ulOperationStateLen
,context
->cipherInfoLen
);
6002 /* do sign/encrypt/decrypt later */
6003 crv
= CKR_SAVED_STATE_INVALID
;
6005 sftk_FreeSession(session
);
6006 if (crv
!= CKR_OK
) break;
6011 /* Dual-function cryptographic operations */
6013 /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
6015 CK_RV
NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pPart
,
6016 CK_ULONG ulPartLen
, CK_BYTE_PTR pEncryptedPart
,
6017 CK_ULONG_PTR pulEncryptedPartLen
)
6023 crv
= NSC_EncryptUpdate(hSession
,pPart
,ulPartLen
, pEncryptedPart
,
6024 pulEncryptedPartLen
);
6025 if (crv
!= CKR_OK
) return crv
;
6026 crv
= NSC_DigestUpdate(hSession
,pPart
,ulPartLen
);
6032 /* NSC_DecryptDigestUpdate continues a multiple-part decryption and
6033 * digesting operation. */
6034 CK_RV
NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession
,
6035 CK_BYTE_PTR pEncryptedPart
, CK_ULONG ulEncryptedPartLen
,
6036 CK_BYTE_PTR pPart
, CK_ULONG_PTR pulPartLen
)
6042 crv
= NSC_DecryptUpdate(hSession
,pEncryptedPart
, ulEncryptedPartLen
,
6044 if (crv
!= CKR_OK
) return crv
;
6045 crv
= NSC_DigestUpdate(hSession
,pPart
,*pulPartLen
);
6051 /* NSC_SignEncryptUpdate continues a multiple-part signing and
6052 * encryption operation. */
6053 CK_RV
NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pPart
,
6054 CK_ULONG ulPartLen
, CK_BYTE_PTR pEncryptedPart
,
6055 CK_ULONG_PTR pulEncryptedPartLen
)
6061 crv
= NSC_EncryptUpdate(hSession
,pPart
,ulPartLen
, pEncryptedPart
,
6062 pulEncryptedPartLen
);
6063 if (crv
!= CKR_OK
) return crv
;
6064 crv
= NSC_SignUpdate(hSession
,pPart
,ulPartLen
);
6070 /* NSC_DecryptVerifyUpdate continues a multiple-part decryption
6071 * and verify operation. */
6072 CK_RV
NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession
,
6073 CK_BYTE_PTR pEncryptedData
, CK_ULONG ulEncryptedDataLen
,
6074 CK_BYTE_PTR pData
, CK_ULONG_PTR pulDataLen
)
6080 crv
= NSC_DecryptUpdate(hSession
,pEncryptedData
, ulEncryptedDataLen
,
6082 if (crv
!= CKR_OK
) return crv
;
6083 crv
= NSC_VerifyUpdate(hSession
, pData
, *pulDataLen
);
6088 /* NSC_DigestKey continues a multi-part message-digesting operation,
6089 * by digesting the value of a secret key as part of the data already digested.
6091 CK_RV
NSC_DigestKey(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hKey
)
6093 SFTKSession
*session
= NULL
;
6094 SFTKObject
*key
= NULL
;
6100 session
= sftk_SessionFromHandle(hSession
);
6101 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
6103 key
= sftk_ObjectFromHandle(hKey
,session
);
6104 sftk_FreeSession(session
);
6105 if (key
== NULL
) return CKR_KEY_HANDLE_INVALID
;
6107 /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
6109 /* make sure it's a valid key for this operation */
6110 if (key
->objclass
!= CKO_SECRET_KEY
) {
6111 sftk_FreeObject(key
);
6112 return CKR_KEY_TYPE_INCONSISTENT
;
6114 /* get the key value */
6115 att
= sftk_FindAttribute(key
,CKA_VALUE
);
6116 sftk_FreeObject(key
);
6118 return CKR_KEY_HANDLE_INVALID
;
6120 crv
= NSC_DigestUpdate(hSession
,(CK_BYTE_PTR
)att
->attrib
.pValue
,
6121 att
->attrib
.ulValueLen
);
6122 sftk_FreeAttribute(att
);