xref: /aosp_15_r20/external/libbrillo/brillo/secure_blob.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #include <cstring>  // memcpy
6*1a96fba6SXin Li 
7*1a96fba6SXin Li #include <base/stl_util.h>
8*1a96fba6SXin Li #include <base/strings/string_number_conversions.h>
9*1a96fba6SXin Li 
10*1a96fba6SXin Li #include "brillo/secure_blob.h"
11*1a96fba6SXin Li 
12*1a96fba6SXin Li namespace brillo {
13*1a96fba6SXin Li 
14*1a96fba6SXin Li namespace {
15*1a96fba6SXin Li 
ConvertHexToBytes(char c,uint8_t * v)16*1a96fba6SXin Li bool ConvertHexToBytes(char c, uint8_t* v) {
17*1a96fba6SXin Li   if (c >= '0' && c <='9')
18*1a96fba6SXin Li     *v = c - '0';
19*1a96fba6SXin Li   else if (c >= 'a' && c <= 'f')
20*1a96fba6SXin Li     *v = c - 'a' + 10;
21*1a96fba6SXin Li   else if (c >= 'A' && c <= 'F')
22*1a96fba6SXin Li     *v = c - 'A' + 10;
23*1a96fba6SXin Li   else
24*1a96fba6SXin Li     return false;
25*1a96fba6SXin Li 
26*1a96fba6SXin Li   return true;
27*1a96fba6SXin Li }
28*1a96fba6SXin Li 
29*1a96fba6SXin Li }  // namespace
30*1a96fba6SXin Li 
BlobToString(const Blob & blob)31*1a96fba6SXin Li std::string BlobToString(const Blob& blob) {
32*1a96fba6SXin Li   return std::string(blob.begin(), blob.end());
33*1a96fba6SXin Li }
34*1a96fba6SXin Li 
BlobFromString(const std::string & bytes)35*1a96fba6SXin Li Blob BlobFromString(const std::string& bytes) {
36*1a96fba6SXin Li   return Blob(bytes.begin(), bytes.end());
37*1a96fba6SXin Li }
38*1a96fba6SXin Li 
CombineBlobs(const std::initializer_list<Blob> & blobs)39*1a96fba6SXin Li Blob CombineBlobs(const std::initializer_list<Blob>& blobs) {
40*1a96fba6SXin Li   size_t total_size = 0;
41*1a96fba6SXin Li   for (const auto& blob : blobs)
42*1a96fba6SXin Li     total_size += blob.size();
43*1a96fba6SXin Li   Blob concatenation;
44*1a96fba6SXin Li   concatenation.reserve(total_size);
45*1a96fba6SXin Li   for (const auto& blob : blobs)
46*1a96fba6SXin Li     concatenation.insert(concatenation.end(), blob.begin(), blob.end());
47*1a96fba6SXin Li   return concatenation;
48*1a96fba6SXin Li }
49*1a96fba6SXin Li 
SecureBlob(const Blob & blob)50*1a96fba6SXin Li SecureBlob::SecureBlob(const Blob& blob)
51*1a96fba6SXin Li     : SecureBlob(blob.begin(), blob.end()) {}
52*1a96fba6SXin Li 
SecureBlob(const std::string & data)53*1a96fba6SXin Li SecureBlob::SecureBlob(const std::string& data)
54*1a96fba6SXin Li     : SecureBlob(data.begin(), data.end()) {}
55*1a96fba6SXin Li 
~SecureBlob()56*1a96fba6SXin Li SecureBlob::~SecureBlob() {
57*1a96fba6SXin Li   clear();
58*1a96fba6SXin Li }
59*1a96fba6SXin Li 
resize(size_type count)60*1a96fba6SXin Li void SecureBlob::resize(size_type count) {
61*1a96fba6SXin Li   if (count < size()) {
62*1a96fba6SXin Li     SecureMemset(data() + count, 0, capacity() - count);
63*1a96fba6SXin Li   }
64*1a96fba6SXin Li   Blob::resize(count);
65*1a96fba6SXin Li }
66*1a96fba6SXin Li 
resize(size_type count,const value_type & value)67*1a96fba6SXin Li void SecureBlob::resize(size_type count, const value_type& value) {
68*1a96fba6SXin Li   if (count < size()) {
69*1a96fba6SXin Li     SecureMemset(data() + count, 0, capacity() - count);
70*1a96fba6SXin Li   }
71*1a96fba6SXin Li   Blob::resize(count, value);
72*1a96fba6SXin Li }
73*1a96fba6SXin Li 
clear()74*1a96fba6SXin Li void SecureBlob::clear() {
75*1a96fba6SXin Li   SecureMemset(data(), 0, capacity());
76*1a96fba6SXin Li   Blob::clear();
77*1a96fba6SXin Li }
78*1a96fba6SXin Li 
to_string() const79*1a96fba6SXin Li std::string SecureBlob::to_string() const {
80*1a96fba6SXin Li   return std::string(data(), data() + size());
81*1a96fba6SXin Li }
82*1a96fba6SXin Li 
Combine(const SecureBlob & blob1,const SecureBlob & blob2)83*1a96fba6SXin Li SecureBlob SecureBlob::Combine(const SecureBlob& blob1,
84*1a96fba6SXin Li                                const SecureBlob& blob2) {
85*1a96fba6SXin Li   SecureBlob result;
86*1a96fba6SXin Li   result.reserve(blob1.size() + blob2.size());
87*1a96fba6SXin Li   result.insert(result.end(), blob1.begin(), blob1.end());
88*1a96fba6SXin Li   result.insert(result.end(), blob2.begin(), blob2.end());
89*1a96fba6SXin Li   return result;
90*1a96fba6SXin Li }
91*1a96fba6SXin Li 
HexStringToSecureBlob(const std::string & input,SecureBlob * output)92*1a96fba6SXin Li bool SecureBlob::HexStringToSecureBlob(const std::string& input,
93*1a96fba6SXin Li                                        SecureBlob* output) {
94*1a96fba6SXin Li   // TODO(jorgelo,crbug.com/728047): Consider not using an intermediate
95*1a96fba6SXin Li   // std::vector here at all.
96*1a96fba6SXin Li   std::vector<uint8_t> temp;
97*1a96fba6SXin Li   if (!base::HexStringToBytes(input, &temp)) {
98*1a96fba6SXin Li     output->clear();
99*1a96fba6SXin Li     return false;
100*1a96fba6SXin Li   }
101*1a96fba6SXin Li   output->assign(temp.begin(), temp.end());
102*1a96fba6SXin Li   SecureMemset(temp.data(), 0, temp.capacity());
103*1a96fba6SXin Li   return true;
104*1a96fba6SXin Li }
105*1a96fba6SXin Li 
SecureMemset(void * v,int c,size_t n)106*1a96fba6SXin Li BRILLO_DISABLE_ASAN void* SecureMemset(void* v, int c, size_t n) {
107*1a96fba6SXin Li   volatile uint8_t* p = reinterpret_cast<volatile uint8_t*>(v);
108*1a96fba6SXin Li   while (n--)
109*1a96fba6SXin Li     *p++ = c;
110*1a96fba6SXin Li   return v;
111*1a96fba6SXin Li }
112*1a96fba6SXin Li 
SecureMemcmp(const void * s1,const void * s2,size_t n)113*1a96fba6SXin Li int SecureMemcmp(const void* s1, const void* s2, size_t n) {
114*1a96fba6SXin Li   const uint8_t* us1 = reinterpret_cast<const uint8_t*>(s1);
115*1a96fba6SXin Li   const uint8_t* us2 = reinterpret_cast<const uint8_t*>(s2);
116*1a96fba6SXin Li   int result = 0;
117*1a96fba6SXin Li 
118*1a96fba6SXin Li   if (0 == n)
119*1a96fba6SXin Li     return 1;
120*1a96fba6SXin Li 
121*1a96fba6SXin Li   /* Code snippet without data-dependent branch due to
122*1a96fba6SXin Li    * Nate Lawson ([email protected]) of Root Labs. */
123*1a96fba6SXin Li   while (n--)
124*1a96fba6SXin Li     result |= *us1++ ^ *us2++;
125*1a96fba6SXin Li 
126*1a96fba6SXin Li   return result != 0;
127*1a96fba6SXin Li }
128*1a96fba6SXin Li 
129*1a96fba6SXin Li // base::HexEncode and base::HexStringToBytes use strings, which may leak
130*1a96fba6SXin Li // contents. These functions are alternatives that keep all contents
131*1a96fba6SXin Li // within secured memory.
SecureBlobToSecureHex(const SecureBlob & blob)132*1a96fba6SXin Li SecureBlob SecureBlobToSecureHex(const SecureBlob& blob) {
133*1a96fba6SXin Li   std::string kHexChars("0123456789ABCDEF");
134*1a96fba6SXin Li   SecureBlob hex(blob.size() * 2, 0);
135*1a96fba6SXin Li   const char* blob_char_data = blob.char_data();
136*1a96fba6SXin Li 
137*1a96fba6SXin Li   // Each input byte creates two output hex characters.
138*1a96fba6SXin Li   for (size_t i = 0; i < blob.size(); ++i) {
139*1a96fba6SXin Li     hex[(i * 2)] = kHexChars[(blob_char_data[i] >> 4) & 0xf];
140*1a96fba6SXin Li     hex[(i * 2) + 1] = kHexChars[blob_char_data[i] & 0xf];
141*1a96fba6SXin Li   }
142*1a96fba6SXin Li   return hex;
143*1a96fba6SXin Li }
144*1a96fba6SXin Li 
SecureHexToSecureBlob(const SecureBlob & hex)145*1a96fba6SXin Li SecureBlob SecureHexToSecureBlob(const SecureBlob& hex) {
146*1a96fba6SXin Li   SecureBlob blob(hex.size()/2, 0);
147*1a96fba6SXin Li 
148*1a96fba6SXin Li   if (hex.size() == 0 || hex.size() % 2)
149*1a96fba6SXin Li     return SecureBlob();
150*1a96fba6SXin Li 
151*1a96fba6SXin Li   for (size_t i = 0; i < hex.size(); i++) {
152*1a96fba6SXin Li     uint8_t v;
153*1a96fba6SXin Li     // Check for invalid characters.
154*1a96fba6SXin Li     if (!ConvertHexToBytes(hex[i], &v))
155*1a96fba6SXin Li       return SecureBlob();
156*1a96fba6SXin Li 
157*1a96fba6SXin Li     blob[i/2] = (blob[i/2] << 4) | (v & 0xf);
158*1a96fba6SXin Li   }
159*1a96fba6SXin Li 
160*1a96fba6SXin Li   return blob;
161*1a96fba6SXin Li }
162*1a96fba6SXin Li 
163*1a96fba6SXin Li }  // namespace brillo
164