security/nss/lib/pk11wrap/pk11kea.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial