Update ODK library for OPK compatibility
This is a merge from http://go/wvgerrit of several changes to the ODK library that allow it to be used in the same compilation unit as the OPK serialization/deserialization code. Merge of: http://go/wvgerrit/104403 http://go/wvgerrit/105663 http://go/wvgerrit/106004 http://go/wvgerrit/107903 http://go/wvgerrit/107985 http://go/wvgerrit/110167 http://go/wvgerrit/110403 http://go/wvgerrit/110423 http://go/wvgerrit/110663 http://go/wvgerrit/110703 http://go/wvgerrit/110985 http://go/wvgerrit/111703 http://go/wvgerrit/112563 http://go/wvgerrit/113243 http://go/wvgerrit/115204 http://go/wvgerrit/117803 http://go/wvgerrit/121949 bug: 174518179 bug: 175920940 bug: 175126254 Change-Id: I433459182043ca43a040cdbc16d04f2b8215067a
This commit is contained in:
@@ -4,71 +4,61 @@
|
||||
|
||||
#include "serialization_base.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "OEMCryptoCENCCommon.h"
|
||||
#include "odk_message.h"
|
||||
#include "odk_message_priv.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;
|
||||
};
|
||||
|
||||
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;
|
||||
/*
|
||||
* An ODK_Message_Impl pointer must only be obtained by calling GetMessageImpl.
|
||||
* This forces any message to pass the validity check before being operated on,
|
||||
* which means that no function can modify or access the internals of a message
|
||||
* without having it be validated first.
|
||||
*/
|
||||
static ODK_Message_Impl* GetMessageImpl(ODK_Message* message) {
|
||||
if (!ODK_Message_IsValid(message)) return NULL;
|
||||
return (ODK_Message_Impl*)message;
|
||||
}
|
||||
|
||||
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;
|
||||
static void PackBytes(ODK_Message* message, const uint8_t* ptr, size_t count) {
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
if (!message_impl) return;
|
||||
if (count <= message_impl->capacity - message_impl->size) {
|
||||
memcpy((void*)(message_impl->base + message_impl->size), (const void*)ptr,
|
||||
count);
|
||||
message_impl->size += count;
|
||||
} else {
|
||||
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void Pack_enum(Message* message, int value) {
|
||||
void Pack_enum(ODK_Message* message, int value) {
|
||||
uint32_t v32 = value;
|
||||
Pack_uint32_t(message, &v32);
|
||||
}
|
||||
|
||||
void Pack_bool(Message* message, const bool* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_bool(ODK_Message* message, const bool* value) {
|
||||
assert(value);
|
||||
uint8_t data[4] = {0};
|
||||
data[3] = *value ? 1 : 0;
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint16_t(Message* message, const uint16_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint16_t(ODK_Message* message, const uint16_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[2] = {0};
|
||||
data[0] = *value >> 8;
|
||||
data[1] = *value >> 0;
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint32_t(Message* message, const uint32_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint32_t(ODK_Message* message, const uint32_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[4] = {0};
|
||||
data[0] = *value >> 24;
|
||||
data[1] = *value >> 16;
|
||||
@@ -77,160 +67,112 @@ void Pack_uint32_t(Message* message, const uint32_t* value) {
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint64_t(Message* message, const uint64_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint64_t(ODK_Message* message, const uint64_t* value) {
|
||||
assert(value);
|
||||
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;
|
||||
void PackArray(ODK_Message* message, const uint8_t* base, size_t size) {
|
||||
PackBytes(message, base, size);
|
||||
}
|
||||
|
||||
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj) {
|
||||
void Pack_OEMCrypto_Substring(ODK_Message* message,
|
||||
const OEMCrypto_Substring* obj) {
|
||||
assert(obj);
|
||||
uint32_t offset = (uint32_t)obj->offset;
|
||||
uint32_t length = (uint32_t)obj->length;
|
||||
Pack_uint32_t(msg, &offset);
|
||||
Pack_uint32_t(msg, &length);
|
||||
Pack_uint32_t(message, &offset);
|
||||
Pack_uint32_t(message, &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;
|
||||
static void UnpackBytes(ODK_Message* message, uint8_t* ptr, size_t count) {
|
||||
assert(ptr);
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
if (!message_impl) return;
|
||||
if (count <= message_impl->size - message_impl->read_offset) {
|
||||
memcpy((void*)ptr, (void*)(message_impl->base + message_impl->read_offset),
|
||||
count);
|
||||
message_impl->read_offset += count;
|
||||
} else {
|
||||
message->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
|
||||
message_impl->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int Unpack_enum(Message* message) {
|
||||
int Unpack_enum(ODK_Message* message) {
|
||||
uint32_t v32;
|
||||
Unpack_uint32_t(message, &v32);
|
||||
return v32;
|
||||
}
|
||||
|
||||
void Unpack_bool(Message* message, bool* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_bool(ODK_Message* message, bool* value) {
|
||||
uint8_t data[4] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
assert(value);
|
||||
*value = (0 != data[3]);
|
||||
}
|
||||
|
||||
void Unpack_uint16_t(Message* message, uint16_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_uint16_t(ODK_Message* message, uint16_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[2] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
*value = data[0];
|
||||
*value = *value << 8 | data[1];
|
||||
}
|
||||
|
||||
void Unpack_uint32_t(Message* message, uint32_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_uint32_t(ODK_Message* message, uint32_t* value) {
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
if (!message_impl) return;
|
||||
uint8_t data[4] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
assert(value);
|
||||
*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;
|
||||
void Unpack_uint64_t(ODK_Message* message, uint64_t* value) {
|
||||
uint32_t hi = 0;
|
||||
uint32_t lo = 0;
|
||||
Unpack_uint32_t(message, &hi);
|
||||
Unpack_uint32_t(message, &lo);
|
||||
assert(value);
|
||||
*value = hi;
|
||||
*value = *value << 32 | lo;
|
||||
}
|
||||
|
||||
void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj) {
|
||||
void Unpack_OEMCrypto_Substring(ODK_Message* message,
|
||||
OEMCrypto_Substring* obj) {
|
||||
uint32_t offset = 0, length = 0;
|
||||
Unpack_uint32_t(msg, &offset);
|
||||
Unpack_uint32_t(msg, &length);
|
||||
if (!ValidMessage(msg)) return;
|
||||
Unpack_uint32_t(message, &offset);
|
||||
Unpack_uint32_t(message, &length);
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
if (!message_impl) return;
|
||||
|
||||
/* Each substring should be contained within the message body, which is in the
|
||||
* total message, just after the core message. The offset of a substring is
|
||||
* relative to the message body. So we need to verify:
|
||||
* 0 < offset and offset + length < message->capacity - message->size
|
||||
* or offset + length + message->size < message->capacity
|
||||
* 0 < offset and offset + length < message_impl->capacity -
|
||||
* message_impl->size or offset + length + message_impl->size <
|
||||
* message_impl->capacity
|
||||
*/
|
||||
size_t substring_end = 0; /* = offset + length; */
|
||||
size_t end = 0; /* = substring_end + message->size; */
|
||||
size_t end = 0; /* = substring_end + message_impl->size; */
|
||||
if (odk_add_overflow_ux(offset, length, &substring_end) ||
|
||||
odk_add_overflow_ux(substring_end, msg->size, &end) ||
|
||||
end > msg->capacity) {
|
||||
msg->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
odk_add_overflow_ux(substring_end, message_impl->size, &end) ||
|
||||
end > message_impl->capacity) {
|
||||
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
return;
|
||||
}
|
||||
assert(obj);
|
||||
obj->offset = offset;
|
||||
obj->length = length;
|
||||
}
|
||||
|
||||
/* copy out */
|
||||
void UnpackArray(Message* message, uint8_t* address, size_t size) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void UnpackArray(ODK_Message* message, uint8_t* address, size_t size) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
if (size > message->capacity)
|
||||
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
else
|
||||
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); }
|
||||
|
||||
Reference in New Issue
Block a user