diff options
Diffstat (limited to 'chromium/device/fido/virtual_fido_device.cc')
-rw-r--r-- | chromium/device/fido/virtual_fido_device.cc | 155 |
1 files changed, 130 insertions, 25 deletions
diff --git a/chromium/device/fido/virtual_fido_device.cc b/chromium/device/fido/virtual_fido_device.cc index 6f4dcad4bb7..f01e9dc0f90 100644 --- a/chromium/device/fido/virtual_fido_device.cc +++ b/chromium/device/fido/virtual_fido_device.cc @@ -9,7 +9,9 @@ #include <utility> #include "base/bind.h" +#include "base/logging.h" #include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" #include "components/cbor/values.h" #include "components/cbor/writer.h" #include "crypto/ec_private_key.h" @@ -50,7 +52,7 @@ constexpr uint8_t kAttestationKey[]{ // CBBFunctionToVector converts a BoringSSL function that writes to a CBB to one // that returns a std::vector. Invoke for a function, f, with: -// CBBFunctionToVector<decltype(f), f>(args, to, f); +// CBBFunctionToVector<decltype(&f), f>(args, to, f); template <typename F, F function, typename... Args> std::vector<uint8_t> CBBFunctionToVector(Args&&... args) { uint8_t* der = nullptr; @@ -101,7 +103,7 @@ class EVPBackedPrivateKey : public VirtualFidoDevice::PrivateKey { } std::vector<uint8_t> GetPKCS8PrivateKey() const override { - return CBBFunctionToVector<decltype(EVP_marshal_private_key), + return CBBFunctionToVector<decltype(&EVP_marshal_private_key), EVP_marshal_private_key>(pkey_.get()); } @@ -121,7 +123,7 @@ class P256PrivateKey : public EVPBackedPrivateKey { std::vector<uint8_t> GetX962PublicKey() const override { const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey_.get()); - return CBBFunctionToVector<decltype(EC_POINT_point2cbb), + return CBBFunctionToVector<decltype(&EC_POINT_point2cbb), EC_POINT_point2cbb>( EC_KEY_get0_group(ec_key), EC_KEY_get0_public_key(ec_key), POINT_CONVERSION_UNCOMPRESSED, /*ctx=*/nullptr); @@ -129,7 +131,7 @@ class P256PrivateKey : public EVPBackedPrivateKey { std::unique_ptr<PublicKey> GetPublicKey() const override { return P256PublicKey::ParseX962Uncompressed( - static_cast<int32_t>(CoseAlgorithmIdentifier::kCoseEs256), + static_cast<int32_t>(CoseAlgorithmIdentifier::kEs256), GetX962PublicKey()); } @@ -159,7 +161,7 @@ class RSAPrivateKey : public EVPBackedPrivateKey { cbor::Value::MapValue map; map.emplace(static_cast<int64_t>(CoseKeyKey::kAlg), - static_cast<int64_t>(CoseAlgorithmIdentifier::kCoseRs256)); + static_cast<int64_t>(CoseAlgorithmIdentifier::kRs256)); map.emplace(static_cast<int64_t>(CoseKeyKey::kKty), static_cast<int64_t>(CoseKeyTypes::kRSA)); map.emplace(static_cast<int64_t>(CoseKeyKey::kRSAModulus), @@ -171,11 +173,11 @@ class RSAPrivateKey : public EVPBackedPrivateKey { cbor::Writer::Write(cbor::Value(std::move(map)))); std::vector<uint8_t> der_bytes( - CBBFunctionToVector<decltype(EVP_marshal_public_key), + CBBFunctionToVector<decltype(&EVP_marshal_public_key), EVP_marshal_public_key>(pkey_.get())); return std::make_unique<PublicKey>( - static_cast<int32_t>(CoseAlgorithmIdentifier::kCoseRs256), *cbor_bytes, + static_cast<int32_t>(CoseAlgorithmIdentifier::kRs256), *cbor_bytes, std::move(der_bytes)); } @@ -185,6 +187,77 @@ class RSAPrivateKey : public EVPBackedPrivateKey { } }; +class Ed25519PrivateKey : public EVPBackedPrivateKey { + public: + Ed25519PrivateKey() + : EVPBackedPrivateKey(EVP_PKEY_ED25519, ConfigureKeyGen) {} + + explicit Ed25519PrivateKey(bssl::UniquePtr<EVP_PKEY> pkey) + : EVPBackedPrivateKey(std::move(pkey)) {} + + std::unique_ptr<PublicKey> GetPublicKey() const override { + uint8_t public_key[32]; + size_t public_key_len = sizeof(public_key); + CHECK( + EVP_PKEY_get_raw_public_key(pkey_.get(), public_key, &public_key_len) && + public_key_len == sizeof(public_key)); + + cbor::Value::MapValue map; + map.emplace(static_cast<int64_t>(CoseKeyKey::kAlg), + static_cast<int64_t>(CoseAlgorithmIdentifier::kEdDSA)); + map.emplace(static_cast<int64_t>(CoseKeyKey::kKty), + static_cast<int64_t>(CoseKeyTypes::kOKP)); + map.emplace(static_cast<int64_t>(CoseKeyKey::kEllipticCurve), + static_cast<int64_t>(CoseCurves::kEd25519)); + map.emplace(static_cast<int64_t>(CoseKeyKey::kEllipticX), + base::span<const uint8_t>(public_key, sizeof(public_key))); + + base::Optional<std::vector<uint8_t>> cbor_bytes( + cbor::Writer::Write(cbor::Value(std::move(map)))); + + std::vector<uint8_t> der_bytes( + CBBFunctionToVector<decltype(&EVP_marshal_public_key), + EVP_marshal_public_key>(pkey_.get())); + + return std::make_unique<PublicKey>( + static_cast<int32_t>(CoseAlgorithmIdentifier::kRs256), *cbor_bytes, + std::move(der_bytes)); + } + + private: + static int ConfigureKeyGen(EVP_PKEY_CTX* ctx) { return 1; } +}; + +class InvalidForTestingPrivateKey : public VirtualFidoDevice::PrivateKey { + public: + InvalidForTestingPrivateKey() = default; + + std::vector<uint8_t> Sign(base::span<const uint8_t> message) override { + return {'s', 'i', 'g'}; + } + + std::vector<uint8_t> GetPKCS8PrivateKey() const override { + CHECK(false); + return {}; + } + + std::unique_ptr<PublicKey> GetPublicKey() const override { + cbor::Value::MapValue map; + map.emplace( + static_cast<int64_t>(CoseKeyKey::kAlg), + static_cast<int64_t>(CoseAlgorithmIdentifier::kInvalidForTesting)); + map.emplace(static_cast<int64_t>(CoseKeyKey::kKty), + static_cast<int64_t>(CoseKeyTypes::kInvalidForTesting)); + + base::Optional<std::vector<uint8_t>> cbor_bytes( + cbor::Writer::Write(cbor::Value(std::move(map)))); + + return std::make_unique<PublicKey>( + static_cast<int32_t>(CoseAlgorithmIdentifier::kInvalidForTesting), + *cbor_bytes, base::nullopt); + } +}; + } // namespace // VirtualFidoDevice::PrivateKey ---------------------------------------------- @@ -222,11 +295,39 @@ VirtualFidoDevice::PrivateKey::FromPKCS8( case EVP_PKEY_RSA: return std::unique_ptr<PrivateKey>(new RSAPrivateKey(std::move(pkey))); + case EVP_PKEY_ED25519: + return std::unique_ptr<PrivateKey>( + new Ed25519PrivateKey(std::move(pkey))); + default: return base::nullopt; } } +// static +std::unique_ptr<VirtualFidoDevice::PrivateKey> +VirtualFidoDevice::PrivateKey::FreshP256Key() { + return std::make_unique<P256PrivateKey>(); +} + +// static +std::unique_ptr<VirtualFidoDevice::PrivateKey> +VirtualFidoDevice::PrivateKey::FreshRSAKey() { + return std::make_unique<RSAPrivateKey>(); +} + +// static +std::unique_ptr<VirtualFidoDevice::PrivateKey> +VirtualFidoDevice::PrivateKey::FreshEd25519Key() { + return std::make_unique<Ed25519PrivateKey>(); +} + +// static +std::unique_ptr<VirtualFidoDevice::PrivateKey> +VirtualFidoDevice::PrivateKey::FreshInvalidForTestingKey() { + return std::make_unique<InvalidForTestingPrivateKey>(); +} + // VirtualFidoDevice::RegistrationData ---------------------------------------- VirtualFidoDevice::RegistrationData::RegistrationData() = default; @@ -242,8 +343,9 @@ VirtualFidoDevice::RegistrationData::RegistrationData(RegistrationData&& data) = default; VirtualFidoDevice::RegistrationData::~RegistrationData() = default; -VirtualFidoDevice::RegistrationData& VirtualFidoDevice::RegistrationData:: -operator=(RegistrationData&& other) = default; +VirtualFidoDevice::RegistrationData& +VirtualFidoDevice::RegistrationData::operator=(RegistrationData&& other) = + default; // VirtualFidoDevice::State --------------------------------------------------- @@ -258,7 +360,7 @@ bool VirtualFidoDevice::State::InjectRegistration( auto application_parameter = fido_parsing_utils::CreateSHA256Hash(relying_party_id); - RegistrationData registration(FreshP256Key(), + RegistrationData registration(PrivateKey::FreshP256Key(), std::move(application_parameter), 0 /* signature counter */); @@ -304,7 +406,7 @@ bool VirtualFidoDevice::State::InjectResidentKey( device::PublicKeyCredentialUserEntity user) { return InjectResidentKey(std::move(credential_id), std::move(rp), std::move(user), /*signature_counter=*/0, - FreshP256Key()); + PrivateKey::FreshP256Key()); } bool VirtualFidoDevice::State::InjectResidentKey( @@ -336,18 +438,6 @@ std::vector<uint8_t> VirtualFidoDevice::GetAttestationKey() { return fido_parsing_utils::Materialize(kAttestationKey); } -// static -std::unique_ptr<VirtualFidoDevice::PrivateKey> -VirtualFidoDevice::FreshP256Key() { - return std::make_unique<P256PrivateKey>(); -} - -// static -std::unique_ptr<VirtualFidoDevice::PrivateKey> -VirtualFidoDevice::FreshRSAKey() { - return std::unique_ptr<PrivateKey>(new RSAPrivateKey); -} - bool VirtualFidoDevice::Sign(crypto::ECPrivateKey* private_key, base::span<const uint8_t> sign_buffer, std::vector<uint8_t>* signature) { @@ -387,8 +477,21 @@ VirtualFidoDevice::GenerateAttestationCertificate( 8 - transport_bit - 1, // trailing bits unused 0b10000000 >> transport_bit, // transport }; + + // https://www.w3.org/TR/webauthn/#packed-attestation-cert-requirements + // The Basic Constraints extension MUST have the CA component set to false. + static constexpr uint8_t kBasicContraintsOID[] = {0x55, 0x1d, 0x13}; + static constexpr uint8_t kBasicContraintsContents[] = { + 0x30, // SEQUENCE + 0x03, // three bytes long + 0x01, // BOOLEAN + 0x01, // one byte long + 0x00, // false + }; + const std::vector<net::x509_util::Extension> extensions = { - {kTransportTypesOID, false /* not critical */, kTransportTypesContents}, + {kTransportTypesOID, /*critical=*/false, kTransportTypesContents}, + {kBasicContraintsOID, /*critical=*/true, kBasicContraintsContents}, }; // https://w3c.github.io/webauthn/#sctn-packed-attestation-cert-requirements @@ -474,7 +577,9 @@ FidoTransportProtocol VirtualFidoDevice::DeviceTransport() const { // static std::string VirtualFidoDevice::MakeVirtualFidoDeviceId() { - return "VirtualFidoDevice-" + base::RandBytesAsString(32); + uint8_t rand_bytes[32]; + base::RandBytes(rand_bytes, sizeof(rand_bytes)); + return "VirtualFidoDevice-" + base::HexEncode(rand_bytes); } } // namespace device |