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 "content/child/webcrypto/openssl/rsa_key_openssl.h" | 5 #include "content/child/webcrypto/openssl/rsa_key_openssl.h" |
6 | 6 |
7 #include <openssl/evp.h> | 7 #include <openssl/evp.h> |
8 #include <openssl/pkcs12.h> | |
9 | 8 |
10 #include "base/logging.h" | 9 #include "base/logging.h" |
11 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
12 #include "content/child/webcrypto/crypto_data.h" | 11 #include "content/child/webcrypto/crypto_data.h" |
13 #include "content/child/webcrypto/generate_key_result.h" | 12 #include "content/child/webcrypto/generate_key_result.h" |
14 #include "content/child/webcrypto/jwk.h" | 13 #include "content/child/webcrypto/jwk.h" |
15 #include "content/child/webcrypto/openssl/key_openssl.h" | 14 #include "content/child/webcrypto/openssl/key_openssl.h" |
| 15 #include "content/child/webcrypto/openssl/util_openssl.h" |
16 #include "content/child/webcrypto/status.h" | 16 #include "content/child/webcrypto/status.h" |
17 #include "content/child/webcrypto/webcrypto_util.h" | 17 #include "content/child/webcrypto/webcrypto_util.h" |
18 #include "crypto/openssl_util.h" | 18 #include "crypto/openssl_util.h" |
19 #include "crypto/scoped_openssl_types.h" | 19 #include "crypto/scoped_openssl_types.h" |
20 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 20 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
21 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 21 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
22 | 22 |
23 namespace content { | 23 namespace content { |
24 | 24 |
25 namespace webcrypto { | 25 namespace webcrypto { |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 Status ExportPKeySpki(EVP_PKEY* key, std::vector<uint8_t>* buffer) { | |
30 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | |
31 crypto::ScopedBIO bio(BIO_new(BIO_s_mem())); | |
32 | |
33 // TODO(eroman): Use the OID specified by webcrypto spec. | |
34 // http://crbug.com/373545 | |
35 if (!i2d_PUBKEY_bio(bio.get(), key)) | |
36 return Status::ErrorUnexpected(); | |
37 | |
38 char* data = NULL; | |
39 long len = BIO_get_mem_data(bio.get(), &data); | |
40 if (!data || len < 0) | |
41 return Status::ErrorUnexpected(); | |
42 | |
43 buffer->assign(data, data + len); | |
44 return Status::Success(); | |
45 } | |
46 | |
47 Status ExportPKeyPkcs8(EVP_PKEY* key, std::vector<uint8_t>* buffer) { | |
48 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | |
49 crypto::ScopedBIO bio(BIO_new(BIO_s_mem())); | |
50 | |
51 // TODO(eroman): Use the OID specified by webcrypto spec. | |
52 // http://crbug.com/373545 | |
53 if (!i2d_PKCS8PrivateKeyInfo_bio(bio.get(), key)) | |
54 return Status::ErrorUnexpected(); | |
55 | |
56 char* data = NULL; | |
57 long len = BIO_get_mem_data(bio.get(), &data); | |
58 if (!data || len < 0) | |
59 return Status::ErrorUnexpected(); | |
60 | |
61 buffer->assign(data, data + len); | |
62 return Status::Success(); | |
63 } | |
64 | |
65 // Creates a blink::WebCryptoAlgorithm having the modulus length and public | 29 // Creates a blink::WebCryptoAlgorithm having the modulus length and public |
66 // exponent of |key|. | 30 // exponent of |key|. |
67 Status CreateRsaHashedKeyAlgorithm( | 31 Status CreateRsaHashedKeyAlgorithm( |
68 blink::WebCryptoAlgorithmId rsa_algorithm, | 32 blink::WebCryptoAlgorithmId rsa_algorithm, |
69 blink::WebCryptoAlgorithmId hash_algorithm, | 33 blink::WebCryptoAlgorithmId hash_algorithm, |
70 EVP_PKEY* key, | 34 EVP_PKEY* key, |
71 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 35 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
72 DCHECK_EQ(EVP_PKEY_RSA, EVP_PKEY_id(key)); | 36 DCHECK_EQ(EVP_PKEY_RSA, EVP_PKEY_id(key)); |
73 | 37 |
74 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(key)); | 38 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(key)); |
75 if (!rsa.get()) | 39 if (!rsa.get()) |
76 return Status::ErrorUnexpected(); | 40 return Status::ErrorUnexpected(); |
77 | 41 |
78 unsigned int modulus_length_bits = BN_num_bits(rsa.get()->n); | 42 unsigned int modulus_length_bits = BN_num_bits(rsa.get()->n); |
79 | 43 |
80 // Convert the public exponent to big-endian representation. | 44 // Convert the public exponent to big-endian representation. |
81 std::vector<uint8_t> e(BN_num_bytes(rsa.get()->e)); | 45 std::vector<uint8_t> e(BN_num_bytes(rsa.get()->e)); |
82 if (e.size() == 0) | 46 if (e.size() == 0) |
83 return Status::ErrorUnexpected(); | 47 return Status::ErrorUnexpected(); |
84 if (e.size() != BN_bn2bin(rsa.get()->e, &e[0])) | 48 if (e.size() != BN_bn2bin(rsa.get()->e, &e[0])) |
85 return Status::ErrorUnexpected(); | 49 return Status::ErrorUnexpected(); |
86 | 50 |
87 *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed( | 51 *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed( |
88 rsa_algorithm, modulus_length_bits, &e[0], e.size(), hash_algorithm); | 52 rsa_algorithm, modulus_length_bits, &e[0], e.size(), hash_algorithm); |
89 | 53 |
90 return Status::Success(); | 54 return Status::Success(); |
91 } | 55 } |
92 | 56 |
93 Status CreateWebCryptoPrivateKey( | 57 // Creates a WebCryptoKey that wraps |private_key|. |
| 58 Status CreateWebCryptoRsaPrivateKey( |
94 crypto::ScopedEVP_PKEY private_key, | 59 crypto::ScopedEVP_PKEY private_key, |
95 const blink::WebCryptoAlgorithmId rsa_algorithm_id, | 60 const blink::WebCryptoAlgorithmId rsa_algorithm_id, |
96 const blink::WebCryptoAlgorithm& hash, | 61 const blink::WebCryptoAlgorithm& hash, |
97 bool extractable, | 62 bool extractable, |
98 blink::WebCryptoKeyUsageMask usages, | 63 blink::WebCryptoKeyUsageMask usages, |
99 blink::WebCryptoKey* key) { | 64 blink::WebCryptoKey* key) { |
100 blink::WebCryptoKeyAlgorithm key_algorithm; | 65 blink::WebCryptoKeyAlgorithm key_algorithm; |
101 Status status = CreateRsaHashedKeyAlgorithm( | 66 Status status = CreateRsaHashedKeyAlgorithm( |
102 rsa_algorithm_id, hash.id(), private_key.get(), &key_algorithm); | 67 rsa_algorithm_id, hash.id(), private_key.get(), &key_algorithm); |
103 if (status.IsError()) | 68 if (status.IsError()) |
104 return status; | 69 return status; |
105 | 70 |
106 // Serialize the key at creation time so that if structured cloning is | 71 return CreateWebCryptoPrivateKey(private_key.Pass(), key_algorithm, |
107 // requested it can be done synchronously from the Blink thread. | 72 extractable, usages, key); |
108 std::vector<uint8_t> pkcs8_data; | |
109 status = ExportPKeyPkcs8(private_key.get(), &pkcs8_data); | |
110 if (status.IsError()) | |
111 return status; | |
112 | |
113 *key = blink::WebCryptoKey::create( | |
114 new AsymKeyOpenSsl(private_key.Pass(), CryptoData(pkcs8_data)), | |
115 blink::WebCryptoKeyTypePrivate, | |
116 extractable, | |
117 key_algorithm, | |
118 usages); | |
119 return Status::Success(); | |
120 } | 73 } |
121 | 74 |
122 Status CreateWebCryptoPublicKey( | 75 // Creates a WebCryptoKey that wraps |public_key|. |
| 76 Status CreateWebCryptoRsaPublicKey( |
123 crypto::ScopedEVP_PKEY public_key, | 77 crypto::ScopedEVP_PKEY public_key, |
124 const blink::WebCryptoAlgorithmId rsa_algorithm_id, | 78 const blink::WebCryptoAlgorithmId rsa_algorithm_id, |
125 const blink::WebCryptoAlgorithm& hash, | 79 const blink::WebCryptoAlgorithm& hash, |
126 bool extractable, | 80 bool extractable, |
127 blink::WebCryptoKeyUsageMask usages, | 81 blink::WebCryptoKeyUsageMask usages, |
128 blink::WebCryptoKey* key) { | 82 blink::WebCryptoKey* key) { |
129 blink::WebCryptoKeyAlgorithm key_algorithm; | 83 blink::WebCryptoKeyAlgorithm key_algorithm; |
130 Status status = CreateRsaHashedKeyAlgorithm( | 84 Status status = CreateRsaHashedKeyAlgorithm( |
131 rsa_algorithm_id, hash.id(), public_key.get(), &key_algorithm); | 85 rsa_algorithm_id, hash.id(), public_key.get(), &key_algorithm); |
132 if (status.IsError()) | 86 if (status.IsError()) |
133 return status; | 87 return status; |
134 | 88 |
135 // Serialize the key at creation time so that if structured cloning is | 89 return CreateWebCryptoPublicKey(public_key.Pass(), key_algorithm, extractable, |
136 // requested it can be done synchronously from the Blink thread. | 90 usages, key); |
137 std::vector<uint8_t> spki_data; | |
138 status = ExportPKeySpki(public_key.get(), &spki_data); | |
139 if (status.IsError()) | |
140 return status; | |
141 | |
142 *key = blink::WebCryptoKey::create( | |
143 new AsymKeyOpenSsl(public_key.Pass(), CryptoData(spki_data)), | |
144 blink::WebCryptoKeyTypePublic, | |
145 extractable, | |
146 key_algorithm, | |
147 usages); | |
148 return Status::Success(); | |
149 } | 91 } |
150 | 92 |
151 // Converts a BIGNUM to a big endian byte array. | 93 // Converts a BIGNUM to a big endian byte array. |
152 std::vector<uint8_t> BIGNUMToVector(BIGNUM* n) { | 94 std::vector<uint8_t> BIGNUMToVector(BIGNUM* n) { |
153 std::vector<uint8_t> v(BN_num_bytes(n)); | 95 std::vector<uint8_t> v(BN_num_bytes(n)); |
154 BN_bn2bin(n, vector_as_array(&v)); | 96 BN_bn2bin(n, vector_as_array(&v)); |
155 return v; | 97 return v; |
156 } | 98 } |
157 | 99 |
158 // Allocates a new BIGNUM given a std::string big-endian representation. | 100 // Allocates a new BIGNUM given a std::string big-endian representation. |
(...skipping 25 matching lines...) Expand all Loading... |
184 // TODO(eroman): This should really be a DataError, however for compatibility | 126 // TODO(eroman): This should really be a DataError, however for compatibility |
185 // with NSS it is an OperationError. | 127 // with NSS it is an OperationError. |
186 if (!RSA_check_key(rsa.get())) | 128 if (!RSA_check_key(rsa.get())) |
187 return Status::OperationError(); | 129 return Status::OperationError(); |
188 | 130 |
189 // Create a corresponding EVP_PKEY. | 131 // Create a corresponding EVP_PKEY. |
190 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 132 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
191 if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) | 133 if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) |
192 return Status::OperationError(); | 134 return Status::OperationError(); |
193 | 135 |
194 return CreateWebCryptoPrivateKey(pkey.Pass(), | 136 return CreateWebCryptoRsaPrivateKey(pkey.Pass(), algorithm.id(), |
195 algorithm.id(), | 137 algorithm.rsaHashedImportParams()->hash(), |
196 algorithm.rsaHashedImportParams()->hash(), | 138 extractable, usages, key); |
197 extractable, | |
198 usages, | |
199 key); | |
200 } | 139 } |
201 | 140 |
202 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, | 141 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, |
203 bool extractable, | 142 bool extractable, |
204 blink::WebCryptoKeyUsageMask usages, | 143 blink::WebCryptoKeyUsageMask usages, |
205 const CryptoData& n, | 144 const CryptoData& n, |
206 const CryptoData& e, | 145 const CryptoData& e, |
207 blink::WebCryptoKey* key) { | 146 blink::WebCryptoKey* key) { |
208 crypto::ScopedRSA rsa(RSA_new()); | 147 crypto::ScopedRSA rsa(RSA_new()); |
209 | 148 |
210 rsa->n = BN_bin2bn(n.bytes(), n.byte_length(), NULL); | 149 rsa->n = BN_bin2bn(n.bytes(), n.byte_length(), NULL); |
211 rsa->e = BN_bin2bn(e.bytes(), e.byte_length(), NULL); | 150 rsa->e = BN_bin2bn(e.bytes(), e.byte_length(), NULL); |
212 | 151 |
213 if (!rsa->n || !rsa->e) | 152 if (!rsa->n || !rsa->e) |
214 return Status::OperationError(); | 153 return Status::OperationError(); |
215 | 154 |
216 // Create a corresponding EVP_PKEY. | 155 // Create a corresponding EVP_PKEY. |
217 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 156 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
218 if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) | 157 if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) |
219 return Status::OperationError(); | 158 return Status::OperationError(); |
220 | 159 |
221 return CreateWebCryptoPublicKey(pkey.Pass(), | 160 return CreateWebCryptoRsaPublicKey(pkey.Pass(), algorithm.id(), |
222 algorithm.id(), | 161 algorithm.rsaHashedImportParams()->hash(), |
223 algorithm.rsaHashedImportParams()->hash(), | 162 extractable, usages, key); |
224 extractable, | |
225 usages, | |
226 key); | |
227 } | 163 } |
228 | 164 |
229 } // namespace | 165 } // namespace |
230 | 166 |
231 Status RsaHashedAlgorithm::GenerateKey( | 167 Status RsaHashedAlgorithm::GenerateKey( |
232 const blink::WebCryptoAlgorithm& algorithm, | 168 const blink::WebCryptoAlgorithm& algorithm, |
233 bool extractable, | 169 bool extractable, |
234 blink::WebCryptoKeyUsageMask combined_usages, | 170 blink::WebCryptoKeyUsageMask combined_usages, |
235 GenerateKeyResult* result) const { | 171 GenerateKeyResult* result) const { |
236 Status status = CheckKeyCreationUsages( | 172 Status status = CheckKeyCreationUsages( |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 if (!public_pkey || | 217 if (!public_pkey || |
282 !EVP_PKEY_set1_RSA(public_pkey.get(), rsa_public_key.get())) { | 218 !EVP_PKEY_set1_RSA(public_pkey.get(), rsa_public_key.get())) { |
283 return Status::OperationError(); | 219 return Status::OperationError(); |
284 } | 220 } |
285 | 221 |
286 blink::WebCryptoKey public_key; | 222 blink::WebCryptoKey public_key; |
287 blink::WebCryptoKey private_key; | 223 blink::WebCryptoKey private_key; |
288 | 224 |
289 // Note that extractable is unconditionally set to true. This is because per | 225 // Note that extractable is unconditionally set to true. This is because per |
290 // the WebCrypto spec generated public keys are always public. | 226 // the WebCrypto spec generated public keys are always public. |
291 status = CreateWebCryptoPublicKey(public_pkey.Pass(), | 227 status = CreateWebCryptoRsaPublicKey(public_pkey.Pass(), algorithm.id(), |
292 algorithm.id(), | 228 params->hash(), true, public_usages, |
293 params->hash(), | 229 &public_key); |
294 true, | |
295 public_usages, | |
296 &public_key); | |
297 if (status.IsError()) | 230 if (status.IsError()) |
298 return status; | 231 return status; |
299 | 232 |
300 status = CreateWebCryptoPrivateKey(private_pkey.Pass(), | 233 status = CreateWebCryptoRsaPrivateKey(private_pkey.Pass(), algorithm.id(), |
301 algorithm.id(), | 234 params->hash(), extractable, |
302 params->hash(), | 235 private_usages, &private_key); |
303 extractable, | |
304 private_usages, | |
305 &private_key); | |
306 if (status.IsError()) | 236 if (status.IsError()) |
307 return status; | 237 return status; |
308 | 238 |
309 result->AssignKeyPair(public_key, private_key); | 239 result->AssignKeyPair(public_key, private_key); |
310 return Status::Success(); | 240 return Status::Success(); |
311 } | 241 } |
312 | 242 |
313 Status RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey( | 243 Status RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey( |
314 blink::WebCryptoKeyFormat format, | 244 blink::WebCryptoKeyFormat format, |
315 blink::WebCryptoKeyUsageMask usages) const { | 245 blink::WebCryptoKeyUsageMask usages) const { |
316 switch (format) { | 246 switch (format) { |
317 case blink::WebCryptoKeyFormatSpki: | 247 case blink::WebCryptoKeyFormatSpki: |
318 return CheckKeyCreationUsages(all_public_key_usages_, usages); | 248 return CheckKeyCreationUsages(all_public_key_usages_, usages); |
319 case blink::WebCryptoKeyFormatPkcs8: | 249 case blink::WebCryptoKeyFormatPkcs8: |
320 return CheckKeyCreationUsages(all_private_key_usages_, usages); | 250 return CheckKeyCreationUsages(all_private_key_usages_, usages); |
321 case blink::WebCryptoKeyFormatJwk: | 251 case blink::WebCryptoKeyFormatJwk: |
322 // The JWK could represent either a public key or private key. The usages | 252 // The JWK could represent either a public key or private key. The usages |
323 // must make sense for one of the two. The usages will be checked again by | 253 // must make sense for one of the two. The usages will be checked again by |
324 // ImportKeyJwk() once the key type has been determined. | 254 // ImportKeyJwk() once the key type has been determined. |
325 if (CheckKeyCreationUsages(all_private_key_usages_, usages) | 255 if (CheckKeyCreationUsages(all_private_key_usages_, usages).IsSuccess() || |
326 .IsSuccess() || | 256 CheckKeyCreationUsages(all_public_key_usages_, usages).IsSuccess()) { |
327 CheckKeyCreationUsages(all_public_key_usages_, usages) | |
328 .IsSuccess()) { | |
329 return Status::Success(); | 257 return Status::Success(); |
330 } | 258 } |
331 return Status::ErrorCreateKeyBadUsages(); | 259 return Status::ErrorCreateKeyBadUsages(); |
332 default: | 260 default: |
333 return Status::ErrorUnsupportedImportKeyFormat(); | 261 return Status::ErrorUnsupportedImportKeyFormat(); |
334 } | 262 } |
335 } | 263 } |
336 | 264 |
337 Status RsaHashedAlgorithm::ImportKeyPkcs8( | 265 Status RsaHashedAlgorithm::ImportKeyPkcs8( |
338 const CryptoData& key_data, | 266 const CryptoData& key_data, |
339 const blink::WebCryptoAlgorithm& algorithm, | 267 const blink::WebCryptoAlgorithm& algorithm, |
340 bool extractable, | 268 bool extractable, |
341 blink::WebCryptoKeyUsageMask usages, | 269 blink::WebCryptoKeyUsageMask usages, |
342 blink::WebCryptoKey* key) const { | 270 blink::WebCryptoKey* key) const { |
343 if (!key_data.byte_length()) | 271 crypto::ScopedEVP_PKEY private_key; |
344 return Status::ErrorImportEmptyKeyData(); | 272 Status status = |
| 273 ImportUnverifiedPkeyFromPkcs8(key_data, EVP_PKEY_RSA, &private_key); |
| 274 if (status.IsError()) |
| 275 return status; |
345 | 276 |
346 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 277 // Verify the parameters of the key. |
347 | |
348 crypto::ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(key_data.bytes()), | |
349 key_data.byte_length())); | |
350 if (!bio.get()) | |
351 return Status::ErrorUnexpected(); | |
352 | |
353 crypto::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type | |
354 p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL)); | |
355 if (!p8inf.get()) | |
356 return Status::DataError(); | |
357 | |
358 crypto::ScopedEVP_PKEY private_key(EVP_PKCS82PKEY(p8inf.get())); | |
359 if (!private_key.get()) | |
360 return Status::DataError(); | |
361 | |
362 if (EVP_PKEY_id(private_key.get()) != EVP_PKEY_RSA) | |
363 return Status::DataError(); // Data did not define an RSA key. | |
364 | |
365 // Verify the parameters of the key (because EVP_PKCS82PKEY() happily imports | |
366 // invalid keys). | |
367 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(private_key.get())); | 278 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(private_key.get())); |
368 if (!rsa.get()) | 279 if (!rsa.get()) |
369 return Status::ErrorUnexpected(); | 280 return Status::ErrorUnexpected(); |
370 if (!RSA_check_key(rsa.get())) | 281 if (!RSA_check_key(rsa.get())) |
371 return Status::DataError(); | 282 return Status::DataError(); |
372 | 283 |
373 // TODO(eroman): Validate the algorithm OID against the webcrypto provided | 284 // TODO(eroman): Validate the algorithm OID against the webcrypto provided |
374 // hash. http://crbug.com/389400 | 285 // hash. http://crbug.com/389400 |
375 | 286 |
376 return CreateWebCryptoPrivateKey(private_key.Pass(), | 287 return CreateWebCryptoRsaPrivateKey(private_key.Pass(), algorithm.id(), |
377 algorithm.id(), | 288 algorithm.rsaHashedImportParams()->hash(), |
378 algorithm.rsaHashedImportParams()->hash(), | 289 extractable, usages, key); |
379 extractable, | |
380 usages, | |
381 key); | |
382 } | 290 } |
383 | 291 |
384 Status RsaHashedAlgorithm::ImportKeySpki( | 292 Status RsaHashedAlgorithm::ImportKeySpki( |
385 const CryptoData& key_data, | 293 const CryptoData& key_data, |
386 const blink::WebCryptoAlgorithm& algorithm, | 294 const blink::WebCryptoAlgorithm& algorithm, |
387 bool extractable, | 295 bool extractable, |
388 blink::WebCryptoKeyUsageMask usages, | 296 blink::WebCryptoKeyUsageMask usages, |
389 blink::WebCryptoKey* key) const { | 297 blink::WebCryptoKey* key) const { |
390 if (!key_data.byte_length()) | 298 crypto::ScopedEVP_PKEY public_key; |
391 return Status::ErrorImportEmptyKeyData(); | 299 Status status = |
392 | 300 ImportUnverifiedPkeyFromSpki(key_data, EVP_PKEY_RSA, &public_key); |
393 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 301 if (status.IsError()) |
394 | 302 return status; |
395 crypto::ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(key_data.bytes()), | |
396 key_data.byte_length())); | |
397 if (!bio.get()) | |
398 return Status::ErrorUnexpected(); | |
399 | |
400 crypto::ScopedEVP_PKEY public_key(d2i_PUBKEY_bio(bio.get(), NULL)); | |
401 if (!public_key.get()) | |
402 return Status::DataError(); | |
403 | |
404 if (EVP_PKEY_id(public_key.get()) != EVP_PKEY_RSA) | |
405 return Status::DataError(); // Data did not define an RSA key. | |
406 | 303 |
407 // TODO(eroman): Validate the algorithm OID against the webcrypto provided | 304 // TODO(eroman): Validate the algorithm OID against the webcrypto provided |
408 // hash. http://crbug.com/389400 | 305 // hash. http://crbug.com/389400 |
409 | 306 |
410 return CreateWebCryptoPublicKey(public_key.Pass(), | 307 return CreateWebCryptoRsaPublicKey(public_key.Pass(), algorithm.id(), |
411 algorithm.id(), | 308 algorithm.rsaHashedImportParams()->hash(), |
412 algorithm.rsaHashedImportParams()->hash(), | 309 extractable, usages, key); |
413 extractable, | |
414 usages, | |
415 key); | |
416 } | 310 } |
417 | 311 |
418 Status RsaHashedAlgorithm::ImportKeyJwk( | 312 Status RsaHashedAlgorithm::ImportKeyJwk( |
419 const CryptoData& key_data, | 313 const CryptoData& key_data, |
420 const blink::WebCryptoAlgorithm& algorithm, | 314 const blink::WebCryptoAlgorithm& algorithm, |
421 bool extractable, | 315 bool extractable, |
422 blink::WebCryptoKeyUsageMask usages, | 316 blink::WebCryptoKeyUsageMask usages, |
423 blink::WebCryptoKey* key) const { | 317 blink::WebCryptoKey* key) const { |
424 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 318 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
425 | 319 |
(...skipping 11 matching lines...) Expand all Loading... |
437 | 331 |
438 // Once the key type is known, verify the usages. | 332 // Once the key type is known, verify the usages. |
439 status = CheckKeyCreationUsages( | 333 status = CheckKeyCreationUsages( |
440 jwk.is_private_key ? all_private_key_usages_ : all_public_key_usages_, | 334 jwk.is_private_key ? all_private_key_usages_ : all_public_key_usages_, |
441 usages); | 335 usages); |
442 if (status.IsError()) | 336 if (status.IsError()) |
443 return status; | 337 return status; |
444 | 338 |
445 return jwk.is_private_key | 339 return jwk.is_private_key |
446 ? ImportRsaPrivateKey(algorithm, extractable, usages, jwk, key) | 340 ? ImportRsaPrivateKey(algorithm, extractable, usages, jwk, key) |
447 : ImportRsaPublicKey(algorithm, | 341 : ImportRsaPublicKey(algorithm, extractable, usages, |
448 extractable, | 342 CryptoData(jwk.n), CryptoData(jwk.e), key); |
449 usages, | |
450 CryptoData(jwk.n), | |
451 CryptoData(jwk.e), | |
452 key); | |
453 } | 343 } |
454 | 344 |
455 Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key, | 345 Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key, |
456 std::vector<uint8_t>* buffer) const { | 346 std::vector<uint8_t>* buffer) const { |
457 if (key.type() != blink::WebCryptoKeyTypePrivate) | 347 if (key.type() != blink::WebCryptoKeyTypePrivate) |
458 return Status::ErrorUnexpectedKeyType(); | 348 return Status::ErrorUnexpectedKeyType(); |
459 *buffer = AsymKeyOpenSsl::Cast(key)->serialized_key_data(); | 349 *buffer = AsymKeyOpenSsl::Cast(key)->serialized_key_data(); |
460 return Status::Success(); | 350 return Status::Success(); |
461 } | 351 } |
462 | 352 |
463 Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key, | 353 Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key, |
464 std::vector<uint8_t>* buffer) const { | 354 std::vector<uint8_t>* buffer) const { |
465 if (key.type() != blink::WebCryptoKeyTypePublic) | 355 if (key.type() != blink::WebCryptoKeyTypePublic) |
466 return Status::ErrorUnexpectedKeyType(); | 356 return Status::ErrorUnexpectedKeyType(); |
467 *buffer = AsymKeyOpenSsl::Cast(key)->serialized_key_data(); | 357 *buffer = AsymKeyOpenSsl::Cast(key)->serialized_key_data(); |
468 return Status::Success(); | 358 return Status::Success(); |
469 } | 359 } |
470 | 360 |
471 Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key, | 361 Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key, |
472 std::vector<uint8_t>* buffer) const { | 362 std::vector<uint8_t>* buffer) const { |
473 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 363 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
474 | 364 |
475 EVP_PKEY* public_key = AsymKeyOpenSsl::Cast(key)->key(); | 365 EVP_PKEY* pkey = AsymKeyOpenSsl::Cast(key)->key(); |
476 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(public_key)); | 366 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey)); |
477 if (!rsa.get()) | 367 if (!rsa.get()) |
478 return Status::ErrorUnexpected(); | 368 return Status::ErrorUnexpected(); |
479 | 369 |
480 const char* jwk_algorithm = | 370 const char* jwk_algorithm = |
481 GetJwkAlgorithm(key.algorithm().rsaHashedParams()->hash().id()); | 371 GetJwkAlgorithm(key.algorithm().rsaHashedParams()->hash().id()); |
482 if (!jwk_algorithm) | 372 if (!jwk_algorithm) |
483 return Status::ErrorUnexpected(); | 373 return Status::ErrorUnexpected(); |
484 | 374 |
485 switch (key.type()) { | 375 switch (key.type()) { |
486 case blink::WebCryptoKeyTypePublic: | 376 case blink::WebCryptoKeyTypePublic: |
487 WriteRsaPublicKeyJwk(CryptoData(BIGNUMToVector(rsa->n)), | 377 WriteRsaPublicKeyJwk(CryptoData(BIGNUMToVector(rsa->n)), |
488 CryptoData(BIGNUMToVector(rsa->e)), | 378 CryptoData(BIGNUMToVector(rsa->e)), jwk_algorithm, |
489 jwk_algorithm, | 379 key.extractable(), key.usages(), buffer); |
490 key.extractable(), | |
491 key.usages(), | |
492 buffer); | |
493 return Status::Success(); | 380 return Status::Success(); |
494 case blink::WebCryptoKeyTypePrivate: | 381 case blink::WebCryptoKeyTypePrivate: |
495 WriteRsaPrivateKeyJwk(CryptoData(BIGNUMToVector(rsa->n)), | 382 WriteRsaPrivateKeyJwk(CryptoData(BIGNUMToVector(rsa->n)), |
496 CryptoData(BIGNUMToVector(rsa->e)), | 383 CryptoData(BIGNUMToVector(rsa->e)), |
497 CryptoData(BIGNUMToVector(rsa->d)), | 384 CryptoData(BIGNUMToVector(rsa->d)), |
498 CryptoData(BIGNUMToVector(rsa->p)), | 385 CryptoData(BIGNUMToVector(rsa->p)), |
499 CryptoData(BIGNUMToVector(rsa->q)), | 386 CryptoData(BIGNUMToVector(rsa->q)), |
500 CryptoData(BIGNUMToVector(rsa->dmp1)), | 387 CryptoData(BIGNUMToVector(rsa->dmp1)), |
501 CryptoData(BIGNUMToVector(rsa->dmq1)), | 388 CryptoData(BIGNUMToVector(rsa->dmq1)), |
502 CryptoData(BIGNUMToVector(rsa->iqmp)), | 389 CryptoData(BIGNUMToVector(rsa->iqmp)), |
503 jwk_algorithm, | 390 jwk_algorithm, key.extractable(), key.usages(), |
504 key.extractable(), | |
505 key.usages(), | |
506 buffer); | 391 buffer); |
507 return Status::Success(); | 392 return Status::Success(); |
508 | 393 |
509 default: | 394 default: |
510 return Status::ErrorUnexpected(); | 395 return Status::ErrorUnexpected(); |
511 } | 396 } |
512 } | 397 } |
513 | 398 |
514 } // namespace webcrypto | 399 } // namespace webcrypto |
515 | 400 |
516 } // namespace content | 401 } // namespace content |
OLD | NEW |