15ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden/*
25ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * Copyright 2014 The Android Open Source Project
35ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden *
45ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * Licensed under the Apache License, Version 2.0 (the "License");
55ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * you may not use this file except in compliance with the License.
65ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * You may obtain a copy of the License at
75ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden *
85ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden *      http://www.apache.org/licenses/LICENSE-2.0
95ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden *
105ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * Unless required by applicable law or agreed to in writing, software
115ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * distributed under the License is distributed on an "AS IS" BASIS,
125ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * See the License for the specific language governing permissions and
145ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * limitations under the License.
155ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden */
165ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden#include <keymaster/serializable.h>
180f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
190f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden#include <assert.h>
200f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
21f38a002624126ca837865826f948edc9100d6e8aJanis Danisevskis#include <keymaster/new>
220f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
23b6837e7a62a1192e33beef586282812239ee8b28Shawn Willden#include <keymaster/android_keymaster_utils.h>
245ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
255ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdennamespace keymaster {
265ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
278d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willdenuint8_t* append_to_buf(uint8_t* buf, const uint8_t* end, const void* data, size_t data_len) {
28637dd8429285bfdc0b89622476ea94d782b1eb14Sami Tolvanen    if (__pval(buf) + data_len < __pval(buf))  // Pointer wrap check
290f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return buf;
300f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
310f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    if (buf + data_len <= end) {
328d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        memcpy(buf, data, data_len);
330f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return buf + data_len;
340f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    }
350f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    return buf;
368d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden}
378d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden
38172f8c9be706e27f43022063bbc7f4b0177583acShawn Willdenbool copy_from_buf(const uint8_t** buf_ptr, const uint8_t* end, void* dest, size_t size) {
39637dd8429285bfdc0b89622476ea94d782b1eb14Sami Tolvanen    if (__pval(*buf_ptr) + size < __pval(*buf_ptr))  // Pointer wrap check
400f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return false;
410f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
42172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    if (end < *buf_ptr + size)
435ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
44172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    memcpy(dest, *buf_ptr, size);
45172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    *buf_ptr += size;
465ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
475ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
485ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
49172f8c9be706e27f43022063bbc7f4b0177583acShawn Willdenbool copy_size_and_data_from_buf(const uint8_t** buf_ptr, const uint8_t* end, size_t* size,
50f2282b3c6690ccfaa7878886f01693ef4f0b3bedShawn Willden                                 UniquePtr<uint8_t[]>* dest) {
510f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    if (!copy_uint32_from_buf(buf_ptr, end, size))
5258e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden        return false;
530f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
54637dd8429285bfdc0b89622476ea94d782b1eb14Sami Tolvanen    if (__pval(*buf_ptr) + *size < __pval(*buf_ptr))  // Pointer wrap check
550f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return false;
560f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
570f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    if (*buf_ptr + *size > end)
580f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return false;
590f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
60172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    if (*size == 0) {
61f2282b3c6690ccfaa7878886f01693ef4f0b3bedShawn Willden        dest->reset();
62172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        return true;
63172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    }
640f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    dest->reset(new (std::nothrow) uint8_t[*size]);
650f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    if (!dest->get())
668d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return false;
67f2282b3c6690ccfaa7878886f01693ef4f0b3bedShawn Willden    return copy_from_buf(buf_ptr, end, dest->get(), *size);
6858e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden}
6958e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden
7098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdenbool Buffer::reserve(size_t size) {
7198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    if (available_write() < size) {
7298d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        size_t new_size = buffer_size_ + size - available_write();
730f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        uint8_t* new_buffer = new (std::nothrow) uint8_t[new_size];
7498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        if (!new_buffer)
7598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden            return false;
7698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        memcpy(new_buffer, buffer_.get() + read_position_, available_read());
7798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        memset_s(buffer_.get(), 0, buffer_size_);
7898d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        buffer_.reset(new_buffer);
7998d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        buffer_size_ = new_size;
8098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        write_position_ -= read_position_;
8198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        read_position_ = 0;
8298d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    }
8398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return true;
8498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
8598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
8698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdenbool Buffer::Reinitialize(size_t size) {
8798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    Clear();
880f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    buffer_.reset(new (std::nothrow) uint8_t[size]);
890f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    if (!buffer_.get())
9098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        return false;
9198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    buffer_size_ = size;
9298d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    read_position_ = 0;
9398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    write_position_ = 0;
9498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return true;
9598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
9698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
9798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdenbool Buffer::Reinitialize(const void* data, size_t data_len) {
9898d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    Clear();
99637dd8429285bfdc0b89622476ea94d782b1eb14Sami Tolvanen    if (__pval(data) + data_len < __pval(data))  // Pointer wrap check
1000f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return false;
1010f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    buffer_.reset(new (std::nothrow) uint8_t[data_len]);
1020f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    if (!buffer_.get())
10398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        return false;
10498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    buffer_size_ = data_len;
10598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    memcpy(buffer_.get(), data, data_len);
10698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    read_position_ = 0;
10798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    write_position_ = buffer_size_;
10898d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return true;
10998d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
11098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
11198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdensize_t Buffer::available_write() const {
1120f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    assert(buffer_size_ >= write_position_);
11398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return buffer_size_ - write_position_;
11498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
11598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
11698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdensize_t Buffer::available_read() const {
1170f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    assert(buffer_size_ >= write_position_);
1180f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    assert(write_position_ >= read_position_);
11998d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return write_position_ - read_position_;
12098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
12198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
12298d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdenbool Buffer::write(const uint8_t* src, size_t write_length) {
12398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    if (available_write() < write_length)
12498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        return false;
12598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    memcpy(buffer_.get() + write_position_, src, write_length);
12698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    write_position_ += write_length;
12798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return true;
12898d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
12998d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
13098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdenbool Buffer::read(uint8_t* dest, size_t read_length) {
13198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    if (available_read() < read_length)
13298d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        return false;
13398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    memcpy(dest, buffer_.get() + read_position_, read_length);
13498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    read_position_ += read_length;
13598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return true;
13698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
13798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
13898d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdensize_t Buffer::SerializedSize() const {
13998d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return sizeof(uint32_t) + available_read();
14098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
14198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
14298d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdenuint8_t* Buffer::Serialize(uint8_t* buf, const uint8_t* end) const {
14398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return append_size_and_data_to_buf(buf, end, peek_read(), available_read());
14498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
14598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
14698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdenbool Buffer::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
14798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    Clear();
14898d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    if (!copy_size_and_data_from_buf(buf_ptr, end, &buffer_size_, &buffer_)) {
14998d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        buffer_.reset();
15098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        buffer_size_ = 0;
15198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden        return false;
15298d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    }
15398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    write_position_ = buffer_size_;
15498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    return true;
15598d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
15698d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
15798d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willdenvoid Buffer::Clear() {
1581834d5f82a7ad5884c184fd22c702ac9d915af45Shawn Willden    memset_s(buffer_.get(), 0, buffer_size_);
15998d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    buffer_.reset();
16098d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    read_position_ = 0;
16198d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    write_position_ = 0;
16298d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden    buffer_size_ = 0;
16398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden}
16498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden
1655ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}  // namespace keymaster
166