/src/nss/lib/pk11wrap/pk11kea.c
| Line | Count | Source (jump to first uncovered line) | 
| 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 | 0 | { | 
| 31 | 0 |     CK_KEY_TYPE key_type = CKK_RSA; | 
| 32 | 0 |     CK_OBJECT_CLASS class_type = CKO_PUBLIC_KEY; | 
| 33 | 0 |     CK_ATTRIBUTE theTemplate[2]; | 
| 34 | 0 |     size_t template_count = sizeof(theTemplate) / sizeof(theTemplate[0]); | 
| 35 | 0 |     CK_ATTRIBUTE *attrs = theTemplate; | 
| 36 |  | 
 | 
| 37 | 0 |     PK11_SETATTRS(attrs, CKA_CLASS, &class_type, sizeof(class_type)); | 
| 38 | 0 |     attrs++; | 
| 39 | 0 |     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &key_type, sizeof(key_type)); | 
| 40 | 0 |     attrs++; | 
| 41 | 0 |     template_count = attrs - theTemplate; | 
| 42 | 0 |     PR_ASSERT(template_count <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE)); | 
| 43 |  | 
 | 
| 44 | 0 |     return pk11_FindObjectByTemplate(slot, theTemplate, template_count); | 
| 45 | 0 | } | 
| 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 | 0 | { | 
| 52 | 0 |     PK11SymKey *newSymKey = NULL; | 
| 53 | 0 |     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 | 0 |     if (PK11_DoesMechanism(symKey->slot, CKM_RSA_PKCS) && | 
| 61 | 0 |         PK11_DoesMechanism(slot, CKM_RSA_PKCS)) { | 
| 62 | 0 |         CK_OBJECT_HANDLE pubKeyHandle = CK_INVALID_HANDLE; | 
| 63 | 0 |         CK_OBJECT_HANDLE privKeyHandle = CK_INVALID_HANDLE; | 
| 64 | 0 |         SECKEYPublicKey *pubKey = NULL; | 
| 65 | 0 |         SECKEYPrivateKey *privKey = NULL; | 
| 66 | 0 |         SECItem wrapData; | 
| 67 | 0 |         unsigned int symKeyLength = PK11_GetKeyLength(symKey); | 
| 68 |  | 
 | 
| 69 | 0 |         wrapData.data = NULL; | 
| 70 |  |  | 
| 71 |  |         /* find RSA Public Key on target */ | 
| 72 | 0 |         pubKeyHandle = pk11_FindRSAPubKey(slot); | 
| 73 | 0 |         if (pubKeyHandle != CK_INVALID_HANDLE) { | 
| 74 | 0 |             privKeyHandle = PK11_MatchItem(slot, pubKeyHandle, CKO_PRIVATE_KEY); | 
| 75 | 0 |         } | 
| 76 |  |  | 
| 77 |  |         /* if no key exists, generate a key pair */ | 
| 78 | 0 |         if (privKeyHandle == CK_INVALID_HANDLE) { | 
| 79 | 0 |             PK11RSAGenParams rsaParams; | 
| 80 |  | 
 | 
| 81 | 0 |             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 | 0 |                 PORT_SetError(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY); | 
| 86 | 0 |                 goto rsa_failed; | 
| 87 | 0 |             } | 
| 88 | 0 |             rsaParams.keySizeInBits = 1024; | 
| 89 | 0 |             rsaParams.pe = 0x10001; | 
| 90 | 0 |             privKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, | 
| 91 | 0 |                                            &rsaParams, &pubKey, PR_FALSE, PR_TRUE, symKey->cx); | 
| 92 | 0 |         } else { | 
| 93 |  |             /* if keys exist, build SECKEY data structures for them */ | 
| 94 | 0 |             privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, privKeyHandle, | 
| 95 | 0 |                                        symKey->cx); | 
| 96 | 0 |             if (privKey != NULL) { | 
| 97 | 0 |                 pubKey = PK11_ExtractPublicKey(slot, rsaKey, pubKeyHandle); | 
| 98 | 0 |                 if (pubKey && pubKey->pkcs11Slot) { | 
| 99 | 0 |                     PK11_FreeSlot(pubKey->pkcs11Slot); | 
| 100 | 0 |                     pubKey->pkcs11Slot = NULL; | 
| 101 | 0 |                     pubKey->pkcs11ID = CK_INVALID_HANDLE; | 
| 102 | 0 |                 } | 
| 103 | 0 |             } | 
| 104 | 0 |         } | 
| 105 | 0 |         if (privKey == NULL) | 
| 106 | 0 |             goto rsa_failed; | 
| 107 | 0 |         if (pubKey == NULL) | 
| 108 | 0 |             goto rsa_failed; | 
| 109 |  |  | 
| 110 | 0 |         wrapData.len = SECKEY_PublicKeyStrength(pubKey); | 
| 111 | 0 |         if (!wrapData.len) | 
| 112 | 0 |             goto rsa_failed; | 
| 113 | 0 |         wrapData.data = PORT_Alloc(wrapData.len); | 
| 114 | 0 |         if (wrapData.data == NULL) | 
| 115 | 0 |             goto rsa_failed; | 
| 116 |  |  | 
| 117 |  |         /* now wrap the keys in and out */ | 
| 118 | 0 |         rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, pubKey, symKey, &wrapData); | 
| 119 | 0 |         if (rv == SECSuccess) { | 
| 120 | 0 |             newSymKey = PK11_PubUnwrapSymKeyWithFlagsPerm(privKey, | 
| 121 | 0 |                                                           &wrapData, type, operation, | 
| 122 | 0 |                                                           symKeyLength, flags, isPerm); | 
| 123 |  |             /* make sure we wound up where we wanted to be! */ | 
| 124 | 0 |             if (newSymKey && newSymKey->slot != slot) { | 
| 125 | 0 |                 PK11_FreeSymKey(newSymKey); | 
| 126 | 0 |                 newSymKey = NULL; | 
| 127 | 0 |             } | 
| 128 | 0 |         } | 
| 129 | 0 |     rsa_failed: | 
| 130 | 0 |         if (wrapData.data != NULL) | 
| 131 | 0 |             PORT_Free(wrapData.data); | 
| 132 | 0 |         if (privKey != NULL) | 
| 133 | 0 |             SECKEY_DestroyPrivateKey(privKey); | 
| 134 | 0 |         if (pubKey != NULL) | 
| 135 | 0 |             SECKEY_DestroyPublicKey(pubKey); | 
| 136 |  | 
 | 
| 137 | 0 |         return newSymKey; | 
| 138 | 0 |     } | 
| 139 | 0 |     PORT_SetError(SEC_ERROR_NO_MODULE); | 
| 140 | 0 |     return NULL; | 
| 141 | 0 | } |