pk11kea.c (5022B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * This file implements the Symkey wrapper and the PKCS context 6 * Interfaces. 7 */ 8 9 #include <stddef.h> 10 11 #include "seccomon.h" 12 #include "secmod.h" 13 #include "nssilock.h" 14 #include "secmodi.h" 15 #include "secmodti.h" 16 #include "pkcs11.h" 17 #include "pk11func.h" 18 #include "secitem.h" 19 #include "keyhi.h" 20 #include "secasn1.h" 21 #include "sechash.h" 22 #include "cert.h" 23 #include "secerr.h" 24 25 /* 26 * find an RSA public key on a card 27 */ 28 static CK_OBJECT_HANDLE 29 pk11_FindRSAPubKey(PK11SlotInfo *slot) 30 { 31 CK_KEY_TYPE key_type = CKK_RSA; 32 CK_OBJECT_CLASS class_type = CKO_PUBLIC_KEY; 33 CK_ATTRIBUTE theTemplate[2]; 34 size_t template_count = sizeof(theTemplate) / sizeof(theTemplate[0]); 35 CK_ATTRIBUTE *attrs = theTemplate; 36 37 PK11_SETATTRS(attrs, CKA_CLASS, &class_type, sizeof(class_type)); 38 attrs++; 39 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &key_type, sizeof(key_type)); 40 attrs++; 41 template_count = attrs - theTemplate; 42 PR_ASSERT(template_count <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE)); 43 44 return pk11_FindObjectByTemplate(slot, theTemplate, template_count); 45 } 46 47 PK11SymKey * 48 pk11_KeyExchange(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 49 CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, 50 PRBool isPerm, PK11SymKey *symKey) 51 { 52 PK11SymKey *newSymKey = NULL; 53 SECStatus rv; 54 /* performance improvement can go here --- use a generated key at startup 55 * to generate a per token wrapping key. If it exists, use it, otherwise 56 * do a full key exchange. */ 57 58 /* find a common Key Exchange algorithm */ 59 /* RSA */ 60 if (PK11_DoesMechanism(symKey->slot, CKM_RSA_PKCS) && 61 PK11_DoesMechanism(slot, CKM_RSA_PKCS)) { 62 CK_OBJECT_HANDLE pubKeyHandle = CK_INVALID_HANDLE; 63 CK_OBJECT_HANDLE privKeyHandle = CK_INVALID_HANDLE; 64 SECKEYPublicKey *pubKey = NULL; 65 SECKEYPrivateKey *privKey = NULL; 66 SECItem wrapData; 67 unsigned int symKeyLength = PK11_GetKeyLength(symKey); 68 69 wrapData.data = NULL; 70 71 /* find RSA Public Key on target */ 72 pubKeyHandle = pk11_FindRSAPubKey(slot); 73 if (pubKeyHandle != CK_INVALID_HANDLE) { 74 privKeyHandle = PK11_MatchItem(slot, pubKeyHandle, CKO_PRIVATE_KEY); 75 } 76 77 /* if no key exists, generate a key pair */ 78 if (privKeyHandle == CK_INVALID_HANDLE) { 79 PK11RSAGenParams rsaParams; 80 81 if (symKeyLength > 120) /* bytes */ { 82 /* we'd have to generate an RSA key pair > 1024 bits long, 83 ** and that's too costly. Don't even try. 84 */ 85 PORT_SetError(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY); 86 goto rsa_failed; 87 } 88 rsaParams.keySizeInBits = 1024; 89 rsaParams.pe = 0x10001; 90 privKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, 91 &rsaParams, &pubKey, PR_FALSE, PR_TRUE, symKey->cx); 92 } else { 93 /* if keys exist, build SECKEY data structures for them */ 94 privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, privKeyHandle, 95 symKey->cx); 96 if (privKey != NULL) { 97 pubKey = PK11_ExtractPublicKey(slot, rsaKey, pubKeyHandle); 98 if (pubKey && pubKey->pkcs11Slot) { 99 PK11_FreeSlot(pubKey->pkcs11Slot); 100 pubKey->pkcs11Slot = NULL; 101 pubKey->pkcs11ID = CK_INVALID_HANDLE; 102 } 103 } 104 } 105 if (privKey == NULL) 106 goto rsa_failed; 107 if (pubKey == NULL) 108 goto rsa_failed; 109 110 wrapData.len = SECKEY_PublicKeyStrength(pubKey); 111 if (!wrapData.len) 112 goto rsa_failed; 113 wrapData.data = PORT_Alloc(wrapData.len); 114 if (wrapData.data == NULL) 115 goto rsa_failed; 116 117 /* now wrap the keys in and out */ 118 rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, pubKey, symKey, &wrapData); 119 if (rv == SECSuccess) { 120 newSymKey = PK11_PubUnwrapSymKeyWithFlagsPerm(privKey, 121 &wrapData, type, operation, 122 symKeyLength, flags, isPerm); 123 /* make sure we wound up where we wanted to be! */ 124 if (newSymKey && newSymKey->slot != slot) { 125 PK11_FreeSymKey(newSymKey); 126 newSymKey = NULL; 127 } 128 } 129 rsa_failed: 130 if (wrapData.data != NULL) 131 PORT_Free(wrapData.data); 132 if (privKey != NULL) 133 SECKEY_DestroyPrivateKey(privKey); 134 if (pubKey != NULL) 135 SECKEY_DestroyPublicKey(pubKey); 136 137 return newSymKey; 138 } 139 PORT_SetError(SEC_ERROR_NO_MODULE); 140 return NULL; 141 }