blob: a5f605974149abc456e2bad0c8afe02da6dd7d88 [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.
#include "libhwsec/crypto_utility.h"
#include <limits>
#include <string>
#include <vector>
#include <base/logging.h>
#include <base/optional.h>
#include <brillo/secure_blob.h>
#include <crypto/scoped_openssl_types.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
namespace {
// The wrapper of OpenSSL i2d series function. It takes a OpenSSL i2d function
// and apply to |object|.
//
// The wrapper will always accept the non-const pointer of the object since
// unique_ptr::get will only return the non-const version. It will break the
// type deduction of template.
template <typename OpenSSLType>
base::Optional<std::vector<uint8_t>> OpenSSLObjectToBytes(
int (*i2d_convert_function)(OpenSSLType*, unsigned char**),
typename std::remove_const<OpenSSLType>::type* object) {
if (object == nullptr) {
return base::nullopt;
}
unsigned char* openssl_buffer = nullptr;
int size = i2d_convert_function(object, &openssl_buffer);
if (size < 0) {
return base::nullopt;
}
crypto::ScopedOpenSSLBytes scoped_buffer(openssl_buffer);
return std::vector<uint8_t>(openssl_buffer, openssl_buffer + size);
}
} // namespace
namespace hwsec {
brillo::SecureBlob CreateSecureRandomBlob(size_t length) {
// OpenSSL takes a signed integer. Returns nullopt if the user requests
// something too large.
if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
LOG(ERROR) << __func__ << ": length exceeds the limit of int.";
return brillo::SecureBlob();
}
brillo::SecureBlob blob(length);
if (!RAND_bytes(reinterpret_cast<unsigned char*>(blob.data()), length)) {
LOG(ERROR) << __func__ << ": failed to generate " << length
<< " random bytes: " << GetOpensslError();
return brillo::SecureBlob();
}
return blob;
}
std::string GetOpensslError() {
BIO* bio = BIO_new(BIO_s_mem());
ERR_print_errors(bio);
char* data = nullptr;
int data_len = BIO_get_mem_data(bio, &data);
std::string error_string(data, data_len);
BIO_free(bio);
return error_string;
}
base::Optional<std::vector<uint8_t>> RsaKeyToSubjectPublicKeyInfoBytes(
const crypto::ScopedRSA& key) {
return OpenSSLObjectToBytes(i2d_RSA_PUBKEY, key.get());
}
base::Optional<std::vector<uint8_t>> EccKeyToSubjectPublicKeyInfoBytes(
const crypto::ScopedEC_KEY& key) {
return OpenSSLObjectToBytes(i2d_EC_PUBKEY, key.get());
}
} // namespace hwsec