Meng-Huan Yu | 4cbaddc | 2019-05-08 18:31:53 +0800 | [diff] [blame] | 1 | // 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 Xiao | 174e16f | 2020-02-20 16:12:55 +0800 | [diff] [blame] | 5 | #include "libhwsec/crypto_utility.h" |
| 6 | |
| 7 | #include <limits> |
Meng-Huan Yu | 4cbaddc | 2019-05-08 18:31:53 +0800 | [diff] [blame] | 8 | #include <string> |
| 9 | #include <vector> |
| 10 | |
Wei-Cheng Xiao | 174e16f | 2020-02-20 16:12:55 +0800 | [diff] [blame] | 11 | #include <base/logging.h> |
Meng-Huan Yu | 4cbaddc | 2019-05-08 18:31:53 +0800 | [diff] [blame] | 12 | #include <base/optional.h> |
Wei-Cheng Xiao | 174e16f | 2020-02-20 16:12:55 +0800 | [diff] [blame] | 13 | #include <brillo/secure_blob.h> |
Meng-Huan Yu | 4cbaddc | 2019-05-08 18:31:53 +0800 | [diff] [blame] | 14 | #include <crypto/scoped_openssl_types.h> |
Wei-Cheng Xiao | 174e16f | 2020-02-20 16:12:55 +0800 | [diff] [blame] | 15 | #include <openssl/bio.h> |
| 16 | #include <openssl/err.h> |
| 17 | #include <openssl/rand.h> |
Meng-Huan Yu | 4cbaddc | 2019-05-08 18:31:53 +0800 | [diff] [blame] | 18 | #include <openssl/x509.h> |
| 19 | |
Meng-Huan Yu | 4cbaddc | 2019-05-08 18:31:53 +0800 | [diff] [blame] | 20 | namespace { |
| 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. |
| 28 | template <typename OpenSSLType> |
| 29 | base::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 | |
| 49 | namespace hwsec { |
| 50 | |
Wei-Cheng Xiao | 174e16f | 2020-02-20 16:12:55 +0800 | [diff] [blame] | 51 | brillo::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 | |
| 69 | std::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 Yu | 4cbaddc | 2019-05-08 18:31:53 +0800 | [diff] [blame] | 79 | base::Optional<std::vector<uint8_t>> RsaKeyToSubjectPublicKeyInfoBytes( |
| 80 | const crypto::ScopedRSA& key) { |
| 81 | return OpenSSLObjectToBytes(i2d_RSA_PUBKEY, key.get()); |
| 82 | } |
| 83 | |
| 84 | base::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 |