aes_kw.cc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Copyright 2014 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 <stddef.h>
  5. #include <stdint.h>
  6. #include <memory>
  7. #include <vector>
  8. #include "base/location.h"
  9. #include "base/numerics/safe_math.h"
  10. #include "components/webcrypto/algorithms/aes.h"
  11. #include "components/webcrypto/blink_key_handle.h"
  12. #include "components/webcrypto/status.h"
  13. #include "crypto/openssl_util.h"
  14. #include "third_party/boringssl/src/include/openssl/aes.h"
  15. namespace webcrypto {
  16. namespace {
  17. class AesKwImplementation : public AesAlgorithm {
  18. public:
  19. AesKwImplementation()
  20. : AesAlgorithm(blink::kWebCryptoKeyUsageWrapKey |
  21. blink::kWebCryptoKeyUsageUnwrapKey,
  22. "KW") {}
  23. Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
  24. const blink::WebCryptoKey& key,
  25. base::span<const uint8_t> data,
  26. std::vector<uint8_t>* buffer) const override {
  27. crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
  28. // These length checks are done in order to give a more specific
  29. // error. These are not required for correctness.
  30. if (data.size() < 16)
  31. return Status::ErrorDataTooSmall();
  32. if (data.size() % 8)
  33. return Status::ErrorInvalidAesKwDataLength();
  34. // Key import validates key sizes, so the bits computation will not
  35. // overflow.
  36. const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key);
  37. AES_KEY aes_key;
  38. if (AES_set_encrypt_key(raw_key.data(),
  39. static_cast<unsigned>(raw_key.size() * 8),
  40. &aes_key) < 0) {
  41. return Status::OperationError();
  42. }
  43. // Key wrap's overhead is 8 bytes.
  44. base::CheckedNumeric<size_t> length(data.size());
  45. length += 8;
  46. if (!length.IsValid())
  47. return Status::ErrorDataTooLarge();
  48. buffer->resize(length.ValueOrDie());
  49. if (AES_wrap_key(&aes_key, nullptr /* default IV */, buffer->data(),
  50. data.data(), data.size()) < 0) {
  51. return Status::OperationError();
  52. }
  53. return Status::Success();
  54. }
  55. Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
  56. const blink::WebCryptoKey& key,
  57. base::span<const uint8_t> data,
  58. std::vector<uint8_t>* buffer) const override {
  59. crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
  60. // These length checks are done in order to give a more specific
  61. // error. These are not required for correctness.
  62. if (data.size() < 24)
  63. return Status::ErrorDataTooSmall();
  64. if (data.size() % 8)
  65. return Status::ErrorInvalidAesKwDataLength();
  66. // Key import validates key sizes, so the bits computation will not
  67. // overflow.
  68. const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key);
  69. AES_KEY aes_key;
  70. if (AES_set_decrypt_key(raw_key.data(),
  71. static_cast<unsigned>(raw_key.size() * 8),
  72. &aes_key) < 0) {
  73. return Status::OperationError();
  74. }
  75. // Key wrap's overhead is 8 bytes.
  76. buffer->resize(data.size() - 8);
  77. if (AES_unwrap_key(&aes_key, nullptr /* default IV */, buffer->data(),
  78. data.data(), data.size()) < 0) {
  79. return Status::OperationError();
  80. }
  81. return Status::Success();
  82. }
  83. };
  84. } // namespace
  85. std::unique_ptr<AlgorithmImplementation> CreateAesKwImplementation() {
  86. return std::make_unique<AesKwImplementation>();
  87. }
  88. } // namespace webcrypto