Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(322)

Side by Side Diff: components/webcrypto/algorithms/ecdsa.cc

Issue 2407633002: Use new BoringSSL scopers in //components. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/webcrypto/algorithms/ecdh.cc ('k') | components/webcrypto/algorithms/pbkdf2.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/bn.h>
6 #include <openssl/digest.h>
5 #include <openssl/ec.h> 7 #include <openssl/ec.h>
6 #include <openssl/ec_key.h> 8 #include <openssl/ec_key.h>
7 #include <openssl/ecdsa.h> 9 #include <openssl/ecdsa.h>
8 #include <openssl/evp.h> 10 #include <openssl/evp.h>
11 #include <openssl/mem.h>
9 #include <stddef.h> 12 #include <stddef.h>
10 #include <stdint.h> 13 #include <stdint.h>
11 14
12 #include "base/logging.h" 15 #include "base/logging.h"
13 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
14 #include "components/webcrypto/algorithm_implementation.h" 17 #include "components/webcrypto/algorithm_implementation.h"
15 #include "components/webcrypto/algorithms/ec.h" 18 #include "components/webcrypto/algorithms/ec.h"
16 #include "components/webcrypto/algorithms/util.h" 19 #include "components/webcrypto/algorithms/util.h"
17 #include "components/webcrypto/blink_key_handle.h" 20 #include "components/webcrypto/blink_key_handle.h"
18 #include "components/webcrypto/crypto_data.h" 21 #include "components/webcrypto/crypto_data.h"
19 #include "components/webcrypto/generate_key_result.h" 22 #include "components/webcrypto/generate_key_result.h"
20 #include "components/webcrypto/status.h" 23 #include "components/webcrypto/status.h"
21 #include "crypto/openssl_util.h" 24 #include "crypto/openssl_util.h"
22 #include "crypto/scoped_openssl_types.h"
23 #include "crypto/secure_util.h" 25 #include "crypto/secure_util.h"
24 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 26 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
25 #include "third_party/WebKit/public/platform/WebCryptoKey.h" 27 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
26 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 28 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
27 29
28 namespace webcrypto { 30 namespace webcrypto {
29 31
30 namespace { 32 namespace {
31 33
32 // Extracts the OpenSSL key and digest from a WebCrypto key + algorithm. The 34 // Extracts the OpenSSL key and digest from a WebCrypto key + algorithm. The
(...skipping 12 matching lines...) Expand all
45 // Gets the EC key's order size in bytes. 47 // Gets the EC key's order size in bytes.
46 Status GetEcGroupOrderSize(EVP_PKEY* pkey, size_t* order_size_bytes) { 48 Status GetEcGroupOrderSize(EVP_PKEY* pkey, size_t* order_size_bytes) {
47 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 49 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
48 50
49 EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey); 51 EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey);
50 if (!ec) 52 if (!ec)
51 return Status::ErrorUnexpected(); 53 return Status::ErrorUnexpected();
52 54
53 const EC_GROUP* group = EC_KEY_get0_group(ec); 55 const EC_GROUP* group = EC_KEY_get0_group(ec);
54 56
55 crypto::ScopedBIGNUM order(BN_new()); 57 bssl::UniquePtr<BIGNUM> order(BN_new());
56 if (!EC_GROUP_get_order(group, order.get(), NULL)) 58 if (!EC_GROUP_get_order(group, order.get(), NULL))
57 return Status::OperationError(); 59 return Status::OperationError();
58 60
59 *order_size_bytes = BN_num_bytes(order.get()); 61 *order_size_bytes = BN_num_bytes(order.get());
60 return Status::Success(); 62 return Status::Success();
61 } 63 }
62 64
63 // Formats a DER-encoded signature (ECDSA-Sig-Value as specified in RFC 3279) to 65 // Formats a DER-encoded signature (ECDSA-Sig-Value as specified in RFC 3279) to
64 // the signature format expected by WebCrypto (raw concatenated "r" and "s"). 66 // the signature format expected by WebCrypto (raw concatenated "r" and "s").
65 // 67 //
66 // TODO(eroman): Where is the specification for WebCrypto's signature format? 68 // TODO(eroman): Where is the specification for WebCrypto's signature format?
67 Status ConvertDerSignatureToWebCryptoSignature( 69 Status ConvertDerSignatureToWebCryptoSignature(
68 EVP_PKEY* key, 70 EVP_PKEY* key,
69 std::vector<uint8_t>* signature) { 71 std::vector<uint8_t>* signature) {
70 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 72 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
71 73
72 crypto::ScopedECDSA_SIG ecdsa_sig( 74 bssl::UniquePtr<ECDSA_SIG> ecdsa_sig(
73 ECDSA_SIG_from_bytes(signature->data(), signature->size())); 75 ECDSA_SIG_from_bytes(signature->data(), signature->size()));
74 if (!ecdsa_sig.get()) 76 if (!ecdsa_sig.get())
75 return Status::ErrorUnexpected(); 77 return Status::ErrorUnexpected();
76 78
77 // Determine the maximum length of r and s. 79 // Determine the maximum length of r and s.
78 size_t order_size_bytes; 80 size_t order_size_bytes;
79 Status status = GetEcGroupOrderSize(key, &order_size_bytes); 81 Status status = GetEcGroupOrderSize(key, &order_size_bytes);
80 if (status.IsError()) 82 if (status.IsError())
81 return status; 83 return status;
82 84
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 // verification with a boolean, rather than reject the promise with an 125 // verification with a boolean, rather than reject the promise with an
124 // exception. 126 // exception.
125 if (signature.byte_length() != 2 * order_size_bytes) { 127 if (signature.byte_length() != 2 * order_size_bytes) {
126 *incorrect_length = true; 128 *incorrect_length = true;
127 return Status::Success(); 129 return Status::Success();
128 } 130 }
129 131
130 *incorrect_length = false; 132 *incorrect_length = false;
131 133
132 // Construct an ECDSA_SIG from |signature|. 134 // Construct an ECDSA_SIG from |signature|.
133 crypto::ScopedECDSA_SIG ecdsa_sig(ECDSA_SIG_new()); 135 bssl::UniquePtr<ECDSA_SIG> ecdsa_sig(ECDSA_SIG_new());
134 if (!ecdsa_sig) 136 if (!ecdsa_sig)
135 return Status::OperationError(); 137 return Status::OperationError();
136 138
137 if (!BN_bin2bn(signature.bytes(), order_size_bytes, ecdsa_sig->r) || 139 if (!BN_bin2bn(signature.bytes(), order_size_bytes, ecdsa_sig->r) ||
138 !BN_bin2bn(signature.bytes() + order_size_bytes, order_size_bytes, 140 !BN_bin2bn(signature.bytes() + order_size_bytes, order_size_bytes,
139 ecdsa_sig->s)) { 141 ecdsa_sig->s)) {
140 return Status::ErrorUnexpected(); 142 return Status::ErrorUnexpected();
141 } 143 }
142 144
143 // Encode the signature. 145 // Encode the signature.
(...skipping 29 matching lines...) Expand all
173 } 175 }
174 176
175 Status Sign(const blink::WebCryptoAlgorithm& algorithm, 177 Status Sign(const blink::WebCryptoAlgorithm& algorithm,
176 const blink::WebCryptoKey& key, 178 const blink::WebCryptoKey& key,
177 const CryptoData& data, 179 const CryptoData& data,
178 std::vector<uint8_t>* buffer) const override { 180 std::vector<uint8_t>* buffer) const override {
179 if (key.type() != blink::WebCryptoKeyTypePrivate) 181 if (key.type() != blink::WebCryptoKeyTypePrivate)
180 return Status::ErrorUnexpectedKeyType(); 182 return Status::ErrorUnexpectedKeyType();
181 183
182 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 184 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
183 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
184 185
185 EVP_PKEY* private_key = NULL; 186 EVP_PKEY* private_key = NULL;
186 const EVP_MD* digest = NULL; 187 const EVP_MD* digest = NULL;
187 Status status = GetPKeyAndDigest(algorithm, key, &private_key, &digest); 188 Status status = GetPKeyAndDigest(algorithm, key, &private_key, &digest);
188 if (status.IsError()) 189 if (status.IsError())
189 return status; 190 return status;
190 191
191 // NOTE: A call to EVP_DigestSignFinal() with a NULL second parameter 192 // NOTE: A call to EVP_DigestSignFinal() with a NULL second parameter
192 // returns a maximum allocation size, while the call without a NULL returns 193 // returns a maximum allocation size, while the call without a NULL returns
193 // the real one, which may be smaller. 194 // the real one, which may be smaller.
195 bssl::ScopedEVP_MD_CTX ctx;
194 size_t sig_len = 0; 196 size_t sig_len = 0;
195 if (!ctx.get() || 197 if (!EVP_DigestSignInit(ctx.get(), NULL, digest, NULL, private_key) ||
196 !EVP_DigestSignInit(ctx.get(), NULL, digest, NULL, private_key) ||
197 !EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) || 198 !EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) ||
198 !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) { 199 !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) {
199 return Status::OperationError(); 200 return Status::OperationError();
200 } 201 }
201 202
202 buffer->resize(sig_len); 203 buffer->resize(sig_len);
203 if (!EVP_DigestSignFinal(ctx.get(), buffer->data(), &sig_len)) 204 if (!EVP_DigestSignFinal(ctx.get(), buffer->data(), &sig_len))
204 return Status::OperationError(); 205 return Status::OperationError();
205 buffer->resize(sig_len); 206 buffer->resize(sig_len);
206 207
207 // ECDSA signing in BoringSSL outputs a DER-encoded (r,s). WebCrypto however 208 // ECDSA signing in BoringSSL outputs a DER-encoded (r,s). WebCrypto however
208 // expects a padded bitstring that is r concatenated to s. Convert to the 209 // expects a padded bitstring that is r concatenated to s. Convert to the
209 // expected format. 210 // expected format.
210 return ConvertDerSignatureToWebCryptoSignature(private_key, buffer); 211 return ConvertDerSignatureToWebCryptoSignature(private_key, buffer);
211 } 212 }
212 213
213 Status Verify(const blink::WebCryptoAlgorithm& algorithm, 214 Status Verify(const blink::WebCryptoAlgorithm& algorithm,
214 const blink::WebCryptoKey& key, 215 const blink::WebCryptoKey& key,
215 const CryptoData& signature, 216 const CryptoData& signature,
216 const CryptoData& data, 217 const CryptoData& data,
217 bool* signature_match) const override { 218 bool* signature_match) const override {
218 if (key.type() != blink::WebCryptoKeyTypePublic) 219 if (key.type() != blink::WebCryptoKeyTypePublic)
219 return Status::ErrorUnexpectedKeyType(); 220 return Status::ErrorUnexpectedKeyType();
220 221
221 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 222 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
222 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
223 223
224 EVP_PKEY* public_key = NULL; 224 EVP_PKEY* public_key = NULL;
225 const EVP_MD* digest = NULL; 225 const EVP_MD* digest = NULL;
226 Status status = GetPKeyAndDigest(algorithm, key, &public_key, &digest); 226 Status status = GetPKeyAndDigest(algorithm, key, &public_key, &digest);
227 if (status.IsError()) 227 if (status.IsError())
228 return status; 228 return status;
229 229
230 std::vector<uint8_t> der_signature; 230 std::vector<uint8_t> der_signature;
231 bool incorrect_length_signature = false; 231 bool incorrect_length_signature = false;
232 status = ConvertWebCryptoSignatureToDerSignature( 232 status = ConvertWebCryptoSignatureToDerSignature(
233 public_key, signature, &der_signature, &incorrect_length_signature); 233 public_key, signature, &der_signature, &incorrect_length_signature);
234 if (status.IsError()) 234 if (status.IsError())
235 return status; 235 return status;
236 236
237 if (incorrect_length_signature) { 237 if (incorrect_length_signature) {
238 *signature_match = false; 238 *signature_match = false;
239 return Status::Success(); 239 return Status::Success();
240 } 240 }
241 241
242 bssl::ScopedEVP_MD_CTX ctx;
242 if (!EVP_DigestVerifyInit(ctx.get(), NULL, digest, NULL, public_key) || 243 if (!EVP_DigestVerifyInit(ctx.get(), NULL, digest, NULL, public_key) ||
243 !EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length())) { 244 !EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length())) {
244 return Status::OperationError(); 245 return Status::OperationError();
245 } 246 }
246 247
247 *signature_match = 248 *signature_match =
248 1 == EVP_DigestVerifyFinal(ctx.get(), der_signature.data(), 249 1 == EVP_DigestVerifyFinal(ctx.get(), der_signature.data(),
249 der_signature.size()); 250 der_signature.size());
250 return Status::Success(); 251 return Status::Success();
251 } 252 }
252 }; 253 };
253 254
254 } // namespace 255 } // namespace
255 256
256 std::unique_ptr<AlgorithmImplementation> CreateEcdsaImplementation() { 257 std::unique_ptr<AlgorithmImplementation> CreateEcdsaImplementation() {
257 return base::WrapUnique(new EcdsaImplementation); 258 return base::WrapUnique(new EcdsaImplementation);
258 } 259 }
259 260
260 } // namespace webcrypto 261 } // namespace webcrypto
OLDNEW
« no previous file with comments | « components/webcrypto/algorithms/ecdh.cc ('k') | components/webcrypto/algorithms/pbkdf2.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698