See https://developers.google.com/widevine/drm/client/opk for documentation and an integration guide.
112 lines
3.8 KiB
C
112 lines
3.8 KiB
C
/* Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
|
source code may only be used and distributed under the Widevine License
|
|
Agreement. */
|
|
|
|
#include "oemcrypto_asymmetric_key_table.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "oemcrypto_object_table.h"
|
|
#include "wtpi_abort_interface.h"
|
|
#include "wtpi_logging_interface.h"
|
|
|
|
#if MAX_NUMBER_OF_ASYMMETRIC_KEYS <= 0
|
|
# error "MAX_NUMBER_OF_ASYMMETRIC_KEYS must be > 0"
|
|
#elif MAX_NUMBER_OF_ASYMMETRIC_KEYS >= UINT32_MAX - 1
|
|
# error "MAX_NUMBER_OF_ASYMMETRIC_KEYS is too large"
|
|
#endif
|
|
|
|
static OEMCryptoResult DtorTrampoline(void* key) {
|
|
return OPKI_FreeAsymmetricKey((AsymmetricKey*)key);
|
|
}
|
|
|
|
DEFINE_OBJECT_TABLE(key_table, AsymmetricKey, MAX_NUMBER_OF_ASYMMETRIC_KEYS,
|
|
&DtorTrampoline);
|
|
|
|
void OPKI_InitializeAsymmetricKeyTable(void) {
|
|
OPKI_UnsafeClearObjectTable(&key_table);
|
|
}
|
|
|
|
uint32_t OPKI_MaxNumberOfAsymmetricKeys(void) { return key_table.capacity; }
|
|
|
|
OEMCryptoResult OPKI_NumberOfUsedAsymmetricKeys(uint32_t* num_used_keys) {
|
|
if (num_used_keys == NULL) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
*num_used_keys = OPKI_GetObjectTableUseCount(&key_table);
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult OPKI_CreateAsymmetricKey(
|
|
AsymmetricKey** key, AsymmetricKeyType key_type, const uint8_t* wrapped_key,
|
|
size_t wrapped_key_length, size_t key_size, uint32_t allowed_schemes) {
|
|
if (key == NULL || wrapped_key == NULL || wrapped_key_length == 0)
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
OEMCryptoResult result;
|
|
if (*key != NULL) {
|
|
result = OPKI_FreeAsymmetricKeyFromTable(key);
|
|
if (result != OEMCrypto_SUCCESS) return result;
|
|
}
|
|
bool key_found = false;
|
|
AsymmetricKey* cur_key = NULL;
|
|
/* If the same wrapped key already exists in the key table, just updates the
|
|
* reference counter and returns a pointer to the existing key. */
|
|
for (uint32_t i = 0; i < key_table.capacity; i++) {
|
|
cur_key = (AsymmetricKey*)OPKI_GetFromObjectTable(&key_table, i);
|
|
if (cur_key != NULL && key_type == cur_key->key_type &&
|
|
wrapped_key_length == cur_key->wrapped_key_length &&
|
|
memcmp(wrapped_key, cur_key->wrapped_key, wrapped_key_length) == 0) {
|
|
key_found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!key_found) {
|
|
cur_key = OPKI_AllocFromObjectTable(&key_table, NULL);
|
|
if (cur_key == NULL) return OEMCrypto_ERROR_TOO_MANY_KEYS;
|
|
result = OPKI_InitializeAsymmetricKey(cur_key, key_type, wrapped_key,
|
|
wrapped_key_length, key_size,
|
|
allowed_schemes);
|
|
if (result != OEMCrypto_SUCCESS) {
|
|
OPKI_FreeAsymmetricKeyFromTable(key);
|
|
return result;
|
|
}
|
|
}
|
|
cur_key->ref_count++;
|
|
*key = cur_key;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult OPKI_FreeAsymmetricKeyFromTable(AsymmetricKey** key) {
|
|
if (!key) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
if ((*key) == NULL) return OEMCrypto_SUCCESS;
|
|
OEMCryptoResult result = OEMCrypto_SUCCESS;
|
|
if ((*key)->ref_count > 0) {
|
|
(*key)->ref_count--;
|
|
}
|
|
if ((*key)->ref_count == 0) {
|
|
result = OPKI_FreeFromObjectTable(&key_table, *key);
|
|
}
|
|
if (result == OEMCrypto_SUCCESS) *key = NULL;
|
|
return result;
|
|
}
|
|
|
|
OEMCryptoResult OPKI_TerminateAsymmetricKeyTable(void) {
|
|
OEMCryptoResult result = OEMCrypto_SUCCESS;
|
|
for (uint32_t i = 0; i < key_table.capacity; i++) {
|
|
AsymmetricKey* key = OPKI_GetFromObjectTable(&key_table, i);
|
|
if (key) {
|
|
/* Attempt to free the key. */
|
|
key->ref_count = 0;
|
|
OEMCryptoResult free_result = OPKI_FreeAsymmetricKeyFromTable(&key);
|
|
if (free_result != OEMCrypto_SUCCESS) {
|
|
LOGE("Could not free asymmetric key at index %u with error: %u", i,
|
|
free_result);
|
|
if (result == OEMCrypto_SUCCESS) {
|
|
result = OEMCrypto_ERROR_TERMINATE_FAILED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|