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.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 * This file implements the Symkey wrapper and the PKCS context
56 * find an RSA public key on a card
58 static CK_OBJECT_HANDLE
59 pk11_FindRSAPubKey(PK11SlotInfo
*slot
)
61 CK_KEY_TYPE key_type
= CKK_RSA
;
62 CK_OBJECT_CLASS class_type
= CKO_PUBLIC_KEY
;
63 CK_ATTRIBUTE theTemplate
[2];
64 int template_count
= sizeof(theTemplate
)/sizeof(theTemplate
[0]);
65 CK_ATTRIBUTE
*attrs
= theTemplate
;
67 PK11_SETATTRS(attrs
,CKA_CLASS
,&class_type
,sizeof(class_type
)); attrs
++;
68 PK11_SETATTRS(attrs
,CKA_KEY_TYPE
,&key_type
,sizeof(key_type
)); attrs
++;
69 template_count
= attrs
- theTemplate
;
70 PR_ASSERT(template_count
<= sizeof(theTemplate
)/sizeof(CK_ATTRIBUTE
));
72 return pk11_FindObjectByTemplate(slot
,theTemplate
,template_count
);
76 pk11_KeyExchange(PK11SlotInfo
*slot
,CK_MECHANISM_TYPE type
,
77 CK_ATTRIBUTE_TYPE operation
, CK_FLAGS flags
,
78 PRBool isPerm
, PK11SymKey
*symKey
)
80 PK11SymKey
*newSymKey
= NULL
;
82 /* performance improvement can go here --- use a generated key at startup
83 * to generate a per token wrapping key. If it exists, use it, otherwise
84 * do a full key exchange. */
86 /* find a common Key Exchange algorithm */
88 if (PK11_DoesMechanism(symKey
->slot
, CKM_RSA_PKCS
) &&
89 PK11_DoesMechanism(slot
,CKM_RSA_PKCS
)) {
90 CK_OBJECT_HANDLE pubKeyHandle
= CK_INVALID_HANDLE
;
91 CK_OBJECT_HANDLE privKeyHandle
= CK_INVALID_HANDLE
;
92 SECKEYPublicKey
*pubKey
= NULL
;
93 SECKEYPrivateKey
*privKey
= NULL
;
95 unsigned int symKeyLength
= PK11_GetKeyLength(symKey
);
99 /* find RSA Public Key on target */
100 pubKeyHandle
= pk11_FindRSAPubKey(slot
);
101 if (pubKeyHandle
!= CK_INVALID_HANDLE
) {
102 privKeyHandle
= PK11_MatchItem(slot
,pubKeyHandle
,CKO_PRIVATE_KEY
);
105 /* if no key exists, generate a key pair */
106 if (privKeyHandle
== CK_INVALID_HANDLE
) {
107 PK11RSAGenParams rsaParams
;
109 if (symKeyLength
> 53) /* bytes */ {
110 /* we'd have to generate an RSA key pair > 512 bits long,
111 ** and that's too costly. Don't even try.
113 PORT_SetError( SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY
);
116 rsaParams
.keySizeInBits
=
117 (symKeyLength
> 21 || symKeyLength
== 0) ? 512 : 256;
118 rsaParams
.pe
= 0x10001;
119 privKey
= PK11_GenerateKeyPair(slot
,CKM_RSA_PKCS_KEY_PAIR_GEN
,
120 &rsaParams
, &pubKey
,PR_FALSE
,PR_TRUE
,symKey
->cx
);
122 /* if keys exist, build SECKEY data structures for them */
123 privKey
= PK11_MakePrivKey(slot
,nullKey
, PR_TRUE
, privKeyHandle
,
125 if (privKey
!= NULL
) {
126 pubKey
= PK11_ExtractPublicKey(slot
, rsaKey
, pubKeyHandle
);
127 if (pubKey
&& pubKey
->pkcs11Slot
) {
128 PK11_FreeSlot(pubKey
->pkcs11Slot
);
129 pubKey
->pkcs11Slot
= NULL
;
130 pubKey
->pkcs11ID
= CK_INVALID_HANDLE
;
134 if (privKey
== NULL
) goto rsa_failed
;
135 if (pubKey
== NULL
) goto rsa_failed
;
137 wrapData
.len
= SECKEY_PublicKeyStrength(pubKey
);
138 if (!wrapData
.len
) goto rsa_failed
;
139 wrapData
.data
= PORT_Alloc(wrapData
.len
);
140 if (wrapData
.data
== NULL
) goto rsa_failed
;
142 /* now wrap the keys in and out */
143 rv
= PK11_PubWrapSymKey(CKM_RSA_PKCS
, pubKey
, symKey
, &wrapData
);
144 if (rv
== SECSuccess
) {
145 newSymKey
= PK11_PubUnwrapSymKeyWithFlagsPerm(privKey
,
146 &wrapData
,type
,operation
,symKeyLength
,flags
,isPerm
);
147 /* make sure we wound up where we wanted to be! */
148 if (newSymKey
&& newSymKey
->slot
!= slot
) {
149 PK11_FreeSymKey(newSymKey
);
154 if (wrapData
.data
!= NULL
) PORT_Free(wrapData
.data
);
155 if (privKey
!= NULL
) SECKEY_DestroyPrivateKey(privKey
);
156 if (pubKey
!= NULL
) SECKEY_DestroyPublicKey(pubKey
);
160 PORT_SetError( SEC_ERROR_NO_MODULE
);