107 lines
3.5 KiB
C
107 lines
3.5 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_session_table.h"
|
|
|
|
#include "stdint.h"
|
|
#include "string.h"
|
|
|
|
#include "assert_interface.h"
|
|
#include "logging_interface.h"
|
|
#include "oemcrypto_key.h"
|
|
|
|
static SessionTable session_table;
|
|
static uint32_t open_session_count = 0;
|
|
static bool session_table_initialized = false;
|
|
|
|
OEMCryptoResult InitializeSessionTable(void) {
|
|
ASSERT(MAX_NUMBER_OF_SESSIONS > 0, "MAX_NUMBER_OF_SESSIONS must be > 0");
|
|
ASSERT(MAX_NUMBER_OF_SESSIONS <= UINT32_MAX - 1,
|
|
"MAX_NUMBER_OF_SESSIONS is too large");
|
|
if (session_table_initialized) {
|
|
return OEMCrypto_ERROR_INIT_FAILED;
|
|
}
|
|
session_table.first_free_session = 0;
|
|
for (uint32_t i = 0; i < MAX_NUMBER_OF_SESSIONS; i++) {
|
|
session_table.next_free_session[i] = i + 1;
|
|
session_table.is_free[i] = true;
|
|
memset(&session_table.sessions[i], 0, sizeof(OEMCryptoSession));
|
|
}
|
|
session_table_initialized = true;
|
|
open_session_count = 0;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
uint32_t MaxNumberOfSessions(void) { return MAX_NUMBER_OF_SESSIONS; }
|
|
|
|
OEMCryptoResult NumberOfOpenSessions(uint32_t* num_open_sessions) {
|
|
ASSERT(num_open_sessions != NULL, "num_open_sessions is NULL");
|
|
if (!session_table_initialized) {
|
|
return OEMCrypto_ERROR_SYSTEM_INVALIDATED;
|
|
}
|
|
*num_open_sessions = open_session_count;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult GrabSession(uint32_t* index) {
|
|
ASSERT(index != NULL, "index is NULL");
|
|
if (!session_table_initialized) {
|
|
return OEMCrypto_ERROR_SYSTEM_INVALIDATED;
|
|
}
|
|
if (session_table.first_free_session == MAX_NUMBER_OF_SESSIONS) {
|
|
return OEMCrypto_ERROR_TOO_MANY_SESSIONS;
|
|
}
|
|
*index = session_table.first_free_session;
|
|
session_table.first_free_session = session_table.next_free_session[*index];
|
|
session_table.is_free[*index] = false;
|
|
open_session_count++;
|
|
return InitializeSession(&session_table.sessions[*index], *index);
|
|
}
|
|
|
|
OEMCryptoResult GetSession(uint32_t index, OEMCryptoSession** session) {
|
|
ASSERT(session != NULL, "session is NULL");
|
|
if (!session_table_initialized) {
|
|
return OEMCrypto_ERROR_SYSTEM_INVALIDATED;
|
|
}
|
|
if (index >= MAX_NUMBER_OF_SESSIONS || session_table.is_free[index]) {
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
*session = &session_table.sessions[index];
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
OEMCryptoResult FreeSession(uint32_t index) {
|
|
if (!session_table_initialized) {
|
|
return OEMCrypto_ERROR_SYSTEM_INVALIDATED;
|
|
}
|
|
if (index >= MAX_NUMBER_OF_SESSIONS || session_table.is_free[index]) {
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
session_table.next_free_session[index] = session_table.first_free_session;
|
|
session_table.is_free[index] = true;
|
|
session_table.first_free_session = index;
|
|
open_session_count--;
|
|
return TerminateSession(&session_table.sessions[index]);
|
|
}
|
|
|
|
OEMCryptoResult TerminateSessionTable(void) {
|
|
if (!session_table_initialized) {
|
|
return OEMCrypto_ERROR_TERMINATE_FAILED;
|
|
}
|
|
OEMCryptoResult result = OEMCrypto_SUCCESS;
|
|
for (int i = 0; i < MAX_NUMBER_OF_SESSIONS; i++) {
|
|
if (!session_table.is_free[i]) {
|
|
result = OEMCrypto_ERROR_TERMINATE_FAILED;
|
|
/* Attempt to free the session. */
|
|
OEMCryptoResult free_result = FreeSession(i);
|
|
if (free_result != OEMCrypto_SUCCESS) {
|
|
LOGE("Could not free session %d with error: %d", i, free_result);
|
|
}
|
|
}
|
|
}
|
|
session_table_initialized = false;
|
|
open_session_count = 0;
|
|
return result;
|
|
}
|