summaryrefslogtreecommitdiff
path: root/chromium/device/fido/attestation_object.cc
blob: dde84162ca0e8fae9e98cc44602d6f83366fe822 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/fido/attestation_object.h"

#include <utility>

#include "components/cbor/values.h"
#include "components/cbor/writer.h"
#include "device/fido/attestation_statement.h"
#include "device/fido/authenticator_data.h"
#include "device/fido/fido_constants.h"
#include "device/fido/opaque_attestation_statement.h"

namespace device {

// static
base::Optional<AttestationObject> AttestationObject::Parse(
    const cbor::Value& value) {
  if (!value.is_map()) {
    return base::nullopt;
  }
  const cbor::Value::MapValue& map = value.GetMap();

  const auto& format_it = map.find(cbor::Value(kFormatKey));
  if (format_it == map.end() || !format_it->second.is_string()) {
    return base::nullopt;
  }
  const std::string& fmt = format_it->second.GetString();

  const auto& att_stmt_it = map.find(cbor::Value(kAttestationStatementKey));
  if (att_stmt_it == map.end() || !att_stmt_it->second.is_map()) {
    return base::nullopt;
  }
  std::unique_ptr<AttestationStatement> attestation_statement =
      std::make_unique<OpaqueAttestationStatement>(
          fmt, cbor::Value(att_stmt_it->second.GetMap()));

  const auto& auth_data_it = map.find(cbor::Value(kAuthDataKey));
  if (auth_data_it == map.end() || !auth_data_it->second.is_bytestring()) {
    return base::nullopt;
  }
  base::Optional<AuthenticatorData> authenticator_data =
      AuthenticatorData::DecodeAuthenticatorData(
          auth_data_it->second.GetBytestring());
  if (!authenticator_data) {
    return base::nullopt;
  }
  return AttestationObject(std::move(*authenticator_data),
                           std::move(attestation_statement));
}

AttestationObject::AttestationObject(
    AuthenticatorData data,
    std::unique_ptr<AttestationStatement> statement)
    : authenticator_data_(std::move(data)),
      attestation_statement_(std::move(statement)) {}

AttestationObject::AttestationObject(AttestationObject&& other) = default;
AttestationObject& AttestationObject::operator=(AttestationObject&& other) =
    default;

AttestationObject::~AttestationObject() = default;

std::vector<uint8_t> AttestationObject::GetCredentialId() const {
  return authenticator_data_.GetCredentialId();
}

void AttestationObject::EraseAttestationStatement(
    AttestationObject::AAGUID erase_aaguid) {
  attestation_statement_ = std::make_unique<NoneAttestationStatement>();
  if (erase_aaguid == AAGUID::kErase) {
    authenticator_data_.DeleteDeviceAaguid();
  }

// Attested credential data is optional section within authenticator data. But
// if present, the first 16 bytes of it represents a device AAGUID which must
// be set to zeros for none attestation statement format, unless explicitly
// requested otherwise (we make an exception for platform authenticators).
#if DCHECK_IS_ON()
  if (!authenticator_data_.attested_data())
    return;
  DCHECK(erase_aaguid == AAGUID::kInclude ||
         authenticator_data_.attested_data()->IsAaguidZero());
#endif
}

bool AttestationObject::IsSelfAttestation() {
  if (!attestation_statement_->IsSelfAttestation()) {
    return false;
  }
  // Self-attestation also requires that the AAGUID be zero. See
  // https://www.w3.org/TR/webauthn/#createCredential.
  return !authenticator_data_.attested_data() ||
         authenticator_data_.attested_data()->IsAaguidZero();
}

bool AttestationObject::IsAttestationCertificateInappropriatelyIdentifying() {
  return attestation_statement_
      ->IsAttestationCertificateInappropriatelyIdentifying();
}

cbor::Value AsCBOR(const AttestationObject& object) {
  cbor::Value::MapValue map;
  map[cbor::Value(kFormatKey)] =
      cbor::Value(object.attestation_statement().format_name());
  map[cbor::Value(kAuthDataKey)] =
      cbor::Value(object.authenticator_data().SerializeToByteArray());
  map[cbor::Value(kAttestationStatementKey)] =
      AsCBOR(object.attestation_statement());
  return cbor::Value(std::move(map));
}

}  // namespace device