xref: /aosp_15_r20/system/keymaster/android_keymaster/serializable.cpp (revision 789431f29546679ab5188a97751fb38e3018d44d)
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