| 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 "components/webcrypto/algorithms/ec.h" | 5 #include "components/webcrypto/algorithms/ec.h" |
| 6 | 6 |
| 7 #include <openssl/bn.h> |
| 8 #include <openssl/bytestring.h> |
| 7 #include <openssl/ec.h> | 9 #include <openssl/ec.h> |
| 8 #include <openssl/ec_key.h> | 10 #include <openssl/ec_key.h> |
| 9 #include <openssl/evp.h> | 11 #include <openssl/evp.h> |
| 12 #include <openssl/mem.h> |
| 10 #include <stddef.h> | 13 #include <stddef.h> |
| 11 #include <utility> | 14 #include <utility> |
| 12 | 15 |
| 13 #include "base/logging.h" | 16 #include "base/logging.h" |
| 14 #include "base/macros.h" | 17 #include "base/macros.h" |
| 15 #include "components/webcrypto/algorithms/asymmetric_key_util.h" | 18 #include "components/webcrypto/algorithms/asymmetric_key_util.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/jwk.h" | 23 #include "components/webcrypto/jwk.h" |
| 21 #include "components/webcrypto/status.h" | 24 #include "components/webcrypto/status.h" |
| 22 #include "crypto/auto_cbb.h" | |
| 23 #include "crypto/openssl_util.h" | 25 #include "crypto/openssl_util.h" |
| 24 #include "crypto/scoped_openssl_types.h" | |
| 25 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 26 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| 26 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 27 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
| 27 | 28 |
| 28 namespace webcrypto { | 29 namespace webcrypto { |
| 29 | 30 |
| 30 namespace { | 31 namespace { |
| 31 | 32 |
| 32 // Maps a blink::WebCryptoNamedCurve to the corresponding NID used by | 33 // Maps a blink::WebCryptoNamedCurve to the corresponding NID used by |
| 33 // BoringSSL. | 34 // BoringSSL. |
| 34 Status WebCryptoCurveToNid(blink::WebCryptoNamedCurve named_curve, int* nid) { | 35 Status WebCryptoCurveToNid(blink::WebCryptoNamedCurve named_curve, int* nid) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 return status; | 135 return status; |
| 135 | 136 |
| 136 if (named_curve != expected_named_curve) | 137 if (named_curve != expected_named_curve) |
| 137 return Status::ErrorImportedEcKeyIncorrectCurve(); | 138 return Status::ErrorImportedEcKeyIncorrectCurve(); |
| 138 | 139 |
| 139 return Status::Success(); | 140 return Status::Success(); |
| 140 } | 141 } |
| 141 | 142 |
| 142 // Creates an EC_KEY for the given WebCryptoNamedCurve. | 143 // Creates an EC_KEY for the given WebCryptoNamedCurve. |
| 143 Status CreateEC_KEY(blink::WebCryptoNamedCurve named_curve, | 144 Status CreateEC_KEY(blink::WebCryptoNamedCurve named_curve, |
| 144 crypto::ScopedEC_KEY* ec) { | 145 bssl::UniquePtr<EC_KEY>* ec) { |
| 145 int curve_nid = 0; | 146 int curve_nid = 0; |
| 146 Status status = WebCryptoCurveToNid(named_curve, &curve_nid); | 147 Status status = WebCryptoCurveToNid(named_curve, &curve_nid); |
| 147 if (status.IsError()) | 148 if (status.IsError()) |
| 148 return status; | 149 return status; |
| 149 | 150 |
| 150 ec->reset(EC_KEY_new_by_curve_name(curve_nid)); | 151 ec->reset(EC_KEY_new_by_curve_name(curve_nid)); |
| 151 if (!ec->get()) | 152 if (!ec->get()) |
| 152 return Status::OperationError(); | 153 return Status::OperationError(); |
| 153 | 154 |
| 154 return Status::Success(); | 155 return Status::Success(); |
| 155 } | 156 } |
| 156 | 157 |
| 157 // Writes an unsigned BIGNUM into |jwk|, zero-padding it to a length of | 158 // Writes an unsigned BIGNUM into |jwk|, zero-padding it to a length of |
| 158 // |padded_length|. | 159 // |padded_length|. |
| 159 Status WritePaddedBIGNUM(const std::string& member_name, | 160 Status WritePaddedBIGNUM(const std::string& member_name, |
| 160 const BIGNUM* value, | 161 const BIGNUM* value, |
| 161 size_t padded_length, | 162 size_t padded_length, |
| 162 JwkWriter* jwk) { | 163 JwkWriter* jwk) { |
| 163 std::vector<uint8_t> padded_bytes(padded_length); | 164 std::vector<uint8_t> padded_bytes(padded_length); |
| 164 if (!BN_bn2bin_padded(padded_bytes.data(), padded_bytes.size(), value)) | 165 if (!BN_bn2bin_padded(padded_bytes.data(), padded_bytes.size(), value)) |
| 165 return Status::OperationError(); | 166 return Status::OperationError(); |
| 166 jwk->SetBytes(member_name, CryptoData(padded_bytes)); | 167 jwk->SetBytes(member_name, CryptoData(padded_bytes)); |
| 167 return Status::Success(); | 168 return Status::Success(); |
| 168 } | 169 } |
| 169 | 170 |
| 170 // Reads a fixed length BIGNUM from a JWK. | 171 // Reads a fixed length BIGNUM from a JWK. |
| 171 Status ReadPaddedBIGNUM(const JwkReader& jwk, | 172 Status ReadPaddedBIGNUM(const JwkReader& jwk, |
| 172 const std::string& member_name, | 173 const std::string& member_name, |
| 173 size_t expected_length, | 174 size_t expected_length, |
| 174 crypto::ScopedBIGNUM* out) { | 175 bssl::UniquePtr<BIGNUM>* out) { |
| 175 std::string bytes; | 176 std::string bytes; |
| 176 Status status = jwk.GetBytes(member_name, &bytes); | 177 Status status = jwk.GetBytes(member_name, &bytes); |
| 177 if (status.IsError()) | 178 if (status.IsError()) |
| 178 return status; | 179 return status; |
| 179 | 180 |
| 180 if (bytes.size() != expected_length) { | 181 if (bytes.size() != expected_length) { |
| 181 return Status::JwkOctetStringWrongLength(member_name, expected_length, | 182 return Status::JwkOctetStringWrongLength(member_name, expected_length, |
| 182 bytes.size()); | 183 bytes.size()); |
| 183 } | 184 } |
| 184 | 185 |
| 185 out->reset(CreateBIGNUM(bytes)); | 186 out->reset(CreateBIGNUM(bytes)); |
| 186 return Status::Success(); | 187 return Status::Success(); |
| 187 } | 188 } |
| 188 | 189 |
| 189 int GetGroupDegreeInBytes(EC_KEY* ec) { | 190 int GetGroupDegreeInBytes(EC_KEY* ec) { |
| 190 const EC_GROUP* group = EC_KEY_get0_group(ec); | 191 const EC_GROUP* group = EC_KEY_get0_group(ec); |
| 191 return NumBitsToBytes(EC_GROUP_get_degree(group)); | 192 return NumBitsToBytes(EC_GROUP_get_degree(group)); |
| 192 } | 193 } |
| 193 | 194 |
| 194 // Extracts the public key as affine coordinates (x,y). | 195 // Extracts the public key as affine coordinates (x,y). |
| 195 Status GetPublicKey(EC_KEY* ec, | 196 Status GetPublicKey(EC_KEY* ec, |
| 196 crypto::ScopedBIGNUM* x, | 197 bssl::UniquePtr<BIGNUM>* x, |
| 197 crypto::ScopedBIGNUM* y) { | 198 bssl::UniquePtr<BIGNUM>* y) { |
| 198 const EC_GROUP* group = EC_KEY_get0_group(ec); | 199 const EC_GROUP* group = EC_KEY_get0_group(ec); |
| 199 const EC_POINT* point = EC_KEY_get0_public_key(ec); | 200 const EC_POINT* point = EC_KEY_get0_public_key(ec); |
| 200 | 201 |
| 201 x->reset(BN_new()); | 202 x->reset(BN_new()); |
| 202 y->reset(BN_new()); | 203 y->reset(BN_new()); |
| 203 | 204 |
| 204 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x->get(), y->get(), | 205 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x->get(), y->get(), |
| 205 NULL)) { | 206 NULL)) { |
| 206 return Status::OperationError(); | 207 return Status::OperationError(); |
| 207 } | 208 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 231 combined_usages, all_public_key_usages_, all_private_key_usages_, | 232 combined_usages, all_public_key_usages_, all_private_key_usages_, |
| 232 &public_usages, &private_usages); | 233 &public_usages, &private_usages); |
| 233 if (status.IsError()) | 234 if (status.IsError()) |
| 234 return status; | 235 return status; |
| 235 | 236 |
| 236 const blink::WebCryptoEcKeyGenParams* params = algorithm.ecKeyGenParams(); | 237 const blink::WebCryptoEcKeyGenParams* params = algorithm.ecKeyGenParams(); |
| 237 | 238 |
| 238 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 239 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 239 | 240 |
| 240 // Generate an EC key pair. | 241 // Generate an EC key pair. |
| 241 crypto::ScopedEC_KEY ec_private_key; | 242 bssl::UniquePtr<EC_KEY> ec_private_key; |
| 242 status = CreateEC_KEY(params->namedCurve(), &ec_private_key); | 243 status = CreateEC_KEY(params->namedCurve(), &ec_private_key); |
| 243 if (status.IsError()) | 244 if (status.IsError()) |
| 244 return status; | 245 return status; |
| 245 | 246 |
| 246 if (!EC_KEY_generate_key(ec_private_key.get())) | 247 if (!EC_KEY_generate_key(ec_private_key.get())) |
| 247 return Status::OperationError(); | 248 return Status::OperationError(); |
| 248 | 249 |
| 249 // Construct an EVP_PKEY for the private key. | 250 // Construct an EVP_PKEY for the private key. |
| 250 crypto::ScopedEVP_PKEY private_pkey(EVP_PKEY_new()); | 251 bssl::UniquePtr<EVP_PKEY> private_pkey(EVP_PKEY_new()); |
| 251 if (!private_pkey || | 252 if (!private_pkey || |
| 252 !EVP_PKEY_set1_EC_KEY(private_pkey.get(), ec_private_key.get())) { | 253 !EVP_PKEY_set1_EC_KEY(private_pkey.get(), ec_private_key.get())) { |
| 253 return Status::OperationError(); | 254 return Status::OperationError(); |
| 254 } | 255 } |
| 255 | 256 |
| 256 // Construct an EVP_PKEY for just the public key. | 257 // Construct an EVP_PKEY for just the public key. |
| 257 crypto::ScopedEC_KEY ec_public_key; | 258 bssl::UniquePtr<EC_KEY> ec_public_key; |
| 258 crypto::ScopedEVP_PKEY public_pkey(EVP_PKEY_new()); | 259 bssl::UniquePtr<EVP_PKEY> public_pkey(EVP_PKEY_new()); |
| 259 status = CreateEC_KEY(params->namedCurve(), &ec_public_key); | 260 status = CreateEC_KEY(params->namedCurve(), &ec_public_key); |
| 260 if (status.IsError()) | 261 if (status.IsError()) |
| 261 return status; | 262 return status; |
| 262 if (!EC_KEY_set_public_key(ec_public_key.get(), | 263 if (!EC_KEY_set_public_key(ec_public_key.get(), |
| 263 EC_KEY_get0_public_key(ec_private_key.get()))) { | 264 EC_KEY_get0_public_key(ec_private_key.get()))) { |
| 264 return Status::OperationError(); | 265 return Status::OperationError(); |
| 265 } | 266 } |
| 266 if (!public_pkey || | 267 if (!public_pkey || |
| 267 !EVP_PKEY_set1_EC_KEY(public_pkey.get(), ec_public_key.get())) { | 268 !EVP_PKEY_set1_EC_KEY(public_pkey.get(), ec_public_key.get())) { |
| 268 return Status::OperationError(); | 269 return Status::OperationError(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 337 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 337 | 338 |
| 338 Status status = CheckKeyCreationUsages(all_public_key_usages_, usages); | 339 Status status = CheckKeyCreationUsages(all_public_key_usages_, usages); |
| 339 if (status.IsError()) | 340 if (status.IsError()) |
| 340 return status; | 341 return status; |
| 341 | 342 |
| 342 const blink::WebCryptoEcKeyImportParams* params = | 343 const blink::WebCryptoEcKeyImportParams* params = |
| 343 algorithm.ecKeyImportParams(); | 344 algorithm.ecKeyImportParams(); |
| 344 | 345 |
| 345 // Create an EC_KEY. | 346 // Create an EC_KEY. |
| 346 crypto::ScopedEC_KEY ec; | 347 bssl::UniquePtr<EC_KEY> ec; |
| 347 status = CreateEC_KEY(params->namedCurve(), &ec); | 348 status = CreateEC_KEY(params->namedCurve(), &ec); |
| 348 if (status.IsError()) | 349 if (status.IsError()) |
| 349 return status; | 350 return status; |
| 350 | 351 |
| 351 crypto::ScopedEC_POINT point(EC_POINT_new(EC_KEY_get0_group(ec.get()))); | 352 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(EC_KEY_get0_group(ec.get()))); |
| 352 if (!point.get()) | 353 if (!point.get()) |
| 353 return Status::OperationError(); | 354 return Status::OperationError(); |
| 354 | 355 |
| 355 // Convert the "raw" input from X9.62 format to an EC_POINT. | 356 // Convert the "raw" input from X9.62 format to an EC_POINT. |
| 356 if (!EC_POINT_oct2point(EC_KEY_get0_group(ec.get()), point.get(), | 357 if (!EC_POINT_oct2point(EC_KEY_get0_group(ec.get()), point.get(), |
| 357 key_data.bytes(), key_data.byte_length(), nullptr)) { | 358 key_data.bytes(), key_data.byte_length(), nullptr)) { |
| 358 return Status::DataError(); | 359 return Status::DataError(); |
| 359 } | 360 } |
| 360 | 361 |
| 361 // Copy the point (public key) into the EC_KEY. | 362 // Copy the point (public key) into the EC_KEY. |
| 362 if (!EC_KEY_set_public_key(ec.get(), point.get())) | 363 if (!EC_KEY_set_public_key(ec.get(), point.get())) |
| 363 return Status::OperationError(); | 364 return Status::OperationError(); |
| 364 | 365 |
| 365 // Verify the key. | 366 // Verify the key. |
| 366 if (!EC_KEY_check_key(ec.get())) | 367 if (!EC_KEY_check_key(ec.get())) |
| 367 return Status::ErrorEcKeyInvalid(); | 368 return Status::ErrorEcKeyInvalid(); |
| 368 | 369 |
| 369 // Wrap the EC_KEY into an EVP_PKEY. | 370 // Wrap the EC_KEY into an EVP_PKEY. |
| 370 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 371 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new()); |
| 371 if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get())) | 372 if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get())) |
| 372 return Status::OperationError(); | 373 return Status::OperationError(); |
| 373 | 374 |
| 374 blink::WebCryptoKeyAlgorithm key_algorithm = | 375 blink::WebCryptoKeyAlgorithm key_algorithm = |
| 375 blink::WebCryptoKeyAlgorithm::createEc(algorithm.id(), | 376 blink::WebCryptoKeyAlgorithm::createEc(algorithm.id(), |
| 376 params->namedCurve()); | 377 params->namedCurve()); |
| 377 | 378 |
| 378 // Wrap the EVP_PKEY into a WebCryptoKey | 379 // Wrap the EVP_PKEY into a WebCryptoKey |
| 379 return CreateWebCryptoPublicKey(std::move(pkey), key_algorithm, extractable, | 380 return CreateWebCryptoPublicKey(std::move(pkey), key_algorithm, extractable, |
| 380 usages, key); | 381 usages, key); |
| 381 } | 382 } |
| 382 | 383 |
| 383 Status EcAlgorithm::ImportKeyPkcs8(const CryptoData& key_data, | 384 Status EcAlgorithm::ImportKeyPkcs8(const CryptoData& key_data, |
| 384 const blink::WebCryptoAlgorithm& algorithm, | 385 const blink::WebCryptoAlgorithm& algorithm, |
| 385 bool extractable, | 386 bool extractable, |
| 386 blink::WebCryptoKeyUsageMask usages, | 387 blink::WebCryptoKeyUsageMask usages, |
| 387 blink::WebCryptoKey* key) const { | 388 blink::WebCryptoKey* key) const { |
| 388 Status status = CheckKeyCreationUsages(all_private_key_usages_, usages); | 389 Status status = CheckKeyCreationUsages(all_private_key_usages_, usages); |
| 389 if (status.IsError()) | 390 if (status.IsError()) |
| 390 return status; | 391 return status; |
| 391 | 392 |
| 392 crypto::ScopedEVP_PKEY private_key; | 393 bssl::UniquePtr<EVP_PKEY> private_key; |
| 393 status = ImportUnverifiedPkeyFromPkcs8(key_data, EVP_PKEY_EC, &private_key); | 394 status = ImportUnverifiedPkeyFromPkcs8(key_data, EVP_PKEY_EC, &private_key); |
| 394 if (status.IsError()) | 395 if (status.IsError()) |
| 395 return status; | 396 return status; |
| 396 | 397 |
| 397 const blink::WebCryptoEcKeyImportParams* params = | 398 const blink::WebCryptoEcKeyImportParams* params = |
| 398 algorithm.ecKeyImportParams(); | 399 algorithm.ecKeyImportParams(); |
| 399 | 400 |
| 400 status = VerifyEcKeyAfterSpkiOrPkcs8Import(private_key.get(), | 401 status = VerifyEcKeyAfterSpkiOrPkcs8Import(private_key.get(), |
| 401 params->namedCurve()); | 402 params->namedCurve()); |
| 402 if (status.IsError()) | 403 if (status.IsError()) |
| 403 return status; | 404 return status; |
| 404 | 405 |
| 405 return CreateWebCryptoPrivateKey(std::move(private_key), | 406 return CreateWebCryptoPrivateKey(std::move(private_key), |
| 406 blink::WebCryptoKeyAlgorithm::createEc( | 407 blink::WebCryptoKeyAlgorithm::createEc( |
| 407 algorithm.id(), params->namedCurve()), | 408 algorithm.id(), params->namedCurve()), |
| 408 extractable, usages, key); | 409 extractable, usages, key); |
| 409 } | 410 } |
| 410 | 411 |
| 411 Status EcAlgorithm::ImportKeySpki(const CryptoData& key_data, | 412 Status EcAlgorithm::ImportKeySpki(const CryptoData& key_data, |
| 412 const blink::WebCryptoAlgorithm& algorithm, | 413 const blink::WebCryptoAlgorithm& algorithm, |
| 413 bool extractable, | 414 bool extractable, |
| 414 blink::WebCryptoKeyUsageMask usages, | 415 blink::WebCryptoKeyUsageMask usages, |
| 415 blink::WebCryptoKey* key) const { | 416 blink::WebCryptoKey* key) const { |
| 416 Status status = CheckKeyCreationUsages(all_public_key_usages_, usages); | 417 Status status = CheckKeyCreationUsages(all_public_key_usages_, usages); |
| 417 if (status.IsError()) | 418 if (status.IsError()) |
| 418 return status; | 419 return status; |
| 419 | 420 |
| 420 crypto::ScopedEVP_PKEY public_key; | 421 bssl::UniquePtr<EVP_PKEY> public_key; |
| 421 status = ImportUnverifiedPkeyFromSpki(key_data, EVP_PKEY_EC, &public_key); | 422 status = ImportUnverifiedPkeyFromSpki(key_data, EVP_PKEY_EC, &public_key); |
| 422 if (status.IsError()) | 423 if (status.IsError()) |
| 423 return status; | 424 return status; |
| 424 | 425 |
| 425 const blink::WebCryptoEcKeyImportParams* params = | 426 const blink::WebCryptoEcKeyImportParams* params = |
| 426 algorithm.ecKeyImportParams(); | 427 algorithm.ecKeyImportParams(); |
| 427 | 428 |
| 428 status = | 429 status = |
| 429 VerifyEcKeyAfterSpkiOrPkcs8Import(public_key.get(), params->namedCurve()); | 430 VerifyEcKeyAfterSpkiOrPkcs8Import(public_key.get(), params->namedCurve()); |
| 430 if (status.IsError()) | 431 if (status.IsError()) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 if (is_private_key) { | 480 if (is_private_key) { |
| 480 status = CheckKeyCreationUsages(all_private_key_usages_, usages); | 481 status = CheckKeyCreationUsages(all_private_key_usages_, usages); |
| 481 } else { | 482 } else { |
| 482 status = CheckKeyCreationUsages(all_public_key_usages_, usages); | 483 status = CheckKeyCreationUsages(all_public_key_usages_, usages); |
| 483 } | 484 } |
| 484 | 485 |
| 485 if (status.IsError()) | 486 if (status.IsError()) |
| 486 return status; | 487 return status; |
| 487 | 488 |
| 488 // Create an EC_KEY. | 489 // Create an EC_KEY. |
| 489 crypto::ScopedEC_KEY ec; | 490 bssl::UniquePtr<EC_KEY> ec; |
| 490 status = CreateEC_KEY(params->namedCurve(), &ec); | 491 status = CreateEC_KEY(params->namedCurve(), &ec); |
| 491 if (status.IsError()) | 492 if (status.IsError()) |
| 492 return status; | 493 return status; |
| 493 | 494 |
| 494 // JWK requires the length of x, y, d to match the group degree. | 495 // JWK requires the length of x, y, d to match the group degree. |
| 495 int degree_bytes = GetGroupDegreeInBytes(ec.get()); | 496 int degree_bytes = GetGroupDegreeInBytes(ec.get()); |
| 496 | 497 |
| 497 // Read the public key's uncompressed affine coordinates. | 498 // Read the public key's uncompressed affine coordinates. |
| 498 crypto::ScopedBIGNUM x; | 499 bssl::UniquePtr<BIGNUM> x; |
| 499 status = ReadPaddedBIGNUM(jwk, "x", degree_bytes, &x); | 500 status = ReadPaddedBIGNUM(jwk, "x", degree_bytes, &x); |
| 500 if (status.IsError()) | 501 if (status.IsError()) |
| 501 return status; | 502 return status; |
| 502 | 503 |
| 503 crypto::ScopedBIGNUM y; | 504 bssl::UniquePtr<BIGNUM> y; |
| 504 status = ReadPaddedBIGNUM(jwk, "y", degree_bytes, &y); | 505 status = ReadPaddedBIGNUM(jwk, "y", degree_bytes, &y); |
| 505 if (status.IsError()) | 506 if (status.IsError()) |
| 506 return status; | 507 return status; |
| 507 | 508 |
| 508 // TODO(eroman): Distinguish more accurately between a DataError and | 509 // TODO(eroman): Distinguish more accurately between a DataError and |
| 509 // OperationError. In general if this fails it was due to the key being an | 510 // OperationError. In general if this fails it was due to the key being an |
| 510 // invalid EC key. | 511 // invalid EC key. |
| 511 if (!EC_KEY_set_public_key_affine_coordinates(ec.get(), x.get(), y.get())) | 512 if (!EC_KEY_set_public_key_affine_coordinates(ec.get(), x.get(), y.get())) |
| 512 return Status::DataError(); | 513 return Status::DataError(); |
| 513 | 514 |
| 514 // Extract the "d" parameters. | 515 // Extract the "d" parameters. |
| 515 if (is_private_key) { | 516 if (is_private_key) { |
| 516 crypto::ScopedBIGNUM d; | 517 bssl::UniquePtr<BIGNUM> d; |
| 517 status = ReadPaddedBIGNUM(jwk, "d", degree_bytes, &d); | 518 status = ReadPaddedBIGNUM(jwk, "d", degree_bytes, &d); |
| 518 if (status.IsError()) | 519 if (status.IsError()) |
| 519 return status; | 520 return status; |
| 520 | 521 |
| 521 if (!EC_KEY_set_private_key(ec.get(), d.get())) | 522 if (!EC_KEY_set_private_key(ec.get(), d.get())) |
| 522 return Status::OperationError(); | 523 return Status::OperationError(); |
| 523 } | 524 } |
| 524 | 525 |
| 525 // Verify the key. | 526 // Verify the key. |
| 526 if (!EC_KEY_check_key(ec.get())) | 527 if (!EC_KEY_check_key(ec.get())) |
| 527 return Status::ErrorEcKeyInvalid(); | 528 return Status::ErrorEcKeyInvalid(); |
| 528 | 529 |
| 529 // Wrap the EC_KEY into an EVP_PKEY. | 530 // Wrap the EC_KEY into an EVP_PKEY. |
| 530 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 531 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new()); |
| 531 if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get())) | 532 if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get())) |
| 532 return Status::OperationError(); | 533 return Status::OperationError(); |
| 533 | 534 |
| 534 blink::WebCryptoKeyAlgorithm key_algorithm = | 535 blink::WebCryptoKeyAlgorithm key_algorithm = |
| 535 blink::WebCryptoKeyAlgorithm::createEc(algorithm.id(), | 536 blink::WebCryptoKeyAlgorithm::createEc(algorithm.id(), |
| 536 params->namedCurve()); | 537 params->namedCurve()); |
| 537 | 538 |
| 538 // Wrap the EVP_PKEY into a WebCryptoKey | 539 // Wrap the EVP_PKEY into a WebCryptoKey |
| 539 if (is_private_key) { | 540 if (is_private_key) { |
| 540 return CreateWebCryptoPrivateKey(std::move(pkey), key_algorithm, | 541 return CreateWebCryptoPrivateKey(std::move(pkey), key_algorithm, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 553 | 554 |
| 554 EVP_PKEY* pkey = GetEVP_PKEY(key); | 555 EVP_PKEY* pkey = GetEVP_PKEY(key); |
| 555 | 556 |
| 556 EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey); | 557 EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey); |
| 557 if (!ec) | 558 if (!ec) |
| 558 return Status::ErrorUnexpected(); | 559 return Status::ErrorUnexpected(); |
| 559 | 560 |
| 560 // Serialize the public key as an uncompressed point in X9.62 form. | 561 // Serialize the public key as an uncompressed point in X9.62 form. |
| 561 uint8_t* raw; | 562 uint8_t* raw; |
| 562 size_t raw_len; | 563 size_t raw_len; |
| 563 crypto::AutoCBB cbb; | 564 bssl::ScopedCBB cbb; |
| 564 if (!CBB_init(cbb.get(), 0) || | 565 if (!CBB_init(cbb.get(), 0) || |
| 565 !EC_POINT_point2cbb(cbb.get(), EC_KEY_get0_group(ec), | 566 !EC_POINT_point2cbb(cbb.get(), EC_KEY_get0_group(ec), |
| 566 EC_KEY_get0_public_key(ec), | 567 EC_KEY_get0_public_key(ec), |
| 567 POINT_CONVERSION_UNCOMPRESSED, nullptr) || | 568 POINT_CONVERSION_UNCOMPRESSED, nullptr) || |
| 568 !CBB_finish(cbb.get(), &raw, &raw_len)) { | 569 !CBB_finish(cbb.get(), &raw, &raw_len)) { |
| 569 return Status::OperationError(); | 570 return Status::OperationError(); |
| 570 } | 571 } |
| 571 buffer->assign(raw, raw + raw_len); | 572 buffer->assign(raw, raw + raw_len); |
| 572 OPENSSL_free(raw); | 573 OPENSSL_free(raw); |
| 573 | 574 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 std::string crv; | 616 std::string crv; |
| 616 Status status = | 617 Status status = |
| 617 WebCryptoCurveToJwkCrv(key.algorithm().ecParams()->namedCurve(), &crv); | 618 WebCryptoCurveToJwkCrv(key.algorithm().ecParams()->namedCurve(), &crv); |
| 618 if (status.IsError()) | 619 if (status.IsError()) |
| 619 return status; | 620 return status; |
| 620 | 621 |
| 621 int degree_bytes = GetGroupDegreeInBytes(ec); | 622 int degree_bytes = GetGroupDegreeInBytes(ec); |
| 622 | 623 |
| 623 jwk.SetString("crv", crv); | 624 jwk.SetString("crv", crv); |
| 624 | 625 |
| 625 crypto::ScopedBIGNUM x; | 626 bssl::UniquePtr<BIGNUM> x; |
| 626 crypto::ScopedBIGNUM y; | 627 bssl::UniquePtr<BIGNUM> y; |
| 627 status = GetPublicKey(ec, &x, &y); | 628 status = GetPublicKey(ec, &x, &y); |
| 628 if (status.IsError()) | 629 if (status.IsError()) |
| 629 return status; | 630 return status; |
| 630 | 631 |
| 631 status = WritePaddedBIGNUM("x", x.get(), degree_bytes, &jwk); | 632 status = WritePaddedBIGNUM("x", x.get(), degree_bytes, &jwk); |
| 632 if (status.IsError()) | 633 if (status.IsError()) |
| 633 return status; | 634 return status; |
| 634 | 635 |
| 635 status = WritePaddedBIGNUM("y", y.get(), degree_bytes, &jwk); | 636 status = WritePaddedBIGNUM("y", y.get(), degree_bytes, &jwk); |
| 636 if (status.IsError()) | 637 if (status.IsError()) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 | 688 |
| 688 if (algorithm.ecParams()->namedCurve() != | 689 if (algorithm.ecParams()->namedCurve() != |
| 689 key->algorithm().ecParams()->namedCurve()) { | 690 key->algorithm().ecParams()->namedCurve()) { |
| 690 return Status::ErrorUnexpected(); | 691 return Status::ErrorUnexpected(); |
| 691 } | 692 } |
| 692 | 693 |
| 693 return Status::Success(); | 694 return Status::Success(); |
| 694 } | 695 } |
| 695 | 696 |
| 696 } // namespace webcrypto | 697 } // namespace webcrypto |
| OLD | NEW |