blob: cc1bf5d079c67e4b034798f39d07d8c57fd25f73 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/crypto/otbn_util.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "sw/device/lib/crypto/drivers/otbn.h"
void otbn_init(otbn_t *ctx) {
*ctx = (otbn_t){
.app = {0},
.app_is_loaded = false,
.error_bits = kOtbnErrBitsNoError,
};
}
otbn_error_t otbn_busy_wait_for_done(otbn_t *ctx) {
while (otbn_is_busy()) {
}
otbn_err_bits_t err_bits;
otbn_get_err_bits(&err_bits);
if (err_bits != kOtbnErrBitsNoError) {
ctx->error_bits = err_bits;
return kOtbnErrorExecutionFailed;
}
return kOtbnErrorOk;
}
/**
* Checks if the OTBN application's IMEM and DMEM address parameters are valid.
*
* IMEM and DMEM ranges must not be "backwards" in memory, with the end address
* coming before the start address, and the IMEM range must additionally be
* non-empty. Finally, separate sections in DMEM must not overlap each other
* when converted to DMEM address space.
*
* @param app the OTBN application to check
* @return true if the addresses are valid, otherwise false.
*/
bool check_app_address_ranges(const otbn_app_t *app) {
// IMEM must have a strictly positive range (cannot be backwards or empty)
if (app->imem_end <= app->imem_start) {
return false;
}
// DMEM data section must not be backwards
if (app->dmem_data_end < app->dmem_data_start) {
return false;
}
return true;
}
otbn_error_t otbn_load_app(otbn_t *ctx, const otbn_app_t app) {
if (!check_app_address_ranges(&app)) {
return kOtbnErrorInvalidArgument;
}
const size_t imem_num_words = app.imem_end - app.imem_start;
const size_t data_num_words = app.dmem_data_end - app.dmem_data_start;
ctx->app_is_loaded = false;
OTBN_RETURN_IF_ERROR(otbn_imem_write(0, app.imem_start, imem_num_words));
otbn_zero_dmem();
if (data_num_words > 0) {
OTBN_RETURN_IF_ERROR(
otbn_dmem_write(0, app.dmem_data_start, data_num_words));
}
ctx->app = app;
ctx->app_is_loaded = true;
return kOtbnErrorOk;
}
otbn_error_t otbn_execute_app(otbn_t *ctx) {
if (!ctx->app_is_loaded) {
return kOtbnErrorInvalidArgument;
}
otbn_execute();
return kOtbnErrorOk;
}
otbn_error_t otbn_copy_data_to_otbn(otbn_t *ctx, size_t len,
const uint32_t *src, otbn_addr_t dest) {
OTBN_RETURN_IF_ERROR(otbn_dmem_write(dest, src, len));
return kOtbnErrorOk;
}
otbn_error_t otbn_copy_data_from_otbn(otbn_t *ctx, size_t len_bytes,
otbn_addr_t src, uint32_t *dest) {
OTBN_RETURN_IF_ERROR(otbn_dmem_read(src, dest, len_bytes));
return kOtbnErrorOk;
}