blob: a5f605974149abc456e2bad0c8afe02da6dd7d88 [file] [log] [blame]
Meng-Huan Yu4cbaddc2019-05-08 18:31:53 +08001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Wei-Cheng Xiao174e16f2020-02-20 16:12:55 +08005#include "libhwsec/crypto_utility.h"
6
7#include <limits>
Meng-Huan Yu4cbaddc2019-05-08 18:31:53 +08008#include <string>
9#include <vector>
10
Wei-Cheng Xiao174e16f2020-02-20 16:12:55 +080011#include <base/logging.h>
Meng-Huan Yu4cbaddc2019-05-08 18:31:53 +080012#include <base/optional.h>
Wei-Cheng Xiao174e16f2020-02-20 16:12:55 +080013#include <brillo/secure_blob.h>
Meng-Huan Yu4cbaddc2019-05-08 18:31:53 +080014#include <crypto/scoped_openssl_types.h>
Wei-Cheng Xiao174e16f2020-02-20 16:12:55 +080015#include <openssl/bio.h>
16#include <openssl/err.h>
17#include <openssl/rand.h>
Meng-Huan Yu4cbaddc2019-05-08 18:31:53 +080018#include <openssl/x509.h>
19
Meng-Huan Yu4cbaddc2019-05-08 18:31:53 +080020namespace {
21
22// The wrapper of OpenSSL i2d series function. It takes a OpenSSL i2d function
23// and apply to |object|.
24//
25// The wrapper will always accept the non-const pointer of the object since
26// unique_ptr::get will only return the non-const version. It will break the
27// type deduction of template.
28template <typename OpenSSLType>
29base::Optional<std::vector<uint8_t>> OpenSSLObjectToBytes(
30 int (*i2d_convert_function)(OpenSSLType*, unsigned char**),
31 typename std::remove_const<OpenSSLType>::type* object) {
32 if (object == nullptr) {
33 return base::nullopt;
34 }
35
36 unsigned char* openssl_buffer = nullptr;
37
38 int size = i2d_convert_function(object, &openssl_buffer);
39 if (size < 0) {
40 return base::nullopt;
41 }
42
43 crypto::ScopedOpenSSLBytes scoped_buffer(openssl_buffer);
44 return std::vector<uint8_t>(openssl_buffer, openssl_buffer + size);
45}
46
47} // namespace
48
49namespace hwsec {
50
Wei-Cheng Xiao174e16f2020-02-20 16:12:55 +080051brillo::SecureBlob CreateSecureRandomBlob(size_t length) {
52 // OpenSSL takes a signed integer. Returns nullopt if the user requests
53 // something too large.
54 if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
55 LOG(ERROR) << __func__ << ": length exceeds the limit of int.";
56 return brillo::SecureBlob();
57 }
58
59 brillo::SecureBlob blob(length);
60 if (!RAND_bytes(reinterpret_cast<unsigned char*>(blob.data()), length)) {
61 LOG(ERROR) << __func__ << ": failed to generate " << length
62 << " random bytes: " << GetOpensslError();
63 return brillo::SecureBlob();
64 }
65
66 return blob;
67}
68
69std::string GetOpensslError() {
70 BIO* bio = BIO_new(BIO_s_mem());
71 ERR_print_errors(bio);
72 char* data = nullptr;
73 int data_len = BIO_get_mem_data(bio, &data);
74 std::string error_string(data, data_len);
75 BIO_free(bio);
76 return error_string;
77}
78
Meng-Huan Yu4cbaddc2019-05-08 18:31:53 +080079base::Optional<std::vector<uint8_t>> RsaKeyToSubjectPublicKeyInfoBytes(
80 const crypto::ScopedRSA& key) {
81 return OpenSSLObjectToBytes(i2d_RSA_PUBKEY, key.get());
82}
83
84base::Optional<std::vector<uint8_t>> EccKeyToSubjectPublicKeyInfoBytes(
85 const crypto::ScopedEC_KEY& key) {
86 return OpenSSLObjectToBytes(i2d_EC_PUBKEY, key.get());
87}
88
89} // namespace hwsec