Chromium Code Reviews| Index: components/webcrypto/algorithms/ec.cc |
| diff --git a/components/webcrypto/algorithms/ec.cc b/components/webcrypto/algorithms/ec.cc |
| index 9aa9bfeced7760270c3f88bf2479ccf0ee48043c..c63785a45795c010807f4c3e0705cb2feaeb01a3 100644 |
| --- a/components/webcrypto/algorithms/ec.cc |
| +++ b/components/webcrypto/algorithms/ec.cc |
| @@ -19,6 +19,7 @@ |
| #include "components/webcrypto/generate_key_result.h" |
| #include "components/webcrypto/jwk.h" |
| #include "components/webcrypto/status.h" |
| +#include "crypto/auto_cbb.h" |
| #include "crypto/openssl_util.h" |
| #include "crypto/scoped_openssl_types.h" |
| #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| @@ -297,6 +298,8 @@ Status EcAlgorithm::ImportKey(blink::WebCryptoKeyFormat format, |
| blink::WebCryptoKeyUsageMask usages, |
| blink::WebCryptoKey* key) const { |
| switch (format) { |
| + case blink::WebCryptoKeyFormatRaw: |
| + return ImportKeyRaw(key_data, algorithm, extractable, usages, key); |
| case blink::WebCryptoKeyFormatPkcs8: |
| return ImportKeyPkcs8(key_data, algorithm, extractable, usages, key); |
| case blink::WebCryptoKeyFormatSpki: |
| @@ -312,6 +315,8 @@ Status EcAlgorithm::ExportKey(blink::WebCryptoKeyFormat format, |
| const blink::WebCryptoKey& key, |
| std::vector<uint8_t>* buffer) const { |
| switch (format) { |
| + case blink::WebCryptoKeyFormatRaw: |
| + return ExportKeyRaw(key, buffer); |
| case blink::WebCryptoKeyFormatPkcs8: |
| return ExportKeyPkcs8(key, buffer); |
| case blink::WebCryptoKeyFormatSpki: |
| @@ -323,6 +328,58 @@ Status EcAlgorithm::ExportKey(blink::WebCryptoKeyFormat format, |
| } |
| } |
| +Status EcAlgorithm::ImportKeyRaw(const CryptoData& key_data, |
| + const blink::WebCryptoAlgorithm& algorithm, |
| + bool extractable, |
| + blink::WebCryptoKeyUsageMask usages, |
| + blink::WebCryptoKey* key) const { |
| + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| + |
| + Status status = CheckKeyCreationUsages(all_public_key_usages_, usages); |
|
eroman
2016/08/03 17:09:06
For the record, technically this is a deviation fr
|
| + if (status.IsError()) |
| + return status; |
| + |
| + const blink::WebCryptoEcKeyImportParams* params = |
| + algorithm.ecKeyImportParams(); |
| + |
| + // Create an EC_KEY. |
| + crypto::ScopedEC_KEY ec; |
| + status = CreateEC_KEY(params->namedCurve(), &ec); |
| + if (status.IsError()) |
| + return status; |
| + |
| + crypto::ScopedEC_POINT point(EC_POINT_new(EC_KEY_get0_group(ec.get()))); |
| + if (!point.get()) |
| + return Status::OperationError(); |
| + |
| + // Convert the "raw" input from X9.62 format to an EC_POINT. |
| + if (!EC_POINT_oct2point(EC_KEY_get0_group(ec.get()), point.get(), |
| + key_data.bytes(), key_data.byte_length(), NULL)) { |
|
Ryan Sleevi
2016/08/11 19:47:07
pedantry: nullptr?
eroman
2016/08/11 21:01:09
Done.
|
| + return Status::DataError(); |
| + } |
| + |
| + // Copy the point (public key) into the EC_KEY. |
| + if (!EC_KEY_set_public_key(ec.get(), point.get())) |
| + return Status::OperationError(); |
| + |
| + // Verify the key. |
| + if (!EC_KEY_check_key(ec.get())) |
| + return Status::ErrorEcKeyInvalid(); |
| + |
| + // Wrap the EC_KEY into an EVP_PKEY. |
| + crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
| + if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get())) |
|
davidben
2016/08/11 19:51:30
[We really should make EVP_PKEY_new_EC_KEY functio
eroman
2016/08/11 21:01:09
Acknowledged.
|
| + return Status::OperationError(); |
| + |
| + blink::WebCryptoKeyAlgorithm key_algorithm = |
| + blink::WebCryptoKeyAlgorithm::createEc(algorithm.id(), |
| + params->namedCurve()); |
| + |
| + // Wrap the EVP_PKEY into a WebCryptoKey |
| + return CreateWebCryptoPublicKey(std::move(pkey), key_algorithm, extractable, |
| + usages, key); |
| +} |
| + |
| Status EcAlgorithm::ImportKeyPkcs8(const CryptoData& key_data, |
| const blink::WebCryptoAlgorithm& algorithm, |
| bool extractable, |
| @@ -487,6 +544,36 @@ Status EcAlgorithm::ImportKeyJwk(const CryptoData& key_data, |
| usages, key); |
| } |
| +Status EcAlgorithm::ExportKeyRaw(const blink::WebCryptoKey& key, |
| + std::vector<uint8_t>* buffer) const { |
| + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| + |
| + if (key.type() != blink::WebCryptoKeyTypePublic) |
| + return Status::ErrorUnexpectedKeyType(); |
| + |
| + EVP_PKEY* pkey = GetEVP_PKEY(key); |
| + |
| + crypto::ScopedEC_KEY ec(EVP_PKEY_get1_EC_KEY(pkey)); |
|
davidben
2016/08/11 19:51:30
There's also EVP_PKEY_get0_EC_KEY which does the s
eroman
2016/08/11 21:01:09
Done.
|
| + if (!ec.get()) |
| + return Status::ErrorUnexpected(); |
| + |
| + // Serialize the public key as an uncompressed point in X9.62 form. |
|
eroman
2016/08/03 17:09:06
For the record, this is an interpretation on my pa
|
| + uint8_t* raw; |
| + size_t raw_len; |
| + crypto::AutoCBB cbb; |
| + if (!CBB_init(cbb.get(), 0) || |
| + !EC_POINT_point2cbb(cbb.get(), EC_KEY_get0_group(ec.get()), |
| + EC_KEY_get0_public_key(ec.get()), |
| + POINT_CONVERSION_UNCOMPRESSED, nullptr) || |
| + !CBB_finish(cbb.get(), &raw, &raw_len)) { |
| + return Status::OperationError(); |
| + } |
| + buffer->assign(raw, raw + raw_len); |
| + OPENSSL_free(raw); |
| + |
| + return Status::Success(); |
| +} |
| + |
| Status EcAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key, |
| std::vector<uint8_t>* buffer) const { |
| if (key.type() != blink::WebCryptoKeyTypePrivate) |