1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "device/fido/authenticator_make_credential_response.h"
6
7 #include <utility>
8
9 #include "components/cbor/writer.h"
10 #include "device/fido/attestation_object.h"
11 #include "device/fido/attestation_statement_formats.h"
12 #include "device/fido/attested_credential_data.h"
13 #include "device/fido/authenticator_data.h"
14 #include "device/fido/client_data.h"
15 #include "device/fido/ec_public_key.h"
16 #include "device/fido/fido_parsing_utils.h"
17
18 namespace device {
19
20 // static
21 base::Optional<AuthenticatorMakeCredentialResponse>
CreateFromU2fRegisterResponse(base::Optional<FidoTransportProtocol> transport_used,base::span<const uint8_t,kRpIdHashLength> relying_party_id_hash,base::span<const uint8_t> u2f_data)22 AuthenticatorMakeCredentialResponse::CreateFromU2fRegisterResponse(
23 base::Optional<FidoTransportProtocol> transport_used,
24 base::span<const uint8_t, kRpIdHashLength> relying_party_id_hash,
25 base::span<const uint8_t> u2f_data) {
26 auto public_key = ECPublicKey::ExtractFromU2fRegistrationResponse(
27 fido_parsing_utils::kEs256, u2f_data);
28 if (!public_key)
29 return base::nullopt;
30
31 auto attested_credential_data =
32 AttestedCredentialData::CreateFromU2fRegisterResponse(
33 u2f_data, std::move(public_key));
34
35 if (!attested_credential_data)
36 return base::nullopt;
37
38 // Extract the credential_id for packing into the response data.
39 std::vector<uint8_t> credential_id =
40 attested_credential_data->credential_id();
41
42 // The counter is zeroed out for Register requests.
43 std::array<uint8_t, 4> counter = {};
44 constexpr uint8_t flags =
45 static_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence) |
46 static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
47
48 AuthenticatorData authenticator_data(relying_party_id_hash, flags, counter,
49 std::move(attested_credential_data));
50
51 auto fido_attestation_statement =
52 FidoAttestationStatement::CreateFromU2fRegisterResponse(u2f_data);
53
54 if (!fido_attestation_statement)
55 return base::nullopt;
56
57 return AuthenticatorMakeCredentialResponse(
58 transport_used, AttestationObject(std::move(authenticator_data),
59 std::move(fido_attestation_statement)));
60 }
61
AuthenticatorMakeCredentialResponse(base::Optional<FidoTransportProtocol> transport_used,AttestationObject attestation_object)62 AuthenticatorMakeCredentialResponse::AuthenticatorMakeCredentialResponse(
63 base::Optional<FidoTransportProtocol> transport_used,
64 AttestationObject attestation_object)
65 : ResponseData(attestation_object.GetCredentialId()),
66 attestation_object_(std::move(attestation_object)),
67 transport_used_(transport_used) {}
68
69 AuthenticatorMakeCredentialResponse::AuthenticatorMakeCredentialResponse(
70 AuthenticatorMakeCredentialResponse&& that) = default;
71
72 AuthenticatorMakeCredentialResponse& AuthenticatorMakeCredentialResponse::
73 operator=(AuthenticatorMakeCredentialResponse&& other) = default;
74
75 AuthenticatorMakeCredentialResponse::~AuthenticatorMakeCredentialResponse() =
76 default;
77
78 std::vector<uint8_t>
GetCBOREncodedAttestationObject() const79 AuthenticatorMakeCredentialResponse::GetCBOREncodedAttestationObject() const {
80 return cbor::Writer::Write(AsCBOR(attestation_object_))
81 .value_or(std::vector<uint8_t>());
82 }
83
EraseAttestationStatement(AttestationObject::AAGUID erase_aaguid)84 void AuthenticatorMakeCredentialResponse::EraseAttestationStatement(
85 AttestationObject::AAGUID erase_aaguid) {
86 attestation_object_.EraseAttestationStatement(erase_aaguid);
87 }
88
IsSelfAttestation()89 bool AuthenticatorMakeCredentialResponse::IsSelfAttestation() {
90 return attestation_object_.IsSelfAttestation();
91 }
92
93 bool AuthenticatorMakeCredentialResponse::
IsAttestationCertificateInappropriatelyIdentifying()94 IsAttestationCertificateInappropriatelyIdentifying() {
95 return attestation_object_
96 .IsAttestationCertificateInappropriatelyIdentifying();
97 }
98
99 const std::array<uint8_t, kRpIdHashLength>&
GetRpIdHash() const100 AuthenticatorMakeCredentialResponse::GetRpIdHash() const {
101 return attestation_object_.rp_id_hash();
102 }
103
AsCTAPStyleCBORBytes(const AuthenticatorMakeCredentialResponse & response)104 std::vector<uint8_t> AsCTAPStyleCBORBytes(
105 const AuthenticatorMakeCredentialResponse& response) {
106 const AttestationObject& object = response.attestation_object();
107 cbor::Value::MapValue map;
108 map.emplace(1, cbor::Value(object.attestation_statement().format_name()));
109 map.emplace(2, cbor::Value(object.authenticator_data().SerializeToByteArray()));
110 map.emplace(3, AsCBOR(object.attestation_statement()));
111 if (response.android_client_data_ext()) {
112 map.emplace(kAndroidClientDataExtOutputKey,
113 cbor::Value(*response.android_client_data_ext()));
114 }
115 auto encoded_bytes = cbor::Writer::Write(cbor::Value(std::move(map)));
116 DCHECK(encoded_bytes);
117 return std::move(*encoded_bytes);
118 }
119
120 } // namespace device
121