Chromium Code Reviews| 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/ec_key.h> | 6 #include <openssl/ec_key.h> |
| 7 #include <openssl/evp.h> | 7 #include <openssl/evp.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/stl_util.h" | |
| 11 #include "components/webcrypto/algorithm_implementation.h" | 10 #include "components/webcrypto/algorithm_implementation.h" |
| 12 #include "components/webcrypto/algorithms/ec.h" | 11 #include "components/webcrypto/algorithms/ec.h" |
| 13 #include "components/webcrypto/algorithms/util.h" | 12 #include "components/webcrypto/algorithms/util.h" |
| 14 #include "components/webcrypto/blink_key_handle.h" | 13 #include "components/webcrypto/blink_key_handle.h" |
| 15 #include "components/webcrypto/crypto_data.h" | 14 #include "components/webcrypto/crypto_data.h" |
| 16 #include "components/webcrypto/generate_key_result.h" | 15 #include "components/webcrypto/generate_key_result.h" |
| 17 #include "components/webcrypto/status.h" | 16 #include "components/webcrypto/status.h" |
| 18 #include "crypto/openssl_util.h" | 17 #include "crypto/openssl_util.h" |
| 19 #include "crypto/scoped_openssl_types.h" | 18 #include "crypto/scoped_openssl_types.h" |
| 20 #include "crypto/secure_util.h" | 19 #include "crypto/secure_util.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 | 58 |
| 60 // Formats a DER-encoded signature (ECDSA-Sig-Value as specified in RFC 3279) to | 59 // Formats a DER-encoded signature (ECDSA-Sig-Value as specified in RFC 3279) to |
| 61 // the signature format expected by WebCrypto (raw concatenated "r" and "s"). | 60 // the signature format expected by WebCrypto (raw concatenated "r" and "s"). |
| 62 // | 61 // |
| 63 // TODO(eroman): Where is the specification for WebCrypto's signature format? | 62 // TODO(eroman): Where is the specification for WebCrypto's signature format? |
| 64 Status ConvertDerSignatureToWebCryptoSignature( | 63 Status ConvertDerSignatureToWebCryptoSignature( |
| 65 EVP_PKEY* key, | 64 EVP_PKEY* key, |
| 66 std::vector<uint8_t>* signature) { | 65 std::vector<uint8_t>* signature) { |
| 67 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 66 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 68 | 67 |
| 69 const unsigned char* der_data = vector_as_array(signature); | |
| 70 crypto::ScopedECDSA_SIG ecdsa_sig( | 68 crypto::ScopedECDSA_SIG ecdsa_sig( |
| 71 d2i_ECDSA_SIG(NULL, &der_data, static_cast<long>(signature->size()))); | 69 ECDSA_SIG_from_bytes(signature->data(), signature->size())); |
|
davidben
2015/11/19 23:57:21
NB: This line is different, because d2i_ECDSA_SIG
| |
| 72 if (!ecdsa_sig.get()) | 70 if (!ecdsa_sig.get()) |
| 73 return Status::ErrorUnexpected(); | 71 return Status::ErrorUnexpected(); |
| 74 | 72 |
| 75 // |der_data| is updated to point to past the end of the DER structure. | |
| 76 if (der_data != vector_as_array(signature) + signature->size()) | |
| 77 return Status::ErrorUnexpected(); | |
| 78 | |
| 79 // Determine the maximum length of r and s. | 73 // Determine the maximum length of r and s. |
| 80 size_t order_size_bytes; | 74 size_t order_size_bytes; |
| 81 Status status = GetEcGroupOrderSize(key, &order_size_bytes); | 75 Status status = GetEcGroupOrderSize(key, &order_size_bytes); |
| 82 if (status.IsError()) | 76 if (status.IsError()) |
| 83 return status; | 77 return status; |
| 84 | 78 |
| 85 signature->resize(order_size_bytes * 2); | 79 signature->resize(order_size_bytes * 2); |
| 86 | 80 |
| 87 if (!BN_bn2bin_padded(vector_as_array(signature), order_size_bytes, | 81 if (!BN_bn2bin_padded(signature->data(), order_size_bytes, |
| 88 ecdsa_sig.get()->r)) { | 82 ecdsa_sig.get()->r)) { |
| 89 return Status::ErrorUnexpected(); | 83 return Status::ErrorUnexpected(); |
| 90 } | 84 } |
| 91 | 85 |
| 92 if (!BN_bn2bin_padded(&(*signature)[order_size_bytes], order_size_bytes, | 86 if (!BN_bn2bin_padded(&(*signature)[order_size_bytes], order_size_bytes, |
| 93 ecdsa_sig.get()->s)) { | 87 ecdsa_sig.get()->s)) { |
| 94 return Status::ErrorUnexpected(); | 88 return Status::ErrorUnexpected(); |
| 95 } | 89 } |
| 96 | 90 |
| 97 return Status::Success(); | 91 return Status::Success(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 return Status::ErrorUnexpected(); | 136 return Status::ErrorUnexpected(); |
| 143 } | 137 } |
| 144 | 138 |
| 145 // Determine the size of the DER-encoded signature. | 139 // Determine the size of the DER-encoded signature. |
| 146 int der_encoding_size = i2d_ECDSA_SIG(ecdsa_sig.get(), NULL); | 140 int der_encoding_size = i2d_ECDSA_SIG(ecdsa_sig.get(), NULL); |
| 147 if (der_encoding_size < 0) | 141 if (der_encoding_size < 0) |
| 148 return Status::OperationError(); | 142 return Status::OperationError(); |
| 149 | 143 |
| 150 // DER-encode the signature. | 144 // DER-encode the signature. |
| 151 der_signature->resize(der_encoding_size); | 145 der_signature->resize(der_encoding_size); |
| 152 uint8_t* result = vector_as_array(der_signature); | 146 uint8_t* result = der_signature->data(); |
| 153 if (0 > i2d_ECDSA_SIG(ecdsa_sig.get(), &result)) | 147 if (0 > i2d_ECDSA_SIG(ecdsa_sig.get(), &result)) |
| 154 return Status::OperationError(); | 148 return Status::OperationError(); |
| 155 | 149 |
| 156 return Status::Success(); | 150 return Status::Success(); |
| 157 } | 151 } |
| 158 | 152 |
| 159 class EcdsaImplementation : public EcAlgorithm { | 153 class EcdsaImplementation : public EcAlgorithm { |
| 160 public: | 154 public: |
| 161 EcdsaImplementation() | 155 EcdsaImplementation() |
| 162 : EcAlgorithm(blink::WebCryptoKeyUsageVerify, | 156 : EcAlgorithm(blink::WebCryptoKeyUsageVerify, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 198 // the real one, which may be smaller. | 192 // the real one, which may be smaller. |
| 199 size_t sig_len = 0; | 193 size_t sig_len = 0; |
| 200 if (!ctx.get() || | 194 if (!ctx.get() || |
| 201 !EVP_DigestSignInit(ctx.get(), NULL, digest, NULL, private_key) || | 195 !EVP_DigestSignInit(ctx.get(), NULL, digest, NULL, private_key) || |
| 202 !EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) || | 196 !EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) || |
| 203 !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) { | 197 !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) { |
| 204 return Status::OperationError(); | 198 return Status::OperationError(); |
| 205 } | 199 } |
| 206 | 200 |
| 207 buffer->resize(sig_len); | 201 buffer->resize(sig_len); |
| 208 if (!EVP_DigestSignFinal(ctx.get(), vector_as_array(buffer), &sig_len)) | 202 if (!EVP_DigestSignFinal(ctx.get(), buffer->data(), &sig_len)) |
| 209 return Status::OperationError(); | 203 return Status::OperationError(); |
| 210 buffer->resize(sig_len); | 204 buffer->resize(sig_len); |
| 211 | 205 |
| 212 // ECDSA signing in BoringSSL outputs a DER-encoded (r,s). WebCrypto however | 206 // ECDSA signing in BoringSSL outputs a DER-encoded (r,s). WebCrypto however |
| 213 // expects a padded bitstring that is r concatenated to s. Convert to the | 207 // expects a padded bitstring that is r concatenated to s. Convert to the |
| 214 // expected format. | 208 // expected format. |
| 215 return ConvertDerSignatureToWebCryptoSignature(private_key, buffer); | 209 return ConvertDerSignatureToWebCryptoSignature(private_key, buffer); |
| 216 } | 210 } |
| 217 | 211 |
| 218 Status Verify(const blink::WebCryptoAlgorithm& algorithm, | 212 Status Verify(const blink::WebCryptoAlgorithm& algorithm, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 242 if (incorrect_length_signature) { | 236 if (incorrect_length_signature) { |
| 243 *signature_match = false; | 237 *signature_match = false; |
| 244 return Status::Success(); | 238 return Status::Success(); |
| 245 } | 239 } |
| 246 | 240 |
| 247 if (!EVP_DigestVerifyInit(ctx.get(), NULL, digest, NULL, public_key) || | 241 if (!EVP_DigestVerifyInit(ctx.get(), NULL, digest, NULL, public_key) || |
| 248 !EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length())) { | 242 !EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length())) { |
| 249 return Status::OperationError(); | 243 return Status::OperationError(); |
| 250 } | 244 } |
| 251 | 245 |
| 252 *signature_match = | 246 *signature_match = !!EVP_DigestVerifyFinal(ctx.get(), der_signature.data(), |
|
eroman
2015/11/20 00:35:14
tbh i don't find !! more readable than 1==
davidben
2015/11/20 19:12:50
Switched back.
| |
| 253 1 == EVP_DigestVerifyFinal(ctx.get(), vector_as_array(&der_signature), | 247 der_signature.size()); |
| 254 der_signature.size()); | |
| 255 return Status::Success(); | 248 return Status::Success(); |
| 256 } | 249 } |
| 257 }; | 250 }; |
| 258 | 251 |
| 259 } // namespace | 252 } // namespace |
| 260 | 253 |
| 261 scoped_ptr<AlgorithmImplementation> CreateEcdsaImplementation() { | 254 scoped_ptr<AlgorithmImplementation> CreateEcdsaImplementation() { |
| 262 return make_scoped_ptr(new EcdsaImplementation); | 255 return make_scoped_ptr(new EcdsaImplementation); |
| 263 } | 256 } |
| 264 | 257 |
| 265 } // namespace webcrypto | 258 } // namespace webcrypto |
| OLD | NEW |