Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / security / nss / lib / pk11wrap / pk11kea.c
blob3d2a52ad5823fb9dd43c0a43dd236d01c2d72c1a
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
12 * License.
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.
21 * Contributor(s):
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
38 * Interfaces.
41 #include "seccomon.h"
42 #include "secmod.h"
43 #include "nssilock.h"
44 #include "secmodi.h"
45 #include "secmodti.h"
46 #include "pkcs11.h"
47 #include "pk11func.h"
48 #include "secitem.h"
49 #include "key.h"
50 #include "secasn1.h"
51 #include "sechash.h"
52 #include "cert.h"
53 #include "secerr.h"
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);
75 PK11SymKey *
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;
81 SECStatus rv;
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 */
87 /* RSA */
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;
94 SECItem wrapData;
95 unsigned int symKeyLength = PK11_GetKeyLength(symKey);
97 wrapData.data = NULL;
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 );
114 goto rsa_failed;
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);
121 } else {
122 /* if keys exist, build SECKEY data structures for them */
123 privKey = PK11_MakePrivKey(slot,nullKey, PR_TRUE, privKeyHandle,
124 symKey->cx);
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);
150 newSymKey = NULL;
153 rsa_failed:
154 if (wrapData.data != NULL) PORT_Free(wrapData.data);
155 if (privKey != NULL) SECKEY_DestroyPrivateKey(privKey);
156 if (pubKey != NULL) SECKEY_DestroyPublicKey(pubKey);
158 return newSymKey;
160 PORT_SetError( SEC_ERROR_NO_MODULE );
161 return NULL;