1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11kea.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,131 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * This file implements the Symkey wrapper and the PKCS context 1.9 + * Interfaces. 1.10 + */ 1.11 + 1.12 +#include "seccomon.h" 1.13 +#include "secmod.h" 1.14 +#include "nssilock.h" 1.15 +#include "secmodi.h" 1.16 +#include "secmodti.h" 1.17 +#include "pkcs11.h" 1.18 +#include "pk11func.h" 1.19 +#include "secitem.h" 1.20 +#include "key.h" 1.21 +#include "secasn1.h" 1.22 +#include "sechash.h" 1.23 +#include "cert.h" 1.24 +#include "secerr.h" 1.25 + 1.26 +/* 1.27 + * find an RSA public key on a card 1.28 + */ 1.29 +static CK_OBJECT_HANDLE 1.30 +pk11_FindRSAPubKey(PK11SlotInfo *slot) 1.31 +{ 1.32 + CK_KEY_TYPE key_type = CKK_RSA; 1.33 + CK_OBJECT_CLASS class_type = CKO_PUBLIC_KEY; 1.34 + CK_ATTRIBUTE theTemplate[2]; 1.35 + int template_count = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.36 + CK_ATTRIBUTE *attrs = theTemplate; 1.37 + 1.38 + PK11_SETATTRS(attrs,CKA_CLASS,&class_type,sizeof(class_type)); attrs++; 1.39 + PK11_SETATTRS(attrs,CKA_KEY_TYPE,&key_type,sizeof(key_type)); attrs++; 1.40 + template_count = attrs - theTemplate; 1.41 + PR_ASSERT(template_count <= sizeof(theTemplate)/sizeof(CK_ATTRIBUTE)); 1.42 + 1.43 + return pk11_FindObjectByTemplate(slot,theTemplate,template_count); 1.44 +} 1.45 + 1.46 +PK11SymKey * 1.47 +pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 1.48 + CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, 1.49 + PRBool isPerm, PK11SymKey *symKey) 1.50 +{ 1.51 + PK11SymKey *newSymKey = NULL; 1.52 + SECStatus rv; 1.53 + /* performance improvement can go here --- use a generated key at startup 1.54 + * to generate a per token wrapping key. If it exists, use it, otherwise 1.55 + * do a full key exchange. */ 1.56 + 1.57 + /* find a common Key Exchange algorithm */ 1.58 + /* RSA */ 1.59 + if (PK11_DoesMechanism(symKey->slot, CKM_RSA_PKCS) && 1.60 + PK11_DoesMechanism(slot,CKM_RSA_PKCS)) { 1.61 + CK_OBJECT_HANDLE pubKeyHandle = CK_INVALID_HANDLE; 1.62 + CK_OBJECT_HANDLE privKeyHandle = CK_INVALID_HANDLE; 1.63 + SECKEYPublicKey *pubKey = NULL; 1.64 + SECKEYPrivateKey *privKey = NULL; 1.65 + SECItem wrapData; 1.66 + unsigned int symKeyLength = PK11_GetKeyLength(symKey); 1.67 + 1.68 + wrapData.data = NULL; 1.69 + 1.70 + /* find RSA Public Key on target */ 1.71 + pubKeyHandle = pk11_FindRSAPubKey(slot); 1.72 + if (pubKeyHandle != CK_INVALID_HANDLE) { 1.73 + privKeyHandle = PK11_MatchItem(slot,pubKeyHandle,CKO_PRIVATE_KEY); 1.74 + } 1.75 + 1.76 + /* if no key exists, generate a key pair */ 1.77 + if (privKeyHandle == CK_INVALID_HANDLE) { 1.78 + PK11RSAGenParams rsaParams; 1.79 + 1.80 + if (symKeyLength > 53) /* bytes */ { 1.81 + /* we'd have to generate an RSA key pair > 512 bits long, 1.82 + ** and that's too costly. Don't even try. 1.83 + */ 1.84 + PORT_SetError( SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY ); 1.85 + goto rsa_failed; 1.86 + } 1.87 + rsaParams.keySizeInBits = 1.88 + (symKeyLength > 21 || symKeyLength == 0) ? 512 : 256; 1.89 + rsaParams.pe = 0x10001; 1.90 + privKey = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN, 1.91 + &rsaParams, &pubKey,PR_FALSE,PR_TRUE,symKey->cx); 1.92 + } else { 1.93 + /* if keys exist, build SECKEY data structures for them */ 1.94 + privKey = PK11_MakePrivKey(slot,nullKey, PR_TRUE, privKeyHandle, 1.95 + symKey->cx); 1.96 + if (privKey != NULL) { 1.97 + pubKey = PK11_ExtractPublicKey(slot, rsaKey, pubKeyHandle); 1.98 + if (pubKey && pubKey->pkcs11Slot) { 1.99 + PK11_FreeSlot(pubKey->pkcs11Slot); 1.100 + pubKey->pkcs11Slot = NULL; 1.101 + pubKey->pkcs11ID = CK_INVALID_HANDLE; 1.102 + } 1.103 + } 1.104 + } 1.105 + if (privKey == NULL) goto rsa_failed; 1.106 + if (pubKey == NULL) goto rsa_failed; 1.107 + 1.108 + wrapData.len = SECKEY_PublicKeyStrength(pubKey); 1.109 + if (!wrapData.len) goto rsa_failed; 1.110 + wrapData.data = PORT_Alloc(wrapData.len); 1.111 + if (wrapData.data == NULL) goto rsa_failed; 1.112 + 1.113 + /* now wrap the keys in and out */ 1.114 + rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, pubKey, symKey, &wrapData); 1.115 + if (rv == SECSuccess) { 1.116 + newSymKey = PK11_PubUnwrapSymKeyWithFlagsPerm(privKey, 1.117 + &wrapData,type,operation,symKeyLength,flags,isPerm); 1.118 + /* make sure we wound up where we wanted to be! */ 1.119 + if (newSymKey && newSymKey->slot != slot) { 1.120 + PK11_FreeSymKey(newSymKey); 1.121 + newSymKey = NULL; 1.122 + } 1.123 + } 1.124 +rsa_failed: 1.125 + if (wrapData.data != NULL) PORT_Free(wrapData.data); 1.126 + if (privKey != NULL) SECKEY_DestroyPrivateKey(privKey); 1.127 + if (pubKey != NULL) SECKEY_DestroyPublicKey(pubKey); 1.128 + 1.129 + return newSymKey; 1.130 + } 1.131 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.132 + return NULL; 1.133 +} 1.134 +