/* 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_nonce_table.h" #include "stddef.h" #include "assert_interface.h" void AddNonce(NonceTable* nonce_table, uint32_t nonce) { ASSERT(nonce_table != NULL, "nonce_table is NULL"); int new_slot = -1; int oldest_slot = -1; /* Flush any nonce_table->nonces that have been checked but not flushed. After flush, nonce_table->nonces will be either valid or invalid. */ FlushNonces(nonce_table); for (int i = 0; i < NONCE_TABLE_SIZE; i++) { /* Increase nonce_table->age of all valid nonce_table->nonces. */ if (nonce_table->state[i] == NT_STATE_VALID) { nonce_table->age[i]++; if (oldest_slot == -1) { oldest_slot = i; } else { if (nonce_table->age[i] > nonce_table->age[oldest_slot]) { oldest_slot = i; } } } else { if (new_slot == -1) { nonce_table->age[i] = 0; nonce_table->nonces[i] = nonce; nonce_table->state[i] = NT_STATE_VALID; new_slot = i; } } } if (new_slot == -1) { /* reuse oldest */ ASSERT(oldest_slot != -1, "oldest_slot is -1"); int i = oldest_slot; nonce_table->age[i] = 0; nonce_table->nonces[i] = nonce; nonce_table->state[i] = NT_STATE_VALID; } } bool CheckNonce(NonceTable* nonce_table, uint32_t nonce) { ASSERT(nonce_table != NULL, "nonce_table is NULL"); for (int i = 0; i < NONCE_TABLE_SIZE; i++) { if (nonce_table->state[i] != NT_STATE_INVALID) { if (nonce_table->nonces[i] == nonce) { nonce_table->state[i] = NT_STATE_FLUSH_PENDING; return true; } } } return false; } bool NonceCollision(NonceTable* nonce_table, uint32_t nonce) { ASSERT(nonce_table != NULL, "nonce_table is NULL"); for (int i = 0; i < NONCE_TABLE_SIZE; i++) { if (nonce_table->nonces[i] == nonce && nonce_table->state[i] != NT_STATE_INVALID) { return true; } } return false; } void FlushNonces(NonceTable* nonce_table) { ASSERT(nonce_table != NULL, "nonce_table is NULL"); for (int i = 0; i < NONCE_TABLE_SIZE; i++) { if (nonce_table->state[i] == NT_STATE_FLUSH_PENDING) { nonce_table->state[i] = NT_STATE_INVALID; } } }