odk: core serialization structs & functions

odk directory copied from wvgerrit.
branch oemcrypto-v16
commit 0c9a7dc

Bug: 140758896
Test: odk_test
Change-Id: I0c631f771b794468a63e4395f6b9c3b60a1dfd4f
This commit is contained in:
Robert Shih
2019-09-12 23:31:31 -07:00
parent 9ea47dc64a
commit 2443fe807a
22 changed files with 4642 additions and 0 deletions

View File

@@ -0,0 +1,205 @@
/*
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
#include "serialization_base.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "OEMCryptoCENCCommon.h"
#include "odk_assert.h"
#include "odk_overflow.h"
struct _Message {
uint8_t* base;
size_t capacity;
size_t size; /* bytes written */
size_t read_offset; /* bytes read */
MessageStatus status;
};
odk_static_assert(SIZE_OF_MESSAGE_STRUCT >= sizeof(Message),
"SIZE_OF_MESSAGE_STRUCT too small");
bool ValidMessage(Message* message) {
if (message == NULL) {
return false;
}
if (message->status != MESSAGE_STATUS_OK) {
return false;
}
if (message->base == NULL) {
message->status = MESSAGE_STATUS_NULL_POINTER_ERROR;
return false;
}
if (message->size > message->capacity ||
message->read_offset > message->size) {
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
return false;
}
return true;
}
static void PackBytes(Message* message, const uint8_t* ptr, size_t count) {
if (count <= message->capacity - message->size) {
memcpy((void*)(message->base + message->size), (void*)ptr, count);
message->size += count;
} else {
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
}
}
void Pack_uint32_t(Message* message, const uint32_t* value) {
if (!ValidMessage(message)) return;
uint8_t data[4] = {0};
data[0] = *value >> 24;
data[1] = *value >> 16;
data[2] = *value >> 8;
data[3] = *value >> 0;
PackBytes(message, data, sizeof(data));
}
void Pack_uint64_t(Message* message, const uint64_t* value) {
if (!ValidMessage(message)) return;
uint32_t hi = *value >> 32;
uint32_t lo = *value;
Pack_uint32_t(message, &hi);
Pack_uint32_t(message, &lo);
}
void PackArray(Message* message, const uint8_t* base, size_t size) {
if (!ValidMessage(message)) return;
PackBytes(message, base, size);
}
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj) {
uint32_t offset = obj->offset;
uint32_t length = obj->length;
Pack_uint32_t(msg, &offset);
Pack_uint32_t(msg, &length);
}
static void UnpackBytes(Message* message, uint8_t* ptr, size_t count) {
if (count <= message->size - message->read_offset) {
memcpy((void*)ptr, (void*)(message->base + message->read_offset), count);
message->read_offset += count;
} else {
message->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
}
}
void Unpack_uint32_t(Message* message, uint32_t* value) {
if (!ValidMessage(message)) return;
uint8_t data[4] = {0};
UnpackBytes(message, data, sizeof(data));
*value = data[0];
*value = *value << 8 | data[1];
*value = *value << 8 | data[2];
*value = *value << 8 | data[3];
}
void Unpack_uint64_t(Message* message, uint64_t* value) {
if (!ValidMessage(message)) return;
uint32_t hi = 0;
uint32_t lo = 0;
Unpack_uint32_t(message, &hi);
Unpack_uint32_t(message, &lo);
*value = hi;
*value = *value << 32 | lo;
}
void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj) {
uint32_t offset = 0, length = 0;
Unpack_uint32_t(msg, &offset);
Unpack_uint32_t(msg, &length);
if (!ValidMessage(msg)) return;
size_t end = 0;
if (offset > msg->capacity || odk_add_overflow_ux(offset, length, &end) ||
end > msg->capacity) {
msg->status = MESSAGE_STATUS_OVERFLOW_ERROR;
return;
}
obj->offset = offset;
obj->length = length;
}
/* copy out */
void UnpackArray(Message* message, uint8_t* address, size_t size) {
if (!ValidMessage(message)) return;
UnpackBytes(message, address, size);
}
/*
* The message structure, which is separate from the buffer,
* is initialized to reference the buffer
*/
void InitMessage(Message* message, uint8_t* buffer, size_t capacity) {
if (message == NULL) return;
memset(message, 0, sizeof(Message));
message->base = buffer;
message->capacity = capacity;
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
}
/*
* The message structure is in the first sizeof(Memory) bytes
* of the buffer
*/
Message* CreateMessage(uint8_t* buffer, size_t buffer_size) {
if (buffer == NULL || buffer_size < sizeof(Message)) return NULL;
Message* message = (Message*)buffer;
message->base = buffer + sizeof(Message);
message->capacity = buffer_size - sizeof(Message);
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
return message;
}
/*
* Set the message to an empty state
*/
void ResetMessage(Message* message) {
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
}
uint8_t* GetBase(Message* message) {
if (message == NULL) return NULL;
return message->base;
}
size_t GetCapacity(Message* message) {
if (message == NULL) return 0;
return message->capacity;
}
size_t GetSize(Message* message) {
if (message == NULL) return 0;
return message->size;
}
void SetSize(Message* message, size_t size) {
if (message == NULL) return;
message->size = size;
}
MessageStatus GetStatus(Message* message) { return message->status; }
void SetStatus(Message* message, MessageStatus status) {
message->status = status;
}
size_t GetOffset(Message* message) {
if (message == NULL) return 0;
return message->read_offset;
}
size_t SizeOfMessageStruct() { return sizeof(Message); }