blob: c48eaad07377a778752191832ece33507aab3f9b [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_UTIL_H_
#define U2FD_UTIL_H_
#include <algorithm>
#include <optional>
#include <string>
#include <vector>
#include <base/logging.h>
#include <brillo/secure_blob.h>
#include <crypto/scoped_openssl_types.h>
#include <openssl/sha.h>
namespace u2f {
namespace util {
//
// Utility functions for copying data to/from vector<uint8_t>.
//
//////////////////////////////////////////////////////////////////////
// Utility function to copy an object, as raw bytes, to a vector.
template <typename FromType>
void AppendToVector(const FromType& from, std::vector<uint8_t>* to) {
const uint8_t* from_bytes = reinterpret_cast<const uint8_t*>(&from);
std::copy(from_bytes, from_bytes + sizeof(from), std::back_inserter(*to));
}
// Specializations of above function for copying from vector and string.
template <>
void AppendToVector(const std::vector<uint8_t>& from, std::vector<uint8_t>* to);
template <>
void AppendToVector(const std::string& from, std::vector<uint8_t>* to);
// Utility function to transform a string to a vector.
std::vector<uint8_t> ToVector(const std::string& str);
// Utility function to copy bytes from a vector to an object. This is the
// inverse of AppendToVector.
template <typename VectorAllocator, typename ToType>
bool VectorToObject(const std::vector<uint8_t, VectorAllocator>& from,
ToType* to,
const size_t size) {
if (size < from.size()) {
return false;
}
memcpy(to, &from.front(), from.size());
return true;
}
// Utility function to copy part of a string to a vector.
void AppendSubstringToVector(const std::string& from,
int start,
int length,
std::vector<uint8_t>* to);
//
// Crypto utilities.
//
//////////////////////////////////////////////////////////////////////
// Attempts to convert the specified ECDSA signature (specified as r and s
// values) to DER encoding; returns std::nullopt on error.
std::optional<std::vector<uint8_t>> SignatureToDerBytes(const uint8_t* r,
const uint8_t* s);
// Returns the SHA-256 of the specified data.
template <typename Blob>
std::vector<uint8_t> Sha256(const Blob& data) {
std::vector<uint8_t> hash(SHA256_DIGEST_LENGTH);
SHA256_CTX sha_context;
SHA256_Init(&sha_context);
SHA256_Update(&sha_context, &data.front(), data.size());
SHA256_Final(&hash.front(), &sha_context);
return hash;
}
// Returns the HMAC_SHA-256 of the specified data.
std::vector<uint8_t> HmacSha256(const brillo::SecureBlob& key,
const std::vector<uint8_t>& data);
// Attest to |data_to_sign| using software attestation.
bool DoSoftwareAttest(const std::vector<uint8_t>& data_to_sign,
std::vector<uint8_t>* attestation_cert,
std::vector<uint8_t>* signature);
// Creates a new EC key to use for U2F attestation.
crypto::ScopedEC_KEY CreateAttestationKey();
// Signs data using attestion_key, and returns the DER-encoded signature,
// or std::nullopt on error.
std::optional<std::vector<uint8_t>> AttestToData(
const std::vector<uint8_t>& data, EC_KEY* attestation_key);
// Returns an X509 certificate for the specified attestation_key, to be included
// in a U2F register response, or std::nullopt on error.
std::optional<std::vector<uint8_t>> CreateAttestationCertificate(
EC_KEY* attestation_key);
// Parses the specified certificate and re-serializes it to the same vector,
// removing any padding that was present.
bool RemoveCertificatePadding(std::vector<uint8_t>* cert);
// Builds data to be signed as part of a U2F_REGISTER response, as defined
// by the "U2F Raw Message Formats" specification.
std::vector<uint8_t> BuildU2fRegisterResponseSignedData(
const std::vector<uint8_t>& app_id,
const std::vector<uint8_t>& challenge,
const std::vector<uint8_t>& pub_key,
const std::vector<uint8_t>& key_handle);
} // namespace util
} // namespace u2f
#endif // U2FD_UTIL_H_