blob: 1c7cb18b28eca145b7e995ef474a79d4b245e656 [file] [log] [blame]
// 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/u2f/fido_attestation_statement.h"
#include <utility>
#include "base/logging.h"
#include "device/u2f/u2f_parsing_utils.h"
#include "third_party/boringssl/src/include/openssl/bytestring.h"
namespace device {
namespace {
constexpr char kFidoFormatName[] = "fido-u2f";
constexpr char kSignatureKey[] = "sig";
constexpr char kX509CertKey[] = "x5c";
} // namespace
// static
std::unique_ptr<FidoAttestationStatement>
FidoAttestationStatement::CreateFromU2fRegisterResponse(
base::span<const uint8_t> u2f_data) {
CBS response, cert;
CBS_init(&response, u2f_data.data(), u2f_data.size());
// The format of |u2f_data| is specified here:
// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#registration-response-message-success
uint8_t credential_length;
if (!CBS_skip(&response, u2f_parsing_utils::kU2fResponseKeyHandleLengthPos) ||
!CBS_get_u8(&response, &credential_length) ||
!CBS_skip(&response, credential_length) ||
!CBS_get_asn1_element(&response, &cert, CBS_ASN1_SEQUENCE)) {
DLOG(ERROR)
<< "Invalid U2F response. Unable to unpack attestation statement.";
return nullptr;
}
std::vector<std::vector<uint8_t>> x509_certificates;
x509_certificates.emplace_back(CBS_data(&cert),
CBS_data(&cert) + CBS_len(&cert));
// The remaining bytes are the signature.
std::vector<uint8_t> signature(CBS_data(&response),
CBS_data(&response) + CBS_len(&response));
return std::make_unique<FidoAttestationStatement>(
std::move(signature), std::move(x509_certificates));
}
FidoAttestationStatement::FidoAttestationStatement(
std::vector<uint8_t> signature,
std::vector<std::vector<uint8_t>> x509_certificates)
: AttestationStatement(kFidoFormatName),
signature_(std::move(signature)),
x509_certificates_(std::move(x509_certificates)) {}
FidoAttestationStatement::~FidoAttestationStatement() = default;
cbor::CBORValue::MapValue FidoAttestationStatement::GetAsCBORMap() {
cbor::CBORValue::MapValue attestation_statement_map;
attestation_statement_map[cbor::CBORValue(kSignatureKey)] =
cbor::CBORValue(signature_);
std::vector<cbor::CBORValue> certificate_array;
for (const auto& cert : x509_certificates_) {
certificate_array.push_back(cbor::CBORValue(cert));
}
attestation_statement_map[cbor::CBORValue(kX509CertKey)] =
cbor::CBORValue(std::move(certificate_array));
return attestation_statement_map;
}
} // namespace device