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