144 lines
4.4 KiB
C
144 lines
4.4 KiB
C
/* 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 "oemcrypto_key_table.h"
|
|
|
|
#include "stdint.h"
|
|
#include "string.h"
|
|
|
|
#include "assert_interface.h"
|
|
#include "logging_interface.h"
|
|
|
|
static KeyTable key_table;
|
|
static bool key_table_initialized = false;
|
|
|
|
OEMCryptoResult InitializeKeyTable(void) {
|
|
ASSERT(MAX_NUMBER_OF_KEYS > 0, "MAX_NUMBER_OF_KEYS must be > 0");
|
|
ASSERT(MAX_NUMBER_OF_KEYS < UINT32_MAX - 1,
|
|
"MAX_NUMBER_OF_KEYS is too large");
|
|
if (key_table_initialized) {
|
|
return OEMCrypto_ERROR_INIT_FAILED;
|
|
}
|
|
key_table.size = MAX_NUMBER_OF_KEYS;
|
|
key_table.first_free_key = 0;
|
|
for (uint32_t i = 0; i < key_table.size; i++) {
|
|
key_table.next_free_key[i] = i + 1;
|
|
key_table.is_free[i] = true;
|
|
memset(&key_table.keys[i], 0, sizeof(CryptoKey));
|
|
}
|
|
key_table_initialized = true;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
uint32_t MaxNumberOfKeys(void) { return MAX_NUMBER_OF_KEYS; }
|
|
|
|
OEMCryptoResult NumberOfUsedKeys(uint32_t* num_used_keys) {
|
|
ASSERT(num_used_keys != NULL, "num_used_keys is NULL");
|
|
if (!key_table_initialized) {
|
|
return OEMCrypto_ERROR_SYSTEM_INVALIDATED;
|
|
}
|
|
for (uint32_t i = 0; i < key_table.size; i++) {
|
|
if (!key_table.is_free[i]) {
|
|
(*num_used_keys)++;
|
|
}
|
|
}
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult GrabKey(uint32_t* index) {
|
|
ASSERT(index != NULL, "index is NULL");
|
|
if (!key_table_initialized) {
|
|
return OEMCrypto_ERROR_SYSTEM_INVALIDATED;
|
|
}
|
|
if (key_table.first_free_key == MAX_NUMBER_OF_KEYS) {
|
|
return OEMCrypto_ERROR_TOO_MANY_KEYS;
|
|
}
|
|
*index = key_table.first_free_key;
|
|
key_table.first_free_key = key_table.next_free_key[*index];
|
|
key_table.is_free[*index] = false;
|
|
key_table.keys[*index].key_table_index = *index;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult GetKey(uint32_t index, CryptoKey** key) {
|
|
ASSERT(key != NULL, "key is NULL");
|
|
if (!key_table_initialized) {
|
|
return OEMCrypto_ERROR_SYSTEM_INVALIDATED;
|
|
}
|
|
if (index >= key_table.size || key_table.is_free[index]) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
*key = &key_table.keys[index];
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult CreateKey(CryptoKey** key, const uint8_t* serialized_bytes,
|
|
uint32_t serialized_bytes_length,
|
|
CryptoKeyType key_type,
|
|
CryptoKeyOperation key_operation,
|
|
CryptoKeySize key_size) {
|
|
ASSERT(key != NULL, "key is NULL");
|
|
OEMCryptoResult result;
|
|
if (*key != NULL) {
|
|
result = FreeKey(key);
|
|
if (result != OEMCrypto_SUCCESS) return result;
|
|
}
|
|
uint32_t key_table_index = 0;
|
|
result = GrabKey(&key_table_index);
|
|
if (result != OEMCrypto_SUCCESS) return result;
|
|
result = GetKey(key_table_index, key);
|
|
if (result != OEMCrypto_SUCCESS) {
|
|
FreeKey(key);
|
|
return result;
|
|
}
|
|
result = InitializeCryptoKey(*key, serialized_bytes, serialized_bytes_length,
|
|
key_type, key_operation, key_size);
|
|
if (result != OEMCrypto_SUCCESS) {
|
|
FreeKey(key);
|
|
return result;
|
|
}
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult FreeKey(CryptoKey** key) {
|
|
ASSERT(key != NULL, "key is NULL");
|
|
if (*key == NULL) return OEMCrypto_SUCCESS;
|
|
uint32_t index = (*key)->key_table_index;
|
|
if (!key_table_initialized) {
|
|
return OEMCrypto_ERROR_SYSTEM_INVALIDATED;
|
|
}
|
|
if (index >= key_table.size || key_table.is_free[index]) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
OEMCryptoResult result = FreeCryptoKey(&key_table.keys[index]);
|
|
if (result != OEMCrypto_SUCCESS) {
|
|
return result;
|
|
}
|
|
key_table.next_free_key[index] = key_table.first_free_key;
|
|
key_table.is_free[index] = true;
|
|
key_table.first_free_key = index;
|
|
*key = NULL;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult TerminateKeyTable(void) {
|
|
if (!key_table_initialized) {
|
|
return OEMCrypto_ERROR_TERMINATE_FAILED;
|
|
}
|
|
OEMCryptoResult result = OEMCrypto_SUCCESS;
|
|
for (uint32_t i = 0; i < key_table.size; i++) {
|
|
if (!key_table.is_free[i]) {
|
|
result = OEMCrypto_ERROR_TERMINATE_FAILED;
|
|
/* Attempt to free the key. */
|
|
CryptoKey* key = &key_table.keys[i];
|
|
OEMCryptoResult free_result = FreeKey(&key);
|
|
if (free_result != OEMCrypto_SUCCESS) {
|
|
LOGE("Could not free key at index %d with error: %d", i, free_result);
|
|
}
|
|
}
|
|
}
|
|
key_table_initialized = false;
|
|
return result;
|
|
}
|