summaryrefslogtreecommitdiff
path: root/chromium/device/fido/virtual_fido_device.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/device/fido/virtual_fido_device.cc')
-rw-r--r--chromium/device/fido/virtual_fido_device.cc155
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