blob: e4237e39055842c9fad46b45677d1ae4efbe6ca9 [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef U2FD_U2F_ADPU_H_
#define U2FD_U2F_ADPU_H_
#include <stdint.h>
#include <string>
#include <vector>
#include <base/optional.h>
#include "u2fd/util.h"
// Classes for dealing with command and response ADPUs, as described in the "U2F
// Raw Message Formats" specification.
namespace u2f {
// INS codes used in U2F Command ADPUs.
enum class U2fIns : uint8_t {
kU2fRegister = 1, // U2F_REGISTER
kU2fAuthenticate = 2, // U2F_AUTHENTICATE
kU2fVersion = 3, // U2F_VERSION
kInsInvalid = 0xff,
};
// Represents a command ADPU.
class U2fCommandAdpu {
public:
// Fixed-size header of a command ADPU.
struct Header {
U2fIns ins_;
uint8_t p1_;
uint8_t p2_;
};
// Attempts to parse the specified string as an ADPU, and returns a valid
// U2fCommandAdpu if successful, or base::nullopt otherwise.
static base::Optional<U2fCommandAdpu> ParseFromString(
const std::string& adpu_raw);
// Creates an 'empty' ADPU for the command with the specified INS command
// code.
static U2fCommandAdpu CreateForU2fIns(U2fIns ins);
// Returns the INS command code for this ADPU.
U2fIns Ins() const { return header_.ins_; }
// Returns the P1 parameter for this ADPU.
uint8_t P1() const { return header_.p1_; }
// Returns the request body for this ADPU.
const std::string& Body() const { return data_; }
// Returns the max response length for this ADPU.
uint32_t MaxResponseLength() const { return max_response_length_; }
// Serializes this ADPU to a string.
std::string ToString();
protected:
Header header_;
std::string data_;
uint32_t max_response_length_;
private:
// Private constructor, use factory methods above.
U2fCommandAdpu() = default;
// Internal parser class called by ParseFromString().
class Parser;
friend class Parser;
};
// Represents an ADPU for a U2F_REGISTER request.
class U2fRegisterRequestAdpu {
public:
// Attempt to parse the body of the specified ADPU as a U2F_REGISTER request.
// Returns a valid U2fRegisterRequestAdpu if successful, or base::nullopt
// otherwise.
static base::Optional<U2fRegisterRequestAdpu> FromCommandAdpu(
const U2fCommandAdpu& adpu);
// Whether the request response should use the G2F attestation certificate (if
// available).
bool UseG2fAttestation() const { return g2f_attestation_; }
// Accessors for the request fields.
const std::vector<uint8_t>& GetAppId() const { return app_id_; }
const std::vector<uint8_t>& GetChallenge() const { return challenge_; }
private:
bool g2f_attestation_;
std::vector<uint8_t> app_id_;
std::vector<uint8_t> challenge_;
};
class U2fAuthenticateRequestAdpu {
public:
// Attempt to parse the body of the specified ADPU as a U2F_AUTHENTICATE
// request. Returns a valid U2fRegisterRequestAdpu if successful, or
// base::nullopt otherwise.
static base::Optional<U2fAuthenticateRequestAdpu> FromCommandAdpu(
const U2fCommandAdpu& adpu);
// Returns true if the ADPU is for a U2F_AUTHENTICATE check-only
// request. Check-only requests should verify whether the specified key handle
// is owned by this U2F device, but not perform any authentication.
bool IsAuthenticateCheckOnly() { return auth_check_only_; }
// Accessors for the request fields.
const std::vector<uint8_t>& GetAppId() const { return app_id_; }
const std::vector<uint8_t>& GetChallenge() const { return challenge_; }
const std::vector<uint8_t>& GetKeyHandle() const { return key_handle_; }
private:
bool auth_check_only_;
std::vector<uint8_t> app_id_;
std::vector<uint8_t> challenge_;
std::vector<uint8_t> key_handle_;
};
// Represents a response ADPU. Provides methods for building and serializing a
// response.
class U2fResponseAdpu {
public:
// Constructs an empty response.
U2fResponseAdpu() = default;
// Serialize the response to the specified string.
bool ToString(std::string* out);
// Methods to append data to the response.
void AppendByte(uint8_t byte) { data_.push_back(byte); }
void AppendBytes(const std::vector<uint8_t>& bytes) {
util::AppendToVector(bytes, &data_);
}
void AppendString(const std::string& string) {
util::AppendToVector(string, &data_);
}
template <typename T>
void AppendObject(const T& obj) {
util::AppendToVector(obj, &data_);
}
// Sets the return status for the response.
void SetStatus(uint16_t sw) {
sw1_ = sw >> 8;
sw2_ = static_cast<uint8_t>(sw);
}
private:
std::vector<uint8_t> data_;
uint8_t sw1_;
uint8_t sw2_;
};
} // namespace u2f
#endif // U2FD_U2F_ADPU_H_