1 // Copyright (c) 2012 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
5 #include <cstring> // memcpy
6
7 #include <base/stl_util.h>
8 #include <base/strings/string_number_conversions.h>
9
10 #include "brillo/secure_blob.h"
11
12 namespace brillo {
13
BlobToString(const Blob & blob)14 std::string BlobToString(const Blob& blob) {
15 return std::string(blob.begin(), blob.end());
16 }
17
BlobFromString(const std::string & bytes)18 Blob BlobFromString(const std::string& bytes) {
19 return Blob(bytes.begin(), bytes.end());
20 }
21
CombineBlobs(const std::initializer_list<Blob> & blobs)22 Blob CombineBlobs(const std::initializer_list<Blob>& blobs) {
23 size_t total_size = 0;
24 for (const auto& blob : blobs)
25 total_size += blob.size();
26 Blob concatenation;
27 concatenation.reserve(total_size);
28 for (const auto& blob : blobs)
29 concatenation.insert(concatenation.end(), blob.begin(), blob.end());
30 return concatenation;
31 }
32
SecureBlob(const Blob & blob)33 SecureBlob::SecureBlob(const Blob& blob)
34 : SecureBlob(blob.begin(), blob.end()) {}
35
SecureBlob(const std::string & data)36 SecureBlob::SecureBlob(const std::string& data)
37 : SecureBlob(data.begin(), data.end()) {}
38
~SecureBlob()39 SecureBlob::~SecureBlob() {
40 clear();
41 }
42
resize(size_type count)43 void SecureBlob::resize(size_type count) {
44 if (count < size()) {
45 SecureMemset(data() + count, 0, capacity() - count);
46 }
47 Blob::resize(count);
48 }
49
resize(size_type count,const value_type & value)50 void SecureBlob::resize(size_type count, const value_type& value) {
51 if (count < size()) {
52 SecureMemset(data() + count, 0, capacity() - count);
53 }
54 Blob::resize(count, value);
55 }
56
clear()57 void SecureBlob::clear() {
58 SecureMemset(data(), 0, capacity());
59 Blob::clear();
60 }
61
to_string() const62 std::string SecureBlob::to_string() const {
63 return std::string(data(), data() + size());
64 }
65
Combine(const SecureBlob & blob1,const SecureBlob & blob2)66 SecureBlob SecureBlob::Combine(const SecureBlob& blob1,
67 const SecureBlob& blob2) {
68 SecureBlob result;
69 result.reserve(blob1.size() + blob2.size());
70 result.insert(result.end(), blob1.begin(), blob1.end());
71 result.insert(result.end(), blob2.begin(), blob2.end());
72 return result;
73 }
74
HexStringToSecureBlob(const std::string & input,SecureBlob * output)75 bool SecureBlob::HexStringToSecureBlob(const std::string& input,
76 SecureBlob* output) {
77 // TODO(jorgelo,crbug.com/728047): Consider not using an intermediate
78 // std::vector here at all.
79 std::vector<uint8_t> temp;
80 if (!base::HexStringToBytes(input, &temp)) {
81 output->clear();
82 return false;
83 }
84 output->assign(temp.begin(), temp.end());
85 SecureMemset(temp.data(), 0, temp.capacity());
86 return true;
87 }
88
SecureMemset(void * v,int c,size_t n)89 BRILLO_DISABLE_ASAN void* SecureMemset(void* v, int c, size_t n) {
90 volatile uint8_t* p = reinterpret_cast<volatile uint8_t*>(v);
91 while (n--)
92 *p++ = c;
93 return v;
94 }
95
SecureMemcmp(const void * s1,const void * s2,size_t n)96 int SecureMemcmp(const void* s1, const void* s2, size_t n) {
97 const uint8_t* us1 = reinterpret_cast<const uint8_t*>(s1);
98 const uint8_t* us2 = reinterpret_cast<const uint8_t*>(s2);
99 int result = 0;
100
101 if (0 == n)
102 return 1;
103
104 /* Code snippet without data-dependent branch due to
105 * Nate Lawson (nate@root.org) of Root Labs. */
106 while (n--)
107 result |= *us1++ ^ *us2++;
108
109 return result != 0;
110 }
111
112 } // namespace brillo
113