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