1f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Copyright 2015 The Chromium Authors. All rights reserved. 2f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be 3f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// found in the LICENSE file. 4f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 5f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "crypto/nss_key_util.h" 6f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 7f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <cryptohi.h> 8f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <keyhi.h> 9f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <pk11pub.h> 100c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez#include <secmod.h> 1124854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko#include <stdint.h> 12f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 1394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory> 1494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 15f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/logging.h" 16f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "crypto/nss_util.h" 17f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "crypto/nss_util_internal.h" 18f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 19f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace crypto { 20f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 21f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace { 22f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 23f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkostruct PublicKeyInfoDeleter { 24f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko inline void operator()(CERTSubjectPublicKeyInfo* spki) { 25f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECKEY_DestroySubjectPublicKeyInfo(spki); 26f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 27f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}; 28f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 2994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chaveztypedef std::unique_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter> 30f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedPublicKeyInfo; 31f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 32f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing 33f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// the CKA_ID of that public key or nullptr on error. 34f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoScopedSECItem MakeIDFromSPKI(const std::vector<uint8_t>& input) { 35f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // First, decode and save the public key. 36f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECItem key_der; 37f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko key_der.type = siBuffer; 3824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko key_der.data = const_cast<unsigned char*>(input.data()); 39f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko key_der.len = input.size(); 40f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 41f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der)); 42f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (!spki) 43f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return nullptr; 44f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 45f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get())); 46f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (!result) 47f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return nullptr; 48f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 49f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA keys are 50f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // supported. 51f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (SECKEY_GetPublicKeyType(result.get()) != rsaKey) 52f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return nullptr; 53f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 54f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return ScopedSECItem(PK11_MakeIDFromPubKey(&result->u.rsa.modulus)); 55f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 56f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 57f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} // namespace 58f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 59f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool GenerateRSAKeyPairNSS(PK11SlotInfo* slot, 60f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko uint16_t num_bits, 61f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko bool permanent, 62f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedSECKEYPublicKey* public_key, 63f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedSECKEYPrivateKey* private_key) { 64f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko DCHECK(slot); 65f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 66f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko PK11RSAGenParams param; 67f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko param.keySizeInBits = num_bits; 68f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko param.pe = 65537L; 69f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECKEYPublicKey* public_key_raw = nullptr; 70f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko private_key->reset(PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, 71f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ¶m, &public_key_raw, permanent, 72f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko permanent /* sensitive */, nullptr)); 73f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (!*private_key) 74f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return false; 75f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 76f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko public_key->reset(public_key_raw); 77f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return true; 78f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 79f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 80f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo( 81f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko PK11SlotInfo* slot, 82f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko const std::vector<uint8_t>& input, 83f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko bool permanent) { 84f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko DCHECK(slot); 85f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 86f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); 87f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko DCHECK(arena); 88f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 89f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // Excess data is illegal, but NSS silently accepts it, so first ensure that 90f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // |input| consists of a single ASN.1 element. 91f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECItem input_item; 9224854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko input_item.data = const_cast<unsigned char*>(input.data()); 93f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko input_item.len = input.size(); 94f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECItem der_private_key_info; 95f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECStatus rv = 96f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info, 97f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SEC_ASN1_GET(SEC_AnyTemplate), &input_item); 98f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (rv != SECSuccess) 99f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return nullptr; 100f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 101f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // Allow the private key to be used for key unwrapping, data decryption, 102f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // and signature generation. 103f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko const unsigned int key_usage = 104f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE; 105f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECKEYPrivateKey* key_raw = nullptr; 106f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( 107f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko slot, &der_private_key_info, nullptr, nullptr, permanent, 108f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko permanent /* sensitive */, key_usage, &key_raw, nullptr); 109f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (rv != SECSuccess) 110f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return nullptr; 111f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return ScopedSECKEYPrivateKey(key_raw); 112f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 113f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 114f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo( 115f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko const std::vector<uint8_t>& input) { 116f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko EnsureNSSInit(); 117f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 118f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedSECItem cka_id(MakeIDFromSPKI(input)); 119f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (!cka_id) 120f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return nullptr; 121f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 122f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // Search all slots in all modules for the key with the given ID. 123f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko AutoSECMODListReadLock auto_lock; 124f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko const SECMODModuleList* head = SECMOD_GetDefaultModuleList(); 125f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko for (const SECMODModuleList* item = head; item != nullptr; 126f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko item = item->next) { 127f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko int slot_count = item->module->loaded ? item->module->slotCount : 0; 128f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko for (int i = 0; i < slot_count; i++) { 129f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // Look for the key in slot |i|. 130f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedSECKEYPrivateKey key( 131f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr)); 132f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (key) 13324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko return key; 134f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 135f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 136f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 137f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko // The key wasn't found in any module. 138f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return nullptr; 139f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 140f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 141f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot( 142f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko const std::vector<uint8_t>& input, 143f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko PK11SlotInfo* slot) { 144f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko DCHECK(slot); 145f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 146f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko ScopedSECItem cka_id(MakeIDFromSPKI(input)); 147f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (!cka_id) 148f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return nullptr; 149f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 150f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return ScopedSECKEYPrivateKey( 151f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr)); 152f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 153f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 154f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} // namespace crypto 155