| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/webcrypto/algorithms/asymmetric_key_util.h" | 5 #include "components/webcrypto/algorithms/asymmetric_key_util.h" |
| 6 | 6 |
| 7 #include <openssl/bytestring.h> | 7 #include <openssl/bytestring.h> |
| 8 #include <openssl/evp.h> | 8 #include <openssl/evp.h> |
| 9 #include <openssl/mem.h> |
| 9 #include <stdint.h> | 10 #include <stdint.h> |
| 10 #include <utility> | 11 #include <utility> |
| 11 | 12 |
| 12 #include "components/webcrypto/algorithms/util.h" | 13 #include "components/webcrypto/algorithms/util.h" |
| 13 #include "components/webcrypto/blink_key_handle.h" | 14 #include "components/webcrypto/blink_key_handle.h" |
| 14 #include "components/webcrypto/crypto_data.h" | 15 #include "components/webcrypto/crypto_data.h" |
| 15 #include "components/webcrypto/generate_key_result.h" | 16 #include "components/webcrypto/generate_key_result.h" |
| 16 #include "components/webcrypto/status.h" | 17 #include "components/webcrypto/status.h" |
| 17 #include "crypto/auto_cbb.h" | |
| 18 #include "crypto/openssl_util.h" | 18 #include "crypto/openssl_util.h" |
| 19 #include "crypto/scoped_openssl_types.h" | |
| 20 | 19 |
| 21 namespace webcrypto { | 20 namespace webcrypto { |
| 22 | 21 |
| 23 namespace { | 22 namespace { |
| 24 | 23 |
| 25 // Exports an EVP_PKEY public key to the SPKI format. | 24 // Exports an EVP_PKEY public key to the SPKI format. |
| 26 Status ExportPKeySpki(EVP_PKEY* key, std::vector<uint8_t>* buffer) { | 25 Status ExportPKeySpki(EVP_PKEY* key, std::vector<uint8_t>* buffer) { |
| 27 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 26 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 28 | 27 |
| 29 uint8_t* der; | 28 uint8_t* der; |
| 30 size_t der_len; | 29 size_t der_len; |
| 31 crypto::AutoCBB cbb; | 30 bssl::ScopedCBB cbb; |
| 32 if (!CBB_init(cbb.get(), 0) || !EVP_marshal_public_key(cbb.get(), key) || | 31 if (!CBB_init(cbb.get(), 0) || !EVP_marshal_public_key(cbb.get(), key) || |
| 33 !CBB_finish(cbb.get(), &der, &der_len)) { | 32 !CBB_finish(cbb.get(), &der, &der_len)) { |
| 34 return Status::ErrorUnexpected(); | 33 return Status::ErrorUnexpected(); |
| 35 } | 34 } |
| 36 buffer->assign(der, der + der_len); | 35 buffer->assign(der, der + der_len); |
| 37 OPENSSL_free(der); | 36 OPENSSL_free(der); |
| 38 return Status::Success(); | 37 return Status::Success(); |
| 39 } | 38 } |
| 40 | 39 |
| 41 // Exports an EVP_PKEY private key to the PKCS8 format. | 40 // Exports an EVP_PKEY private key to the PKCS8 format. |
| 42 Status ExportPKeyPkcs8(EVP_PKEY* key, std::vector<uint8_t>* buffer) { | 41 Status ExportPKeyPkcs8(EVP_PKEY* key, std::vector<uint8_t>* buffer) { |
| 43 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 42 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 44 | 43 |
| 45 // TODO(eroman): Use the OID specified by webcrypto spec. | 44 // TODO(eroman): Use the OID specified by webcrypto spec. |
| 46 // http://crbug.com/373545 | 45 // http://crbug.com/373545 |
| 47 uint8_t* der; | 46 uint8_t* der; |
| 48 size_t der_len; | 47 size_t der_len; |
| 49 crypto::AutoCBB cbb; | 48 bssl::ScopedCBB cbb; |
| 50 if (!CBB_init(cbb.get(), 0) || !EVP_marshal_private_key(cbb.get(), key) || | 49 if (!CBB_init(cbb.get(), 0) || !EVP_marshal_private_key(cbb.get(), key) || |
| 51 !CBB_finish(cbb.get(), &der, &der_len)) { | 50 !CBB_finish(cbb.get(), &der, &der_len)) { |
| 52 return Status::ErrorUnexpected(); | 51 return Status::ErrorUnexpected(); |
| 53 } | 52 } |
| 54 buffer->assign(der, der + der_len); | 53 buffer->assign(der, der + der_len); |
| 55 OPENSSL_free(der); | 54 OPENSSL_free(der); |
| 56 return Status::Success(); | 55 return Status::Success(); |
| 57 } | 56 } |
| 58 | 57 |
| 59 } // namespace | 58 } // namespace |
| 60 | 59 |
| 61 Status CreateWebCryptoPublicKey(crypto::ScopedEVP_PKEY public_key, | 60 Status CreateWebCryptoPublicKey(bssl::UniquePtr<EVP_PKEY> public_key, |
| 62 const blink::WebCryptoKeyAlgorithm& algorithm, | 61 const blink::WebCryptoKeyAlgorithm& algorithm, |
| 63 bool extractable, | 62 bool extractable, |
| 64 blink::WebCryptoKeyUsageMask usages, | 63 blink::WebCryptoKeyUsageMask usages, |
| 65 blink::WebCryptoKey* key) { | 64 blink::WebCryptoKey* key) { |
| 66 // Serialize the key at creation time so that if structured cloning is | 65 // Serialize the key at creation time so that if structured cloning is |
| 67 // requested it can be done synchronously from the Blink thread. | 66 // requested it can be done synchronously from the Blink thread. |
| 68 std::vector<uint8_t> spki_data; | 67 std::vector<uint8_t> spki_data; |
| 69 Status status = ExportPKeySpki(public_key.get(), &spki_data); | 68 Status status = ExportPKeySpki(public_key.get(), &spki_data); |
| 70 if (status.IsError()) | 69 if (status.IsError()) |
| 71 return status; | 70 return status; |
| 72 | 71 |
| 73 *key = blink::WebCryptoKey::create( | 72 *key = blink::WebCryptoKey::create( |
| 74 CreateAsymmetricKeyHandle(std::move(public_key), spki_data), | 73 CreateAsymmetricKeyHandle(std::move(public_key), spki_data), |
| 75 blink::WebCryptoKeyTypePublic, extractable, algorithm, usages); | 74 blink::WebCryptoKeyTypePublic, extractable, algorithm, usages); |
| 76 return Status::Success(); | 75 return Status::Success(); |
| 77 } | 76 } |
| 78 | 77 |
| 79 Status CreateWebCryptoPrivateKey(crypto::ScopedEVP_PKEY private_key, | 78 Status CreateWebCryptoPrivateKey(bssl::UniquePtr<EVP_PKEY> private_key, |
| 80 const blink::WebCryptoKeyAlgorithm& algorithm, | 79 const blink::WebCryptoKeyAlgorithm& algorithm, |
| 81 bool extractable, | 80 bool extractable, |
| 82 blink::WebCryptoKeyUsageMask usages, | 81 blink::WebCryptoKeyUsageMask usages, |
| 83 blink::WebCryptoKey* key) { | 82 blink::WebCryptoKey* key) { |
| 84 // Serialize the key at creation time so that if structured cloning is | 83 // Serialize the key at creation time so that if structured cloning is |
| 85 // requested it can be done synchronously from the Blink thread. | 84 // requested it can be done synchronously from the Blink thread. |
| 86 std::vector<uint8_t> pkcs8_data; | 85 std::vector<uint8_t> pkcs8_data; |
| 87 Status status = ExportPKeyPkcs8(private_key.get(), &pkcs8_data); | 86 Status status = ExportPKeyPkcs8(private_key.get(), &pkcs8_data); |
| 88 if (status.IsError()) | 87 if (status.IsError()) |
| 89 return status; | 88 return status; |
| 90 | 89 |
| 91 *key = blink::WebCryptoKey::create( | 90 *key = blink::WebCryptoKey::create( |
| 92 CreateAsymmetricKeyHandle(std::move(private_key), pkcs8_data), | 91 CreateAsymmetricKeyHandle(std::move(private_key), pkcs8_data), |
| 93 blink::WebCryptoKeyTypePrivate, extractable, algorithm, usages); | 92 blink::WebCryptoKeyTypePrivate, extractable, algorithm, usages); |
| 94 return Status::Success(); | 93 return Status::Success(); |
| 95 } | 94 } |
| 96 | 95 |
| 97 Status ImportUnverifiedPkeyFromSpki(const CryptoData& key_data, | 96 Status ImportUnverifiedPkeyFromSpki(const CryptoData& key_data, |
| 98 int expected_pkey_id, | 97 int expected_pkey_id, |
| 99 crypto::ScopedEVP_PKEY* out_pkey) { | 98 bssl::UniquePtr<EVP_PKEY>* out_pkey) { |
| 100 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 99 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 101 | 100 |
| 102 CBS cbs; | 101 CBS cbs; |
| 103 CBS_init(&cbs, key_data.bytes(), key_data.byte_length()); | 102 CBS_init(&cbs, key_data.bytes(), key_data.byte_length()); |
| 104 crypto::ScopedEVP_PKEY pkey(EVP_parse_public_key(&cbs)); | 103 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs)); |
| 105 if (!pkey || CBS_len(&cbs) != 0) | 104 if (!pkey || CBS_len(&cbs) != 0) |
| 106 return Status::DataError(); | 105 return Status::DataError(); |
| 107 | 106 |
| 108 if (EVP_PKEY_id(pkey.get()) != expected_pkey_id) | 107 if (EVP_PKEY_id(pkey.get()) != expected_pkey_id) |
| 109 return Status::DataError(); // Data did not define expected key type. | 108 return Status::DataError(); // Data did not define expected key type. |
| 110 | 109 |
| 111 *out_pkey = std::move(pkey); | 110 *out_pkey = std::move(pkey); |
| 112 return Status::Success(); | 111 return Status::Success(); |
| 113 } | 112 } |
| 114 | 113 |
| 115 Status ImportUnverifiedPkeyFromPkcs8(const CryptoData& key_data, | 114 Status ImportUnverifiedPkeyFromPkcs8(const CryptoData& key_data, |
| 116 int expected_pkey_id, | 115 int expected_pkey_id, |
| 117 crypto::ScopedEVP_PKEY* out_pkey) { | 116 bssl::UniquePtr<EVP_PKEY>* out_pkey) { |
| 118 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 117 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 119 | 118 |
| 120 CBS cbs; | 119 CBS cbs; |
| 121 CBS_init(&cbs, key_data.bytes(), key_data.byte_length()); | 120 CBS_init(&cbs, key_data.bytes(), key_data.byte_length()); |
| 122 crypto::ScopedEVP_PKEY pkey(EVP_parse_private_key(&cbs)); | 121 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs)); |
| 123 if (!pkey || CBS_len(&cbs) != 0) | 122 if (!pkey || CBS_len(&cbs) != 0) |
| 124 return Status::DataError(); | 123 return Status::DataError(); |
| 125 | 124 |
| 126 if (EVP_PKEY_id(pkey.get()) != expected_pkey_id) | 125 if (EVP_PKEY_id(pkey.get()) != expected_pkey_id) |
| 127 return Status::DataError(); // Data did not define expected key type. | 126 return Status::DataError(); // Data did not define expected key type. |
| 128 | 127 |
| 129 *out_pkey = std::move(pkey); | 128 *out_pkey = std::move(pkey); |
| 130 return Status::Success(); | 129 return Status::Success(); |
| 131 } | 130 } |
| 132 | 131 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 145 *public_usages = combined_usages & all_public_usages; | 144 *public_usages = combined_usages & all_public_usages; |
| 146 *private_usages = combined_usages & all_private_usages; | 145 *private_usages = combined_usages & all_private_usages; |
| 147 | 146 |
| 148 // NOTE: empty private_usages is allowed at this layer. Such keys will be | 147 // NOTE: empty private_usages is allowed at this layer. Such keys will be |
| 149 // rejected at a higher layer. | 148 // rejected at a higher layer. |
| 150 | 149 |
| 151 return Status::Success(); | 150 return Status::Success(); |
| 152 } | 151 } |
| 153 | 152 |
| 154 } // namespace webcrypto | 153 } // namespace webcrypto |
| OLD | NEW |