hkdf.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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 <stdint.h>
  5. #include <memory>
  6. #include "components/webcrypto/algorithm_implementation.h"
  7. #include "components/webcrypto/algorithms/secret_key_util.h"
  8. #include "components/webcrypto/algorithms/util.h"
  9. #include "components/webcrypto/blink_key_handle.h"
  10. #include "components/webcrypto/status.h"
  11. #include "crypto/openssl_util.h"
  12. #include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
  13. #include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
  14. #include "third_party/boringssl/src/include/openssl/err.h"
  15. #include "third_party/boringssl/src/include/openssl/hkdf.h"
  16. namespace webcrypto {
  17. namespace {
  18. const blink::WebCryptoKeyUsageMask kValidUsages =
  19. blink::kWebCryptoKeyUsageDeriveKey | blink::kWebCryptoKeyUsageDeriveBits;
  20. class HkdfImplementation : public AlgorithmImplementation {
  21. public:
  22. HkdfImplementation() {}
  23. Status ImportKey(blink::WebCryptoKeyFormat format,
  24. base::span<const uint8_t> key_data,
  25. const blink::WebCryptoAlgorithm& algorithm,
  26. bool extractable,
  27. blink::WebCryptoKeyUsageMask usages,
  28. blink::WebCryptoKey* key) const override {
  29. switch (format) {
  30. case blink::kWebCryptoKeyFormatRaw:
  31. return ImportKeyRaw(key_data, algorithm, extractable, usages, key);
  32. default:
  33. return Status::ErrorUnsupportedImportKeyFormat();
  34. }
  35. }
  36. Status ImportKeyRaw(base::span<const uint8_t> key_data,
  37. const blink::WebCryptoAlgorithm& algorithm,
  38. bool extractable,
  39. blink::WebCryptoKeyUsageMask usages,
  40. blink::WebCryptoKey* key) const {
  41. Status status = CheckKeyCreationUsages(kValidUsages, usages);
  42. if (status.IsError())
  43. return status;
  44. if (extractable)
  45. return Status::ErrorImportExtractableKdfKey();
  46. return CreateWebCryptoSecretKey(
  47. key_data,
  48. blink::WebCryptoKeyAlgorithm::CreateWithoutParams(
  49. blink::kWebCryptoAlgorithmIdHkdf),
  50. extractable, usages, key);
  51. }
  52. Status DeriveBits(const blink::WebCryptoAlgorithm& algorithm,
  53. const blink::WebCryptoKey& base_key,
  54. bool has_optional_length_bits,
  55. unsigned int optional_length_bits,
  56. std::vector<uint8_t>* derived_bytes) const override {
  57. crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
  58. if (!has_optional_length_bits)
  59. return Status::ErrorHkdfDeriveBitsLengthNotSpecified();
  60. if (optional_length_bits % 8)
  61. return Status::ErrorHkdfLengthNotWholeByte();
  62. const blink::WebCryptoHkdfParams* params = algorithm.HkdfParams();
  63. const EVP_MD* digest_algorithm = GetDigest(params->GetHash());
  64. if (!digest_algorithm)
  65. return Status::ErrorUnsupported();
  66. // Size output to fit length
  67. unsigned int derived_bytes_len = optional_length_bits / 8;
  68. derived_bytes->resize(derived_bytes_len);
  69. // Algorithm dispatch checks that the algorithm in |base_key| matches
  70. // |algorithm|.
  71. const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(base_key);
  72. if (!HKDF(derived_bytes->data(), derived_bytes_len, digest_algorithm,
  73. raw_key.data(), raw_key.size(), params->Salt().data(),
  74. params->Salt().size(), params->Info().data(),
  75. params->Info().size())) {
  76. uint32_t error = ERR_get_error();
  77. if (ERR_GET_LIB(error) == ERR_LIB_HKDF &&
  78. ERR_GET_REASON(error) == HKDF_R_OUTPUT_TOO_LARGE) {
  79. return Status::ErrorHkdfLengthTooLong();
  80. }
  81. return Status::OperationError();
  82. }
  83. return Status::Success();
  84. }
  85. Status DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
  86. blink::WebCryptoKeyType type,
  87. bool extractable,
  88. blink::WebCryptoKeyUsageMask usages,
  89. base::span<const uint8_t> key_data,
  90. blink::WebCryptoKey* key) const override {
  91. if (algorithm.ParamsType() != blink::kWebCryptoKeyAlgorithmParamsTypeNone ||
  92. type != blink::kWebCryptoKeyTypeSecret)
  93. return Status::ErrorUnexpected();
  94. // NOTE: Unlike ImportKeyRaw(), this does not enforce extractable==false.
  95. // This is intentional. Although keys cannot currently be created with
  96. // extractable==true, earlier implementations permitted this, so
  97. // de-serialization by structured clone should not reject them.
  98. return CreateWebCryptoSecretKey(key_data, algorithm, extractable, usages,
  99. key);
  100. }
  101. Status GetKeyLength(const blink::WebCryptoAlgorithm& key_length_algorithm,
  102. bool* has_length_bits,
  103. unsigned int* length_bits) const override {
  104. *has_length_bits = false;
  105. return Status::Success();
  106. }
  107. };
  108. } // namespace
  109. std::unique_ptr<AlgorithmImplementation> CreateHkdfImplementation() {
  110. return std::make_unique<HkdfImplementation>();
  111. }
  112. } // namespace webcrypto