| 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 |