| 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 <openssl/ec.h> | 5 #include <openssl/ec.h> |
| 6 #include <openssl/ecdh.h> | 6 #include <openssl/ecdh.h> |
| 7 #include <openssl/evp.h> | 7 #include <openssl/evp.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 if (public_key.algorithm().id() != blink::WebCryptoAlgorithmIdEcdh) | 72 if (public_key.algorithm().id() != blink::WebCryptoAlgorithmIdEcdh) |
| 73 return Status::ErrorEcdhPublicKeyWrongAlgorithm(); | 73 return Status::ErrorEcdhPublicKeyWrongAlgorithm(); |
| 74 | 74 |
| 75 // The public and private keys come from different key pairs, however their | 75 // The public and private keys come from different key pairs, however their |
| 76 // curves must match. | 76 // curves must match. |
| 77 if (public_key.algorithm().ecParams()->namedCurve() != | 77 if (public_key.algorithm().ecParams()->namedCurve() != |
| 78 base_key.algorithm().ecParams()->namedCurve()) { | 78 base_key.algorithm().ecParams()->namedCurve()) { |
| 79 return Status::ErrorEcdhCurveMismatch(); | 79 return Status::ErrorEcdhCurveMismatch(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 crypto::ScopedEC_KEY public_key_ec( | 82 EC_KEY* public_key_ec = EVP_PKEY_get0_EC_KEY(GetEVP_PKEY(public_key)); |
| 83 EVP_PKEY_get1_EC_KEY(GetEVP_PKEY(public_key))); | |
| 84 | 83 |
| 85 const EC_POINT* public_key_point = | 84 const EC_POINT* public_key_point = EC_KEY_get0_public_key(public_key_ec); |
| 86 EC_KEY_get0_public_key(public_key_ec.get()); | |
| 87 | 85 |
| 88 crypto::ScopedEC_KEY private_key_ec( | 86 EC_KEY* private_key_ec = EVP_PKEY_get0_EC_KEY(GetEVP_PKEY(base_key)); |
| 89 EVP_PKEY_get1_EC_KEY(GetEVP_PKEY(base_key))); | |
| 90 | 87 |
| 91 // The size of the shared secret is the field size in bytes (rounded up). | 88 // The size of the shared secret is the field size in bytes (rounded up). |
| 92 // Note that, if rounding was required, the most significant bits of the | 89 // Note that, if rounding was required, the most significant bits of the |
| 93 // secret are zero. So for P-521, the maximum length is 528 bits, not 521. | 90 // secret are zero. So for P-521, the maximum length is 528 bits, not 521. |
| 94 int field_size_bytes = NumBitsToBytes( | 91 int field_size_bytes = |
| 95 EC_GROUP_get_degree(EC_KEY_get0_group(private_key_ec.get()))); | 92 NumBitsToBytes(EC_GROUP_get_degree(EC_KEY_get0_group(private_key_ec))); |
| 96 | 93 |
| 97 // If a desired key length was not specified, default to the field size | 94 // If a desired key length was not specified, default to the field size |
| 98 // (rounded up to nearest byte). | 95 // (rounded up to nearest byte). |
| 99 unsigned int length_bits = | 96 unsigned int length_bits = |
| 100 has_optional_length_bits ? optional_length_bits : field_size_bytes * 8; | 97 has_optional_length_bits ? optional_length_bits : field_size_bytes * 8; |
| 101 | 98 |
| 102 // Short-circuit when deriving an empty key. | 99 // Short-circuit when deriving an empty key. |
| 103 // TODO(eroman): ECDH_compute_key() is not happy when given a NULL output. | 100 // TODO(eroman): ECDH_compute_key() is not happy when given a NULL output. |
| 104 // http://crbug.com/464194. | 101 // http://crbug.com/464194. |
| 105 if (length_bits == 0) { | 102 if (length_bits == 0) { |
| 106 derived_bytes->clear(); | 103 derived_bytes->clear(); |
| 107 return Status::Success(); | 104 return Status::Success(); |
| 108 } | 105 } |
| 109 | 106 |
| 110 if (length_bits > static_cast<unsigned int>(field_size_bytes * 8)) | 107 if (length_bits > static_cast<unsigned int>(field_size_bytes * 8)) |
| 111 return Status::ErrorEcdhLengthTooBig(field_size_bytes * 8); | 108 return Status::ErrorEcdhLengthTooBig(field_size_bytes * 8); |
| 112 | 109 |
| 113 // Resize to target length in bytes (BoringSSL can operate on a shorter | 110 // Resize to target length in bytes (BoringSSL can operate on a shorter |
| 114 // buffer than field_size_bytes). | 111 // buffer than field_size_bytes). |
| 115 derived_bytes->resize(NumBitsToBytes(length_bits)); | 112 derived_bytes->resize(NumBitsToBytes(length_bits)); |
| 116 | 113 |
| 117 int result = ECDH_compute_key(derived_bytes->data(), derived_bytes->size(), | 114 int result = ECDH_compute_key(derived_bytes->data(), derived_bytes->size(), |
| 118 public_key_point, private_key_ec.get(), 0); | 115 public_key_point, private_key_ec, 0); |
| 119 if (result < 0 || static_cast<size_t>(result) != derived_bytes->size()) | 116 if (result < 0 || static_cast<size_t>(result) != derived_bytes->size()) |
| 120 return Status::OperationError(); | 117 return Status::OperationError(); |
| 121 | 118 |
| 122 TruncateToBitLength(length_bits, derived_bytes); | 119 TruncateToBitLength(length_bits, derived_bytes); |
| 123 return Status::Success(); | 120 return Status::Success(); |
| 124 } | 121 } |
| 125 }; | 122 }; |
| 126 | 123 |
| 127 } // namespace | 124 } // namespace |
| 128 | 125 |
| 129 std::unique_ptr<AlgorithmImplementation> CreateEcdhImplementation() { | 126 std::unique_ptr<AlgorithmImplementation> CreateEcdhImplementation() { |
| 130 return base::WrapUnique(new EcdhImplementation); | 127 return base::WrapUnique(new EcdhImplementation); |
| 131 } | 128 } |
| 132 | 129 |
| 133 } // namespace webcrypto | 130 } // namespace webcrypto |
| OLD | NEW |