Wed, 31 Dec 2014 06:09:35 +0100
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 |