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())); |
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 24 matching lines...) Expand all Loading... |
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 = |
253 1 == EVP_DigestVerifyFinal(ctx.get(), vector_as_array(&der_signature), | 247 1 == EVP_DigestVerifyFinal(ctx.get(), der_signature.data(), |
254 der_signature.size()); | 248 der_signature.size()); |
255 return Status::Success(); | 249 return Status::Success(); |
256 } | 250 } |
257 }; | 251 }; |
258 | 252 |
259 } // namespace | 253 } // namespace |
260 | 254 |
261 scoped_ptr<AlgorithmImplementation> CreateEcdsaImplementation() { | 255 scoped_ptr<AlgorithmImplementation> CreateEcdsaImplementation() { |
262 return make_scoped_ptr(new EcdsaImplementation); | 256 return make_scoped_ptr(new EcdsaImplementation); |
263 } | 257 } |
264 | 258 |
265 } // namespace webcrypto | 259 } // namespace webcrypto |
OLD | NEW |