| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/ec.h" | 5 #include "components/webcrypto/algorithms/ec.h" |
| 6 | 6 |
| 7 #include <openssl/ec.h> | 7 #include <openssl/ec.h> |
| 8 #include <openssl/ec_key.h> | 8 #include <openssl/ec_key.h> |
| 9 #include <openssl/evp.h> | 9 #include <openssl/evp.h> |
| 10 #include <stddef.h> | 10 #include <stddef.h> |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 } | 104 } |
| 105 | 105 |
| 106 // Verifies that an EC key imported from PKCS8 or SPKI format is correct. | 106 // Verifies that an EC key imported from PKCS8 or SPKI format is correct. |
| 107 // This involves verifying the key validity, and the NID for the named curve. | 107 // This involves verifying the key validity, and the NID for the named curve. |
| 108 // Also removes the EC_PKEY_NO_PUBKEY flag if present. | 108 // Also removes the EC_PKEY_NO_PUBKEY flag if present. |
| 109 Status VerifyEcKeyAfterSpkiOrPkcs8Import( | 109 Status VerifyEcKeyAfterSpkiOrPkcs8Import( |
| 110 EVP_PKEY* pkey, | 110 EVP_PKEY* pkey, |
| 111 blink::WebCryptoNamedCurve expected_named_curve) { | 111 blink::WebCryptoNamedCurve expected_named_curve) { |
| 112 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 112 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 113 | 113 |
| 114 crypto::ScopedEC_KEY ec(EVP_PKEY_get1_EC_KEY(pkey)); | 114 EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey); |
| 115 if (!ec.get()) | 115 if (!ec) |
| 116 return Status::ErrorUnexpected(); | 116 return Status::ErrorUnexpected(); |
| 117 | 117 |
| 118 // When importing an ECPrivateKey, the public key is optional. If it was | 118 // When importing an ECPrivateKey, the public key is optional. If it was |
| 119 // omitted then the public key will be calculated by BoringSSL and added into | 119 // omitted then the public key will be calculated by BoringSSL and added into |
| 120 // the EC_KEY. However an encoding flag is set such that when exporting to | 120 // the EC_KEY. However an encoding flag is set such that when exporting to |
| 121 // PKCS8 format the public key is once again omitted. Remove this flag. | 121 // PKCS8 format the public key is once again omitted. Remove this flag. |
| 122 unsigned int enc_flags = EC_KEY_get_enc_flags(ec.get()); | 122 unsigned int enc_flags = EC_KEY_get_enc_flags(ec); |
| 123 enc_flags &= ~EC_PKEY_NO_PUBKEY; | 123 enc_flags &= ~EC_PKEY_NO_PUBKEY; |
| 124 EC_KEY_set_enc_flags(ec.get(), enc_flags); | 124 EC_KEY_set_enc_flags(ec, enc_flags); |
| 125 | 125 |
| 126 if (!EC_KEY_check_key(ec.get())) | 126 if (!EC_KEY_check_key(ec)) |
| 127 return Status::ErrorEcKeyInvalid(); | 127 return Status::ErrorEcKeyInvalid(); |
| 128 | 128 |
| 129 // Make sure the curve matches the expected curve name. | 129 // Make sure the curve matches the expected curve name. |
| 130 int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get())); | 130 int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); |
| 131 blink::WebCryptoNamedCurve named_curve = blink::WebCryptoNamedCurveP256; | 131 blink::WebCryptoNamedCurve named_curve = blink::WebCryptoNamedCurveP256; |
| 132 Status status = NidToWebCryptoCurve(curve_nid, &named_curve); | 132 Status status = NidToWebCryptoCurve(curve_nid, &named_curve); |
| 133 if (status.IsError()) | 133 if (status.IsError()) |
| 134 return status; | 134 return status; |
| 135 | 135 |
| 136 if (named_curve != expected_named_curve) | 136 if (named_curve != expected_named_curve) |
| 137 return Status::ErrorImportedEcKeyIncorrectCurve(); | 137 return Status::ErrorImportedEcKeyIncorrectCurve(); |
| 138 | 138 |
| 139 return Status::Success(); | 139 return Status::Success(); |
| 140 } | 140 } |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 } | 597 } |
| 598 | 598 |
| 599 // The format for JWK EC keys is given by: | 599 // The format for JWK EC keys is given by: |
| 600 // https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-36#section-6.
2 | 600 // https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-36#section-6.
2 |
| 601 Status EcAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key, | 601 Status EcAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key, |
| 602 std::vector<uint8_t>* buffer) const { | 602 std::vector<uint8_t>* buffer) const { |
| 603 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 603 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 604 | 604 |
| 605 EVP_PKEY* pkey = GetEVP_PKEY(key); | 605 EVP_PKEY* pkey = GetEVP_PKEY(key); |
| 606 | 606 |
| 607 crypto::ScopedEC_KEY ec(EVP_PKEY_get1_EC_KEY(pkey)); | 607 EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey); |
| 608 if (!ec.get()) | 608 if (!ec) |
| 609 return Status::ErrorUnexpected(); | 609 return Status::ErrorUnexpected(); |
| 610 | 610 |
| 611 // No "alg" is set for EC keys. | 611 // No "alg" is set for EC keys. |
| 612 JwkWriter jwk(std::string(), key.extractable(), key.usages(), "EC"); | 612 JwkWriter jwk(std::string(), key.extractable(), key.usages(), "EC"); |
| 613 | 613 |
| 614 // Set the crv | 614 // Set the crv |
| 615 std::string crv; | 615 std::string crv; |
| 616 Status status = | 616 Status status = |
| 617 WebCryptoCurveToJwkCrv(key.algorithm().ecParams()->namedCurve(), &crv); | 617 WebCryptoCurveToJwkCrv(key.algorithm().ecParams()->namedCurve(), &crv); |
| 618 if (status.IsError()) | 618 if (status.IsError()) |
| 619 return status; | 619 return status; |
| 620 | 620 |
| 621 int degree_bytes = GetGroupDegreeInBytes(ec.get()); | 621 int degree_bytes = GetGroupDegreeInBytes(ec); |
| 622 | 622 |
| 623 jwk.SetString("crv", crv); | 623 jwk.SetString("crv", crv); |
| 624 | 624 |
| 625 crypto::ScopedBIGNUM x; | 625 crypto::ScopedBIGNUM x; |
| 626 crypto::ScopedBIGNUM y; | 626 crypto::ScopedBIGNUM y; |
| 627 status = GetPublicKey(ec.get(), &x, &y); | 627 status = GetPublicKey(ec, &x, &y); |
| 628 if (status.IsError()) | 628 if (status.IsError()) |
| 629 return status; | 629 return status; |
| 630 | 630 |
| 631 status = WritePaddedBIGNUM("x", x.get(), degree_bytes, &jwk); | 631 status = WritePaddedBIGNUM("x", x.get(), degree_bytes, &jwk); |
| 632 if (status.IsError()) | 632 if (status.IsError()) |
| 633 return status; | 633 return status; |
| 634 | 634 |
| 635 status = WritePaddedBIGNUM("y", y.get(), degree_bytes, &jwk); | 635 status = WritePaddedBIGNUM("y", y.get(), degree_bytes, &jwk); |
| 636 if (status.IsError()) | 636 if (status.IsError()) |
| 637 return status; | 637 return status; |
| 638 | 638 |
| 639 if (key.type() == blink::WebCryptoKeyTypePrivate) { | 639 if (key.type() == blink::WebCryptoKeyTypePrivate) { |
| 640 const BIGNUM* d = EC_KEY_get0_private_key(ec.get()); | 640 const BIGNUM* d = EC_KEY_get0_private_key(ec); |
| 641 status = WritePaddedBIGNUM("d", d, degree_bytes, &jwk); | 641 status = WritePaddedBIGNUM("d", d, degree_bytes, &jwk); |
| 642 if (status.IsError()) | 642 if (status.IsError()) |
| 643 return status; | 643 return status; |
| 644 } | 644 } |
| 645 | 645 |
| 646 jwk.ToJson(buffer); | 646 jwk.ToJson(buffer); |
| 647 return Status::Success(); | 647 return Status::Success(); |
| 648 } | 648 } |
| 649 | 649 |
| 650 // TODO(eroman): Defer import to the crypto thread. http://crbug.com/430763 | 650 // TODO(eroman): Defer import to the crypto thread. http://crbug.com/430763 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 | 687 |
| 688 if (algorithm.ecParams()->namedCurve() != | 688 if (algorithm.ecParams()->namedCurve() != |
| 689 key->algorithm().ecParams()->namedCurve()) { | 689 key->algorithm().ecParams()->namedCurve()) { |
| 690 return Status::ErrorUnexpected(); | 690 return Status::ErrorUnexpected(); |
| 691 } | 691 } |
| 692 | 692 |
| 693 return Status::Success(); | 693 return Status::Success(); |
| 694 } | 694 } |
| 695 | 695 |
| 696 } // namespace webcrypto | 696 } // namespace webcrypto |
| OLD | NEW |