1*789431f2SAndroid Build Coastguard Worker /*
2*789431f2SAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
3*789431f2SAndroid Build Coastguard Worker *
4*789431f2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*789431f2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*789431f2SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*789431f2SAndroid Build Coastguard Worker *
8*789431f2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*789431f2SAndroid Build Coastguard Worker *
10*789431f2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*789431f2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*789431f2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*789431f2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*789431f2SAndroid Build Coastguard Worker * limitations under the License.
15*789431f2SAndroid Build Coastguard Worker */
16*789431f2SAndroid Build Coastguard Worker
17*789431f2SAndroid Build Coastguard Worker #include <keymaster/serializable.h>
18*789431f2SAndroid Build Coastguard Worker
19*789431f2SAndroid Build Coastguard Worker #include <assert.h>
20*789431f2SAndroid Build Coastguard Worker
21*789431f2SAndroid Build Coastguard Worker #include <keymaster/android_keymaster_utils.h>
22*789431f2SAndroid Build Coastguard Worker
23*789431f2SAndroid Build Coastguard Worker namespace keymaster {
24*789431f2SAndroid Build Coastguard Worker
__buffer_bound_check(const uint8_t * buf,const uint8_t * end,size_t len)25*789431f2SAndroid Build Coastguard Worker bool __buffer_bound_check(const uint8_t* buf, const uint8_t* end, size_t len) {
26*789431f2SAndroid Build Coastguard Worker uintptr_t buf_next;
27*789431f2SAndroid Build Coastguard Worker bool overflow_occurred = __builtin_add_overflow(__pval(buf), len, &buf_next);
28*789431f2SAndroid Build Coastguard Worker return (!overflow_occurred) && (buf_next <= __pval(end));
29*789431f2SAndroid Build Coastguard Worker }
30*789431f2SAndroid Build Coastguard Worker
append_to_buf(uint8_t * buf,const uint8_t * end,const void * data,size_t data_len)31*789431f2SAndroid Build Coastguard Worker uint8_t* append_to_buf(uint8_t* buf, const uint8_t* end, const void* data, size_t data_len) {
32*789431f2SAndroid Build Coastguard Worker if (__buffer_bound_check(buf, end, data_len) && data != nullptr) {
33*789431f2SAndroid Build Coastguard Worker memcpy(buf, data, data_len);
34*789431f2SAndroid Build Coastguard Worker return buf + data_len;
35*789431f2SAndroid Build Coastguard Worker } else {
36*789431f2SAndroid Build Coastguard Worker return buf;
37*789431f2SAndroid Build Coastguard Worker }
38*789431f2SAndroid Build Coastguard Worker }
39*789431f2SAndroid Build Coastguard Worker
copy_from_buf(const uint8_t ** buf_ptr,const uint8_t * end,void * dest,size_t size)40*789431f2SAndroid Build Coastguard Worker bool copy_from_buf(const uint8_t** buf_ptr, const uint8_t* end, void* dest, size_t size) {
41*789431f2SAndroid Build Coastguard Worker if (__buffer_bound_check(*buf_ptr, end, size)) {
42*789431f2SAndroid Build Coastguard Worker memcpy(dest, *buf_ptr, size);
43*789431f2SAndroid Build Coastguard Worker *buf_ptr += size;
44*789431f2SAndroid Build Coastguard Worker return true;
45*789431f2SAndroid Build Coastguard Worker } else {
46*789431f2SAndroid Build Coastguard Worker return false;
47*789431f2SAndroid Build Coastguard Worker }
48*789431f2SAndroid Build Coastguard Worker }
49*789431f2SAndroid Build Coastguard Worker
copy_size_and_data_from_buf(const uint8_t ** buf_ptr,const uint8_t * end,size_t * size,UniquePtr<uint8_t[]> * dest)50*789431f2SAndroid Build Coastguard Worker bool copy_size_and_data_from_buf(const uint8_t** buf_ptr, const uint8_t* end, size_t* size,
51*789431f2SAndroid Build Coastguard Worker UniquePtr<uint8_t[]>* dest) {
52*789431f2SAndroid Build Coastguard Worker if (!copy_uint32_from_buf(buf_ptr, end, size)) return false;
53*789431f2SAndroid Build Coastguard Worker
54*789431f2SAndroid Build Coastguard Worker if (*size == 0) {
55*789431f2SAndroid Build Coastguard Worker dest->reset();
56*789431f2SAndroid Build Coastguard Worker return true;
57*789431f2SAndroid Build Coastguard Worker }
58*789431f2SAndroid Build Coastguard Worker
59*789431f2SAndroid Build Coastguard Worker if (__buffer_bound_check(*buf_ptr, end, *size)) {
60*789431f2SAndroid Build Coastguard Worker dest->reset(new (std::nothrow) uint8_t[*size]);
61*789431f2SAndroid Build Coastguard Worker if (!dest->get()) {
62*789431f2SAndroid Build Coastguard Worker return false;
63*789431f2SAndroid Build Coastguard Worker }
64*789431f2SAndroid Build Coastguard Worker return copy_from_buf(buf_ptr, end, dest->get(), *size);
65*789431f2SAndroid Build Coastguard Worker } else {
66*789431f2SAndroid Build Coastguard Worker return false;
67*789431f2SAndroid Build Coastguard Worker }
68*789431f2SAndroid Build Coastguard Worker }
69*789431f2SAndroid Build Coastguard Worker
reserve(size_t size)70*789431f2SAndroid Build Coastguard Worker bool Buffer::reserve(size_t size) {
71*789431f2SAndroid Build Coastguard Worker if (available_write() < size) {
72*789431f2SAndroid Build Coastguard Worker if (!valid_buffer_state()) {
73*789431f2SAndroid Build Coastguard Worker return false;
74*789431f2SAndroid Build Coastguard Worker }
75*789431f2SAndroid Build Coastguard Worker
76*789431f2SAndroid Build Coastguard Worker size_t new_size = buffer_size_ + size - available_write();
77*789431f2SAndroid Build Coastguard Worker uint8_t* new_buffer = new (std::nothrow) uint8_t[new_size];
78*789431f2SAndroid Build Coastguard Worker if (!new_buffer) return false;
79*789431f2SAndroid Build Coastguard Worker memcpy(new_buffer, buffer_.get() + read_position_, available_read());
80*789431f2SAndroid Build Coastguard Worker memset_s(buffer_.get(), 0, buffer_size_);
81*789431f2SAndroid Build Coastguard Worker buffer_.reset(new_buffer);
82*789431f2SAndroid Build Coastguard Worker buffer_size_ = new_size;
83*789431f2SAndroid Build Coastguard Worker write_position_ -= read_position_;
84*789431f2SAndroid Build Coastguard Worker read_position_ = 0;
85*789431f2SAndroid Build Coastguard Worker }
86*789431f2SAndroid Build Coastguard Worker return true;
87*789431f2SAndroid Build Coastguard Worker }
88*789431f2SAndroid Build Coastguard Worker
Reinitialize(size_t size)89*789431f2SAndroid Build Coastguard Worker bool Buffer::Reinitialize(size_t size) {
90*789431f2SAndroid Build Coastguard Worker Clear();
91*789431f2SAndroid Build Coastguard Worker buffer_.reset(new (std::nothrow) uint8_t[size]);
92*789431f2SAndroid Build Coastguard Worker if (!buffer_.get()) return false;
93*789431f2SAndroid Build Coastguard Worker buffer_size_ = size;
94*789431f2SAndroid Build Coastguard Worker read_position_ = 0;
95*789431f2SAndroid Build Coastguard Worker write_position_ = 0;
96*789431f2SAndroid Build Coastguard Worker return true;
97*789431f2SAndroid Build Coastguard Worker }
98*789431f2SAndroid Build Coastguard Worker
Reinitialize(const void * data,size_t data_len)99*789431f2SAndroid Build Coastguard Worker bool Buffer::Reinitialize(const void* data, size_t data_len) {
100*789431f2SAndroid Build Coastguard Worker Clear();
101*789431f2SAndroid Build Coastguard Worker if (__pval(data) + data_len < __pval(data)) // Pointer wrap check
102*789431f2SAndroid Build Coastguard Worker return false;
103*789431f2SAndroid Build Coastguard Worker buffer_.reset(new (std::nothrow) uint8_t[data_len]);
104*789431f2SAndroid Build Coastguard Worker if (!buffer_.get()) return false;
105*789431f2SAndroid Build Coastguard Worker buffer_size_ = data_len;
106*789431f2SAndroid Build Coastguard Worker memcpy(buffer_.get(), data, data_len);
107*789431f2SAndroid Build Coastguard Worker read_position_ = 0;
108*789431f2SAndroid Build Coastguard Worker write_position_ = buffer_size_;
109*789431f2SAndroid Build Coastguard Worker return true;
110*789431f2SAndroid Build Coastguard Worker }
111*789431f2SAndroid Build Coastguard Worker
available_write() const112*789431f2SAndroid Build Coastguard Worker size_t Buffer::available_write() const {
113*789431f2SAndroid Build Coastguard Worker assert(buffer_size_ >= write_position_);
114*789431f2SAndroid Build Coastguard Worker return buffer_size_ - write_position_;
115*789431f2SAndroid Build Coastguard Worker }
116*789431f2SAndroid Build Coastguard Worker
available_read() const117*789431f2SAndroid Build Coastguard Worker size_t Buffer::available_read() const {
118*789431f2SAndroid Build Coastguard Worker assert(buffer_size_ >= write_position_);
119*789431f2SAndroid Build Coastguard Worker assert(write_position_ >= read_position_);
120*789431f2SAndroid Build Coastguard Worker return write_position_ - read_position_;
121*789431f2SAndroid Build Coastguard Worker }
122*789431f2SAndroid Build Coastguard Worker
valid_buffer_state() const123*789431f2SAndroid Build Coastguard Worker bool Buffer::valid_buffer_state() const {
124*789431f2SAndroid Build Coastguard Worker return (buffer_size_ >= write_position_) && (write_position_ >= read_position_);
125*789431f2SAndroid Build Coastguard Worker }
126*789431f2SAndroid Build Coastguard Worker
write(const uint8_t * src,size_t write_length)127*789431f2SAndroid Build Coastguard Worker bool Buffer::write(const uint8_t* src, size_t write_length) {
128*789431f2SAndroid Build Coastguard Worker if (available_write() < write_length) return false;
129*789431f2SAndroid Build Coastguard Worker memcpy(buffer_.get() + write_position_, src, write_length);
130*789431f2SAndroid Build Coastguard Worker write_position_ += write_length;
131*789431f2SAndroid Build Coastguard Worker return true;
132*789431f2SAndroid Build Coastguard Worker }
133*789431f2SAndroid Build Coastguard Worker
read(uint8_t * dest,size_t read_length)134*789431f2SAndroid Build Coastguard Worker bool Buffer::read(uint8_t* dest, size_t read_length) {
135*789431f2SAndroid Build Coastguard Worker if (available_read() < read_length) return false;
136*789431f2SAndroid Build Coastguard Worker memcpy(dest, buffer_.get() + read_position_, read_length);
137*789431f2SAndroid Build Coastguard Worker read_position_ += read_length;
138*789431f2SAndroid Build Coastguard Worker return true;
139*789431f2SAndroid Build Coastguard Worker }
140*789431f2SAndroid Build Coastguard Worker
advance_write(int distance)141*789431f2SAndroid Build Coastguard Worker bool Buffer::advance_write(int distance) {
142*789431f2SAndroid Build Coastguard Worker if (distance < 0) {
143*789431f2SAndroid Build Coastguard Worker return false;
144*789431f2SAndroid Build Coastguard Worker }
145*789431f2SAndroid Build Coastguard Worker
146*789431f2SAndroid Build Coastguard Worker const size_t validated_distance = static_cast<size_t>(distance);
147*789431f2SAndroid Build Coastguard Worker size_t new_write_position = 0;
148*789431f2SAndroid Build Coastguard Worker
149*789431f2SAndroid Build Coastguard Worker // if an integer overflow occurred or the new position exceeds the buffer_size return false.
150*789431f2SAndroid Build Coastguard Worker if (__builtin_add_overflow(write_position_, validated_distance, &new_write_position) ||
151*789431f2SAndroid Build Coastguard Worker new_write_position > buffer_size_) {
152*789431f2SAndroid Build Coastguard Worker return false;
153*789431f2SAndroid Build Coastguard Worker }
154*789431f2SAndroid Build Coastguard Worker
155*789431f2SAndroid Build Coastguard Worker write_position_ = new_write_position;
156*789431f2SAndroid Build Coastguard Worker return true;
157*789431f2SAndroid Build Coastguard Worker }
158*789431f2SAndroid Build Coastguard Worker
SerializedSize() const159*789431f2SAndroid Build Coastguard Worker size_t Buffer::SerializedSize() const {
160*789431f2SAndroid Build Coastguard Worker return sizeof(uint32_t) + available_read();
161*789431f2SAndroid Build Coastguard Worker }
162*789431f2SAndroid Build Coastguard Worker
Serialize(uint8_t * buf,const uint8_t * end) const163*789431f2SAndroid Build Coastguard Worker uint8_t* Buffer::Serialize(uint8_t* buf, const uint8_t* end) const {
164*789431f2SAndroid Build Coastguard Worker return append_size_and_data_to_buf(buf, end, peek_read(), available_read());
165*789431f2SAndroid Build Coastguard Worker }
166*789431f2SAndroid Build Coastguard Worker
Deserialize(const uint8_t ** buf_ptr,const uint8_t * end)167*789431f2SAndroid Build Coastguard Worker bool Buffer::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
168*789431f2SAndroid Build Coastguard Worker Clear();
169*789431f2SAndroid Build Coastguard Worker if (!copy_size_and_data_from_buf(buf_ptr, end, &buffer_size_, &buffer_)) {
170*789431f2SAndroid Build Coastguard Worker buffer_.reset();
171*789431f2SAndroid Build Coastguard Worker buffer_size_ = 0;
172*789431f2SAndroid Build Coastguard Worker return false;
173*789431f2SAndroid Build Coastguard Worker }
174*789431f2SAndroid Build Coastguard Worker write_position_ = buffer_size_;
175*789431f2SAndroid Build Coastguard Worker return true;
176*789431f2SAndroid Build Coastguard Worker }
177*789431f2SAndroid Build Coastguard Worker
Clear()178*789431f2SAndroid Build Coastguard Worker void Buffer::Clear() {
179*789431f2SAndroid Build Coastguard Worker memset_s(buffer_.get(), 0, buffer_size_);
180*789431f2SAndroid Build Coastguard Worker buffer_.reset();
181*789431f2SAndroid Build Coastguard Worker read_position_ = 0;
182*789431f2SAndroid Build Coastguard Worker write_position_ = 0;
183*789431f2SAndroid Build Coastguard Worker buffer_size_ = 0;
184*789431f2SAndroid Build Coastguard Worker }
185*789431f2SAndroid Build Coastguard Worker
186*789431f2SAndroid Build Coastguard Worker } // namespace keymaster
187