blob: 014d823f0eeed9bbcc4d0b6e9d7b3d55ede6f38e [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 "modules/credentialmanager/CredentialManagerTypeConverters.h"
#include "bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "modules/credentialmanager/MakePublicKeyCredentialOptions.h"
#include "modules/credentialmanager/PublicKeyCredential.h"
#include "modules/credentialmanager/PublicKeyCredentialParameters.h"
#include "modules/credentialmanager/PublicKeyCredentialRpEntity.h"
#include "modules/credentialmanager/PublicKeyCredentialUserEntity.h"
#include "platform/wtf/Time.h"
namespace {
// Time to wait for an authenticator to successfully complete an operation.
constexpr TimeDelta kAdjustedTimeoutLower = TimeDelta::FromMinutes(1);
constexpr TimeDelta kAdjustedTimeoutUpper = TimeDelta::FromMinutes(2);
} // namespace
namespace mojo {
using webauth::mojom::blink::AuthenticatorStatus;
using webauth::mojom::blink::MakePublicKeyCredentialOptionsPtr;
using webauth::mojom::blink::PublicKeyCredentialRpEntity;
using webauth::mojom::blink::PublicKeyCredentialRpEntityPtr;
using webauth::mojom::blink::PublicKeyCredentialUserEntity;
using webauth::mojom::blink::PublicKeyCredentialUserEntityPtr;
using webauth::mojom::blink::PublicKeyCredentialParameters;
using webauth::mojom::blink::PublicKeyCredentialParametersPtr;
using webauth::mojom::blink::PublicKeyCredentialType;
using webauth::mojom::blink::AuthenticatorTransport;
// static
Vector<uint8_t>
TypeConverter<Vector<uint8_t>, blink::ArrayBufferOrArrayBufferView>::Convert(
const blink::ArrayBufferOrArrayBufferView& buffer) {
DCHECK(!buffer.IsNull());
Vector<uint8_t> vector;
if (buffer.IsArrayBuffer()) {
vector.Append(static_cast<uint8_t*>(buffer.GetAsArrayBuffer()->Data()),
buffer.GetAsArrayBuffer()->ByteLength());
} else {
DCHECK(buffer.IsArrayBufferView());
vector.Append(static_cast<uint8_t*>(
buffer.GetAsArrayBufferView().View()->BaseAddress()),
buffer.GetAsArrayBufferView().View()->byteLength());
}
return vector;
}
// static
PublicKeyCredentialType TypeConverter<PublicKeyCredentialType, String>::Convert(
const String& type) {
if (type == "public-key")
return PublicKeyCredentialType::PUBLIC_KEY;
NOTREACHED();
return PublicKeyCredentialType::PUBLIC_KEY;
}
// static
AuthenticatorTransport TypeConverter<AuthenticatorTransport, String>::Convert(
const String& transport) {
if (transport == "usb")
return AuthenticatorTransport::USB;
if (transport == "nfc")
return AuthenticatorTransport::NFC;
if (transport == "ble")
return AuthenticatorTransport::BLE;
NOTREACHED();
return AuthenticatorTransport::USB;
}
// static
PublicKeyCredentialUserEntityPtr
TypeConverter<PublicKeyCredentialUserEntityPtr,
blink::PublicKeyCredentialUserEntity>::
Convert(const blink::PublicKeyCredentialUserEntity& user) {
auto entity = webauth::mojom::blink::PublicKeyCredentialUserEntity::New();
entity->id = ConvertTo<Vector<uint8_t>>(user.id());
entity->name = user.name();
if (user.hasIcon()) {
entity->icon = blink::KURL(blink::KURL(), user.icon());
}
entity->display_name = user.displayName();
return entity;
}
// static
PublicKeyCredentialRpEntityPtr
TypeConverter<PublicKeyCredentialRpEntityPtr,
blink::PublicKeyCredentialRpEntity>::
Convert(const blink::PublicKeyCredentialRpEntity& rp) {
auto entity = webauth::mojom::blink::PublicKeyCredentialRpEntity::New();
entity->id = rp.id();
entity->name = rp.name();
if (rp.hasIcon()) {
entity->icon = blink::KURL(blink::KURL(), rp.icon());
}
return entity;
}
// static
PublicKeyCredentialParametersPtr
TypeConverter<PublicKeyCredentialParametersPtr,
blink::PublicKeyCredentialParameters>::
Convert(const blink::PublicKeyCredentialParameters& parameter) {
auto mojo_parameter =
webauth::mojom::blink::PublicKeyCredentialParameters::New();
mojo_parameter->type = ConvertTo<PublicKeyCredentialType>(parameter.type());
// A COSEAlgorithmIdentifier's value is a number identifying a cryptographic
// algorithm. Values are registered in the IANA COSE Algorithms registry.
// https://www.iana.org/assignments/cose/cose.xhtml#algorithms
mojo_parameter->algorithm_identifier = parameter.alg();
return mojo_parameter;
}
// static
MakePublicKeyCredentialOptionsPtr
TypeConverter<MakePublicKeyCredentialOptionsPtr,
blink::MakePublicKeyCredentialOptions>::
Convert(const blink::MakePublicKeyCredentialOptions& options) {
auto mojo_options =
webauth::mojom::blink::MakePublicKeyCredentialOptions::New();
mojo_options->relying_party = PublicKeyCredentialRpEntity::From(options.rp());
mojo_options->user = PublicKeyCredentialUserEntity::From(options.user());
if (!mojo_options->relying_party | !mojo_options->user) {
return nullptr;
}
mojo_options->challenge = ConvertTo<Vector<uint8_t>>(options.challenge());
// Step 4 of https://w3c.github.io/webauthn/#createCredential
if (options.hasTimeout()) {
WTF::TimeDelta adjusted_timeout;
adjusted_timeout = WTF::TimeDelta::FromMilliseconds(options.timeout());
mojo_options->adjusted_timeout =
std::max(kAdjustedTimeoutLower,
std::min(kAdjustedTimeoutUpper, adjusted_timeout));
} else {
mojo_options->adjusted_timeout = kAdjustedTimeoutLower;
}
// Steps 8 and 9 of
// https://www.w3.org/TR/2017/WD-webauthn-20170505/#createCredential
Vector<PublicKeyCredentialParametersPtr> parameters;
for (const auto& parameter : options.pubKeyCredParams()) {
PublicKeyCredentialParametersPtr normalized_parameter =
PublicKeyCredentialParameters::From(parameter);
if (normalized_parameter) {
parameters.push_back(std::move(normalized_parameter));
}
}
if (parameters.IsEmpty() && options.hasPubKeyCredParams()) {
return nullptr;
}
mojo_options->public_key_parameters = std::move(parameters);
if (options.hasExcludeCredentials()) {
// Adds the excludeCredentials members
for (const blink::PublicKeyCredentialDescriptor& descriptor :
options.excludeCredentials()) {
auto mojo_descriptor =
webauth::mojom::blink::PublicKeyCredentialDescriptor::New();
mojo_descriptor->type =
ConvertTo<PublicKeyCredentialType>(descriptor.type());
mojo_descriptor->id = ConvertTo<Vector<uint8_t>>((descriptor.id()));
if (descriptor.hasTransports()) {
for (const auto& transport : descriptor.transports()) {
mojo_descriptor->transports.push_back(
ConvertTo<AuthenticatorTransport>(transport));
}
}
mojo_options->exclude_credentials.push_back(std::move(mojo_descriptor));
}
}
return mojo_options;
}
} // namespace mojo