1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "operation_table.h" 18 19#include <new> 20 21#include <openssl/rand.h> 22 23#include "openssl_err.h" 24#include "operation.h" 25 26namespace keymaster { 27 28OperationTable::Entry::~Entry() { 29 delete operation; 30 operation = NULL; 31 handle = 0; 32} 33 34keymaster_error_t OperationTable::Add(Operation* operation, 35 keymaster_operation_handle_t* op_handle) { 36 if (!table_.get()) { 37 table_.reset(new (std::nothrow) Entry[table_size_]); 38 if (!table_.get()) 39 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 40 } 41 42 UniquePtr<Operation> op(operation); 43 if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) != 1) 44 return TranslateLastOpenSslError(); 45 if (*op_handle == 0) { 46 // Statistically this is vanishingly unlikely, which means if it ever happens in practice, 47 // it indicates a broken RNG. 48 return KM_ERROR_UNKNOWN_ERROR; 49 } 50 51 for (size_t i = 0; i < table_size_; ++i) { 52 if (table_[i].operation == NULL) { 53 table_[i].operation = op.release(); 54 table_[i].handle = *op_handle; 55 return KM_ERROR_OK; 56 } 57 } 58 return KM_ERROR_TOO_MANY_OPERATIONS; 59} 60 61Operation* OperationTable::Find(keymaster_operation_handle_t op_handle) { 62 if (op_handle == 0) 63 return NULL; 64 65 if (!table_.get()) 66 return NULL; 67 68 for (size_t i = 0; i < table_size_; ++i) { 69 if (table_[i].handle == op_handle) 70 return table_[i].operation; 71 } 72 return NULL; 73} 74 75bool OperationTable::Delete(keymaster_operation_handle_t op_handle) { 76 if (!table_.get()) 77 return false; 78 79 for (size_t i = 0; i < table_size_; ++i) { 80 if (table_[i].handle == op_handle) { 81 delete table_[i].operation; 82 table_[i].operation = NULL; 83 table_[i].handle = 0; 84 return true; 85 } 86 } 87 return false; 88} 89 90} // namespace keymaster 91