nss_key_util.cc 6.1 KB

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