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