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

Side by Side Diff: content/child/webcrypto/openssl/ecdh_openssl.cc

Issue 749183004: WebCrypto: Implement crypto.subtle.deriveKey (chromium-side). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ecdh
Patch Set: rebase Created 6 years 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
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/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 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "content/child/webcrypto/algorithm_implementation.h" 10 #include "content/child/webcrypto/algorithm_implementation.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 blink::WebCryptoKeyUsageDeriveBits) {} 42 blink::WebCryptoKeyUsageDeriveBits) {}
43 43
44 const char* GetJwkAlgorithm( 44 const char* GetJwkAlgorithm(
45 const blink::WebCryptoNamedCurve curve) const override { 45 const blink::WebCryptoNamedCurve curve) const override {
46 // JWK import for ECDH does not enforce any required value for "alg". 46 // JWK import for ECDH does not enforce any required value for "alg".
47 return ""; 47 return "";
48 } 48 }
49 49
50 Status DeriveBits(const blink::WebCryptoAlgorithm& algorithm, 50 Status DeriveBits(const blink::WebCryptoAlgorithm& algorithm,
51 const blink::WebCryptoKey& base_key, 51 const blink::WebCryptoKey& base_key,
52 unsigned int length_bits, 52 bool has_optional_length_bits,
53 unsigned int optional_length_bits,
53 std::vector<uint8_t>* derived_bytes) const override { 54 std::vector<uint8_t>* derived_bytes) const override {
54 if (base_key.type() != blink::WebCryptoKeyTypePrivate) 55 if (base_key.type() != blink::WebCryptoKeyTypePrivate)
55 return Status::ErrorUnexpectedKeyType(); 56 return Status::ErrorUnexpectedKeyType();
56 57
57 // Verify the "publicKey" parameter. The only guarantee from Blink is that 58 // Verify the "publicKey" parameter. The only guarantee from Blink is that
58 // it is a valid WebCryptoKey, but it could be any type. 59 // it is a valid WebCryptoKey, but it could be any type.
59 const blink::WebCryptoKey& public_key = 60 const blink::WebCryptoKey& public_key =
60 algorithm.ecdhKeyDeriveParams()->publicKey(); 61 algorithm.ecdhKeyDeriveParams()->publicKey();
61 62
62 if (public_key.type() != blink::WebCryptoKeyTypePublic) 63 if (public_key.type() != blink::WebCryptoKeyTypePublic)
63 return Status::ErrorEcdhPublicKeyWrongType(); 64 return Status::ErrorEcdhPublicKeyWrongType();
64 65
65 // Make sure it is an EC key. 66 // Make sure it is an EC key.
66 if (!public_key.algorithm().ecParams()) 67 if (!public_key.algorithm().ecParams())
67 return Status::ErrorEcdhPublicKeyWrongType(); 68 return Status::ErrorEcdhPublicKeyWrongType();
68 69
69 // TODO(eroman): This is not described by the spec: 70 // TODO(eroman): This is not described by the spec:
70 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27404 71 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27404
71 if (public_key.algorithm().id() != blink::WebCryptoAlgorithmIdEcdh) 72 if (public_key.algorithm().id() != blink::WebCryptoAlgorithmIdEcdh)
72 return Status::ErrorEcdhPublicKeyWrongAlgorithm(); 73 return Status::ErrorEcdhPublicKeyWrongAlgorithm();
73 74
74 // 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
75 // curves must match. 76 // curves must match.
76 if (public_key.algorithm().ecParams()->namedCurve() != 77 if (public_key.algorithm().ecParams()->namedCurve() !=
77 base_key.algorithm().ecParams()->namedCurve()) { 78 base_key.algorithm().ecParams()->namedCurve()) {
78 return Status::ErrorEcdhCurveMismatch(); 79 return Status::ErrorEcdhCurveMismatch();
79 } 80 }
80 81
81 // Handle the empty length case now to avoid calling an undefined
82 // |&derived_bytes->front()| later.
83 if (length_bits == 0) {
84 derived_bytes->clear();
85 return Status::Success();
86 }
87
88 crypto::ScopedEC_KEY public_key_ec( 82 crypto::ScopedEC_KEY public_key_ec(
89 EVP_PKEY_get1_EC_KEY(AsymKeyOpenSsl::Cast(public_key)->key())); 83 EVP_PKEY_get1_EC_KEY(AsymKeyOpenSsl::Cast(public_key)->key()));
90 84
91 const EC_POINT* public_key_point = 85 const EC_POINT* public_key_point =
92 EC_KEY_get0_public_key(public_key_ec.get()); 86 EC_KEY_get0_public_key(public_key_ec.get());
93 87
94 crypto::ScopedEC_KEY private_key_ec( 88 crypto::ScopedEC_KEY private_key_ec(
95 EVP_PKEY_get1_EC_KEY(AsymKeyOpenSsl::Cast(base_key)->key())); 89 EVP_PKEY_get1_EC_KEY(AsymKeyOpenSsl::Cast(base_key)->key()));
96 90
97 // The size of the shared secret is the field size in bytes (rounded up). 91 // The size of the shared secret is the field size in bytes (rounded up).
98 // Note that, if rounding was required, the most significant bits of the 92 // Note that, if rounding was required, the most significant bits of the
99 // secret are zero. So for P-521, the maximum length is 528 bits, not 521. 93 // secret are zero. So for P-521, the maximum length is 528 bits, not 521.
100 int field_size_bytes = NumBitsToBytes( 94 int field_size_bytes = NumBitsToBytes(
101 EC_GROUP_get_degree(EC_KEY_get0_group(private_key_ec.get()))); 95 EC_GROUP_get_degree(EC_KEY_get0_group(private_key_ec.get())));
102 96
97 // If a desired key length was not specified, default to the field size
98 // (rounded up to nearest byte).
99 unsigned int length_bits =
100 has_optional_length_bits ? optional_length_bits : field_size_bytes * 8;
101
102 // Handle the empty length case now to avoid calling an undefined
103 // |&derived_bytes->front()| later.
104 if (length_bits == 0) {
105 derived_bytes->clear();
106 return Status::Success();
107 }
108
103 if (length_bits > static_cast<unsigned int>(field_size_bytes * 8)) 109 if (length_bits > static_cast<unsigned int>(field_size_bytes * 8))
104 return Status::ErrorEcdhLengthTooBig(field_size_bytes * 8); 110 return Status::ErrorEcdhLengthTooBig(field_size_bytes * 8);
105 111
106 // Resize to target length in bytes (BoringSSL can operate on a shorter 112 // Resize to target length in bytes (BoringSSL can operate on a shorter
107 // buffer than field_size_bytes). 113 // buffer than field_size_bytes).
108 derived_bytes->resize(NumBitsToBytes(length_bits)); 114 derived_bytes->resize(NumBitsToBytes(length_bits));
109 115
110 int result = 116 int result =
111 ECDH_compute_key(&derived_bytes->front(), derived_bytes->size(), 117 ECDH_compute_key(&derived_bytes->front(), derived_bytes->size(),
112 public_key_point, private_key_ec.get(), 0); 118 public_key_point, private_key_ec.get(), 0);
113 if (result < 0 || static_cast<size_t>(result) != derived_bytes->size()) 119 if (result < 0 || static_cast<size_t>(result) != derived_bytes->size())
114 return Status::OperationError(); 120 return Status::OperationError();
115 121
116 TruncateToBitLength(length_bits, derived_bytes); 122 TruncateToBitLength(length_bits, derived_bytes);
117 return Status::Success(); 123 return Status::Success();
118 } 124 }
119 }; 125 };
120 126
121 } // namespace 127 } // namespace
122 128
123 AlgorithmImplementation* CreatePlatformEcdhImplementation() { 129 AlgorithmImplementation* CreatePlatformEcdhImplementation() {
124 return new EcdhImplementation; 130 return new EcdhImplementation;
125 } 131 }
126 132
127 } // namespace webcrypto 133 } // namespace webcrypto
128 134
129 } // namespace content 135 } // namespace content
OLDNEW
« no previous file with comments | « content/child/webcrypto/algorithm_implementation.cc ('k') | content/child/webcrypto/test/ecdh_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698