| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/webcrypto/blink_key_handle.h" |
| |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "components/webcrypto/crypto_data.h" |
| #include "components/webcrypto/status.h" |
| #include "third_party/boringssl/src/include/openssl/evp.h" |
| |
| namespace webcrypto { |
| |
| namespace { |
| |
| class SymKey; |
| class AsymKey; |
| |
| // Base class for wrapping OpenSSL keys in a type that can be passed to |
| // Blink (blink::WebCryptoKeyHandle). |
| // |
| // In addition to the key's internal OpenSSL representation (EVP_PKEY or just |
| // raw bytes), each key maintains a copy of its serialized form in either |
| // 'raw', 'pkcs8', or 'spki' format. This is to allow structured cloning of |
| // keys to be done synchronously from the target Blink thread, without having to |
| // lock access to the key throughout the code. |
| // |
| // TODO(eroman): Should be able to do the key export needed for structured |
| // clone synchronously. |
| class Key : public blink::WebCryptoKeyHandle { |
| public: |
| explicit Key(const CryptoData& serialized_key_data) |
| : serialized_key_data_( |
| serialized_key_data.bytes(), |
| serialized_key_data.bytes() + serialized_key_data.byte_length()) {} |
| |
| ~Key() override {} |
| |
| // Helpers to add some safety to casting. |
| virtual SymKey* AsSymKey() { return nullptr; } |
| virtual AsymKey* AsAsymKey() { return nullptr; } |
| |
| const std::vector<uint8_t>& serialized_key_data() const { |
| return serialized_key_data_; |
| } |
| |
| private: |
| const std::vector<uint8_t> serialized_key_data_; |
| }; |
| |
| class SymKey : public Key { |
| public: |
| explicit SymKey(const CryptoData& raw_key_data) : Key(raw_key_data) {} |
| |
| SymKey* AsSymKey() override { return this; } |
| |
| const std::vector<uint8_t>& raw_key_data() const { |
| return serialized_key_data(); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SymKey); |
| }; |
| |
| class AsymKey : public Key { |
| public: |
| // After construction the |pkey| should NOT be mutated. |
| AsymKey(bssl::UniquePtr<EVP_PKEY> pkey, |
| const std::vector<uint8_t>& serialized_key_data) |
| : Key(CryptoData(serialized_key_data)), pkey_(std::move(pkey)) {} |
| |
| AsymKey* AsAsymKey() override { return this; } |
| |
| // The caller should NOT mutate this EVP_PKEY. |
| EVP_PKEY* pkey() { return pkey_.get(); } |
| |
| private: |
| bssl::UniquePtr<EVP_PKEY> pkey_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AsymKey); |
| }; |
| |
| Key* GetKey(const blink::WebCryptoKey& key) { |
| return reinterpret_cast<Key*>(key.handle()); |
| } |
| |
| } // namespace |
| |
| const std::vector<uint8_t>& GetSymmetricKeyData( |
| const blink::WebCryptoKey& key) { |
| DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| return GetKey(key)->AsSymKey()->raw_key_data(); |
| } |
| |
| EVP_PKEY* GetEVP_PKEY(const blink::WebCryptoKey& key) { |
| DCHECK_NE(blink::WebCryptoKeyTypeSecret, key.type()); |
| return GetKey(key)->AsAsymKey()->pkey(); |
| } |
| |
| const std::vector<uint8_t>& GetSerializedKeyData( |
| const blink::WebCryptoKey& key) { |
| return GetKey(key)->serialized_key_data(); |
| } |
| |
| blink::WebCryptoKeyHandle* CreateSymmetricKeyHandle( |
| const CryptoData& key_bytes) { |
| return new SymKey(key_bytes); |
| } |
| |
| blink::WebCryptoKeyHandle* CreateAsymmetricKeyHandle( |
| bssl::UniquePtr<EVP_PKEY> pkey, |
| const std::vector<uint8_t>& serialized_key_data) { |
| return new AsymKey(std::move(pkey), serialized_key_data); |
| } |
| |
| } // namespace webcrypto |