osd-contiki/cpu/cc2538/dev/bignum-driver.c
Benoît Thébaudeau f78a132395 cc2538: pka: Fix include paths breakage
The PKA drivers and examples were full of include paths missing the
appropriate prefix, or using angle brackets instead of double quotes or
the other way around.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-01-09 15:43:13 +01:00

1065 lines
30 KiB
C

/*
* Original file:
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Port to Contiki:
* Authors: Andreas Dröscher <contiki@anticat.ch>
* Hu Luo
* Hossein Shafagh <shafagh@inf.ethz.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-bignum
* @{
*
* \file
* Implementation of the cc2538 BigNum driver
*
* bignum_subtract_start bignum_subtract_get_result (subtraction)
* bignum_add_start bignum_add_get_result (addition)
* bignum_mod_start bignum_mod_get_result (modulo)
* bignum_exp_mod_start bignum_exp_mod_get_result (modular exponentiation operation)
* bignum_inv_mod_start bignum_inv_mod_get_result (inverse modulo operation)
* bignum_mul_start bignum_mul_get_result (multiplication)
* bignum_divide_start bignum_divide_get_result (division)
* bignum_cmp_start bignum_cmp_get_result (comparison)
*/
#include "dev/bignum-driver.h"
#include <stdio.h>
#include "reg.h"
#include "dev/nvic.h"
#define ASSERT(IF) if(!(IF)) { return PKA_STATUS_INVALID_PARAM; }
/*---------------------------------------------------------------------------*/
uint8_t
bignum_mod_start(const uint32_t *number,
const uint8_t number_size,
const uint32_t *modulus,
const uint8_t modulus_size,
uint32_t *result_vector,
struct process *process)
{
uint8_t extraBuf;
uint32_t offset;
int i;
/* Check the arguments. */
ASSERT(NULL != number);
ASSERT(NULL != modulus);
ASSERT(NULL != result_vector);
/* make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* calculate the extra buffer requirement. */
extraBuf = 2 + modulus_size % 2;
offset = 0;
/* Update the A ptr with the offset address of the PKA RAM location
* where the number will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the number in PKA RAM */
for(i = 0; i < number_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number[i];
}
/* determine the offset for the next data input. */
offset += 4 * (i + number_size % 2);
/* Update the B ptr with the offset address of the PKA RAM location
* where the divisor will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Load the divisor in PKA RAM. */
for(i = 0; i < modulus_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = modulus[i];
}
/* determine the offset for the next data. */
offset += 4 * (i + extraBuf);
/* Copy the result vector address location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load C ptr with the result location in PKA RAM */
REG(PKA_CPTR) = offset >> 2;
/* Load A length registers with Big number length in 32 bit words. */
REG(PKA_ALENGTH) = number_size;
/* Load B length registers Divisor length in 32-bit words. */
REG(PKA_BLENGTH) = modulus_size;
/* Start the PKCP modulo operation by setting the PKA Function register. */
REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_MODULO);
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_mod_get_result(uint32_t *buffer,
const uint8_t buffer_size,
const uint32_t result_vector)
{
uint32_t regMSWVal;
uint32_t len;
int i;
/* Check the arguments. */
ASSERT(NULL != buffer);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* verify that the operation is complete. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
/* Get the MSW register value. */
regMSWVal = REG(PKA_DIVMSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_DIVMSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result. */
len = ((regMSWVal & PKA_DIVMSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
/* If the size of the buffer provided is less than the result length than
* return error. */
if(buffer_size < len) {
return PKA_STATUS_BUF_UNDERFLOW;
}
/* copy the result from vector C into the pResult. */
for(i = 0; i < len; i++) {
buffer[i] = REG(result_vector + 4 * i);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_cmp_start(const uint32_t *number1,
const uint32_t *number2,
const uint8_t size,
struct process *process)
{
uint32_t offset;
int i;
/* Check the arguments. */
ASSERT(NULL != number1);
ASSERT(NULL != number2);
offset = 0;
/* Make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Update the A ptr with the offset address of the PKA RAM location
* where the first big number will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the first big number in PKA RAM. */
for(i = 0; i < size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number1[i];
}
/* Determine the offset in PKA RAM for the next pointer. */
offset += 4 * (i + size % 2);
/* Update the B ptr with the offset address of the PKA RAM location
* where the second big number will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Load the second big number in PKA RAM. */
for(i = 0; i < size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number2[i];
}
/* Load length registers in 32 bit word size. */
REG(PKA_ALENGTH) = size;
/* Set the PKA Function register for the compare operation
* and start the operation. */
REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_COMPARE);
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_cmp_get_result(void)
{
uint8_t status;
/* verify that the operation is complete. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
status = PKA_STATUS_OPERATION_INPRG;
return status;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
/* Check the compare register. */
switch(REG(PKA_COMPARE)) {
case PKA_COMPARE_A_EQUALS_B:
status = PKA_STATUS_SUCCESS;
break;
case PKA_COMPARE_A_GREATER_THAN_B:
status = PKA_STATUS_A_GR_B;
break;
case PKA_COMPARE_A_LESS_THAN_B:
status = PKA_STATUS_A_LT_B;
break;
default:
status = PKA_STATUS_FAILURE;
break;
}
return status;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_inv_mod_start(const uint32_t *number,
const uint8_t number_size,
const uint32_t *modulus,
const uint8_t modulus_size,
uint32_t *result_vector,
struct process *process)
{
uint32_t offset;
int i;
/* Check the arguments. */
ASSERT(NULL != number);
ASSERT(NULL != modulus);
ASSERT(NULL != result_vector);
offset = 0;
/* Make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Update the A ptr with the offset address of the PKA RAM location
* where the number will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the \e number number in PKA RAM. */
for(i = 0; i < number_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number[i];
}
/* Determine the offset for next data. */
offset += 4 * (i + number_size % 2);
/* Update the B ptr with the offset address of the PKA RAM location
* where the modulus will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Load the \e modulus divisor in PKA RAM. */
for(i = 0; i < modulus_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = modulus[i];
}
/* Determine the offset for result data. */
offset += 4 * (i + modulus_size % 2);
/* Copy the result vector address location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load D ptr with the result location in PKA RAM. */
REG(PKA_DPTR) = offset >> 2;
/* Load the respective length registers. */
REG(PKA_ALENGTH) = number_size;
REG(PKA_BLENGTH) = modulus_size;
/* set the PKA function to InvMod operation and the start the operation. */
REG(PKA_FUNCTION) = 0x0000F000;
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_inv_mod_get_result(uint32_t *buffer,
const uint8_t buffer_size,
const uint32_t result_vector)
{
uint32_t regMSWVal;
uint32_t len;
int i;
/* Check the arguments. */
ASSERT(NULL != buffer);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* Verify that the operation is complete. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
/* Check if the provided buffer length is adequate to store the result
* data. */
if(buffer_size < len) {
return PKA_STATUS_BUF_UNDERFLOW;
}
/* Copy the result from vector C into the \e buffer. */
for(i = 0; i < len; i++) {
buffer[i] = REG(result_vector + 4 * i);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_mul_start(const uint32_t *multiplicand,
const uint8_t multiplicand_size,
const uint32_t *multiplier,
const uint8_t multiplier_size,
uint32_t *result_vector,
struct process *process)
{
uint32_t offset;
int i;
/* Check for the arguments. */
ASSERT(NULL != multiplicand);
ASSERT(NULL != multiplier);
ASSERT(NULL != result_vector);
offset = 0;
/* Make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Update the A ptr with the offset address of the PKA RAM location
* where the multiplicand will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the multiplicand in PKA RAM. */
for(i = 0; i < multiplicand_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = *multiplicand;
multiplicand++;
}
/* Determine the offset for the next data. */
offset += 4 * (i + (multiplicand_size % 2));
/* Update the B ptr with the offset address of the PKA RAM location
* where the multiplier will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Load the multiplier in PKA RAM. */
for(i = 0; i < multiplier_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = *multiplier;
multiplier++;
}
/* Determine the offset for the next data. */
offset += 4 * (i + (multiplier_size % 2));
/* Copy the result vector address location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load C ptr with the result location in PKA RAM. */
REG(PKA_CPTR) = offset >> 2;
/* Load the respective length registers. */
REG(PKA_ALENGTH) = multiplicand_size;
REG(PKA_BLENGTH) = multiplier_size;
/* Set the PKA function to the multiplication and start it. */
REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_MULTIPLY);
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_mul_get_result(uint32_t *buffer,
uint32_t *buffer_size,
const uint32_t result_vector)
{
uint32_t regMSWVal;
uint32_t len;
int i;
/* Check for arguments. */
ASSERT(NULL != buffer);
ASSERT(NULL != buffer_size);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* Verify that the operation is complete. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result. */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
/* Make sure that the length of the supplied result buffer is adequate
* to store the resultant. */
if(*buffer_size < len) {
return PKA_STATUS_BUF_UNDERFLOW;
}
/* Copy the resultant length. */
*buffer_size = len;
/* Copy the result from vector C into the pResult. */
for(i = 0; i < *buffer_size; i++) {
buffer[i] = REG(result_vector + 4 * i);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_add_start(const uint32_t *number1,
const uint8_t number1_size,
const uint32_t *number2,
const uint8_t number2_size,
uint32_t *result_vector,
struct process *process)
{
uint32_t offset;
int i;
/* Check for arguments. */
ASSERT(NULL != number1);
ASSERT(NULL != number2);
ASSERT(NULL != result_vector);
offset = 0;
/* Make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Update the A ptr with the offset address of the PKA RAM location
* where the big number 1 will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the big number 1 in PKA RAM. */
for(i = 0; i < number1_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number1[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + (number1_size % 2));
/* Update the B ptr with the offset address of the PKA RAM location
* where the big number 2 will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Load the big number 2 in PKA RAM. */
for(i = 0; i < number2_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number2[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + (number2_size % 2));
/* Copy the result vector address location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load C ptr with the result location in PKA RAM. */
REG(PKA_CPTR) = offset >> 2;
/* Load respective length registers. */
REG(PKA_ALENGTH) = number1_size;
REG(PKA_BLENGTH) = number2_size;
/* Set the function for the add operation and start the operation. */
REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_ADD);
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_add_get_result(uint32_t *buffer,
uint32_t *buffer_size,
const uint32_t result_vector)
{
uint32_t regMSWVal;
uint32_t len;
int i;
/* Check for the arguments. */
ASSERT(NULL != buffer);
ASSERT(NULL != buffer_size);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* Verify that the operation is complete. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result. */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
/* Make sure that the supplied result buffer is adequate to store the
* resultant data. */
if(*buffer_size < len) {
return PKA_STATUS_BUF_UNDERFLOW;
}
/* Copy the length. */
*buffer_size = len;
/* Copy the result from vector C into the provided buffer. */
for(i = 0; i < *buffer_size; i++) {
buffer[i] = REG(result_vector + 4 * i);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
/* below functions are added by hu luo */
uint8_t
bignum_subtract_start(const uint32_t *number1,
const uint8_t number1_size,
const uint32_t *number2,
const uint8_t number2_size,
uint32_t *result_vector,
struct process *process)
{
uint32_t offset;
int i;
/* Check for arguments. */
ASSERT(NULL != number1);
ASSERT(NULL != number2);
ASSERT(NULL != result_vector);
offset = 0;
/* Make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Update the A ptr with the offset address of the PKA RAM location
* where the big number 1 will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the big number 1 in PKA RAM. */
for(i = 0; i < number1_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number1[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + (number1_size % 2));
/* Update the B ptr with the offset address of the PKA RAM location
* where the big number 2 will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Load the big number 2 in PKA RAM. */
for(i = 0; i < number2_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number2[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + (number2_size % 2));
/* Copy the result vector address location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load C ptr with the result location in PKA RAM. */
REG(PKA_CPTR) = offset >> 2;
/* Load respective length registers. */
REG(PKA_ALENGTH) = number1_size;
REG(PKA_BLENGTH) = number2_size;
/* Set the function for the add operation and start the operation. */
REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_SUBTRACT);
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_subtract_get_result(uint32_t *buffer,
uint32_t *buffer_size,
const uint32_t result_vector)
{
uint32_t regMSWVal;
uint32_t len;
int i;
/* Check for the arguments. */
ASSERT(NULL != buffer);
ASSERT(NULL != buffer_size);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* Verify that the operation is complete. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result. */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
/* Make sure that the supplied result buffer is adequate to store the
* resultant data. */
if(*buffer_size < len) {
return PKA_STATUS_BUF_UNDERFLOW;
}
/* Copy the length. */
*buffer_size = len;
/* Copy the result from vector C into the provided buffer. */
for(i = 0; i < *buffer_size; i++) {
buffer[i] = REG(result_vector + 4 * i);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_exp_mod_start(const uint32_t *number,
const uint8_t number_size,
const uint32_t *modulus,
const uint8_t modulus_size,
const uint32_t *base,
const uint8_t base_size,
uint32_t *result_vector,
struct process *process)
{
uint32_t offset;
int i;
/* Check for the arguments. */
ASSERT(NULL != number);
ASSERT(NULL != modulus);
ASSERT(NULL != base);
ASSERT(NULL != result_vector);
ASSERT(modulus != base);
offset = 0;
/* Make sure no PKA operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Update the A ptr with the offset address of the PKA RAM location
* where the exponent will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the Exponent in PKA RAM. */
for(i = 0; i < number_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = number[i];
}
/* Determine the offset for the next data(BPTR). */
offset += 4 * (i + number_size % 2);
/* Update the B ptr with the offset address of the PKA RAM location
* where the divisor will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Load the Modulus in PKA RAM. */
for(i = 0; i < modulus_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = modulus[i];
}
/* Determine the offset for the next data(CPTR). */
offset += 4 * (i + modulus_size % 2 + 2);
/* Update the C ptr with the offset address of the PKA RAM location
* where the Base will be stored. */
REG(PKA_CPTR) = offset >> 2;
/* Write Base to the Vector C in PKA RAM */
for(i = 0; i < base_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = base[i];
}
/* Determine the offset for the next data.
* INFO D and B can share the same memory area!
* offset += 4 * (i + extraBuf + 2); */
/* Copy the result vector address location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load D ptr with the result location in PKA RAM */
REG(PKA_DPTR) = offset >> 2;
/* Load A length registers with Big number length in 32 bit words. */
REG(PKA_ALENGTH) = number_size;
/* Load B length registers Divisor length in 32-bit words. */
REG(PKA_BLENGTH) = modulus_size;
/* REG(PKA_SHIFT) = 0x00000001;
* Required for (EXPMod-variable): 0x0000A000
* Start the PKCP modulo exponentiation operation(EXPMod-ACT2)
* by setting the PKA Function register. */
REG(PKA_FUNCTION) = 0x0000C000;
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_exp_mod_get_result(uint32_t *buffer,
const uint8_t buffer_size,
const uint32_t result_vector)
{
uint32_t regMSWVal;
uint32_t len;
int i;
/* Check the arguments. */
ASSERT(NULL != buffer);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* verify that the operation is complete. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
/* If the size of the buffer provided is less than the result length than
* return error. */
if(buffer_size < len) {
return PKA_STATUS_BUF_UNDERFLOW;
}
/* copy the result from vector C into the pResult. */
for(i = 0; i < len; i++) {
buffer[i] = REG(result_vector + 4 * i);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_divide_start(const uint32_t *dividend,
const uint8_t dividend_size,
const uint32_t *divisor,
const uint8_t divisor_size,
uint32_t *result_vector,
struct process *process)
{
uint32_t offset;
uint32_t spacing;
int i;
/* We use largest len for spacing */
if(dividend_size > divisor_size) {
spacing = dividend_size;
} else {
spacing = divisor_size;
}
spacing += 2 + spacing % 2;
/* Check for the arguments. */
ASSERT(NULL != dividend);
ASSERT(NULL != divisor);
ASSERT(NULL != result_vector);
/* Make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Update the A ptr with the offset address of the PKA RAM location
* where the multiplicand will be stored. */
offset = 0;
REG(PKA_APTR) = offset >> 2;
/* Load the multiplicand in PKA RAM. */
for(i = 0; i < dividend_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = *dividend;
dividend++;
}
/* Determine the offset for the next data. */
offset += 4 * spacing;
/* Update the B ptr with the offset address of the PKA RAM location
* where the multiplier will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Load the multiplier in PKA RAM. */
for(i = 0; i < divisor_size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = *divisor;
divisor++;
}
/* Determine the offset for the reminder. */
offset += 4 * spacing;
/* Load C ptr with the result location in PKA RAM. */
REG(PKA_CPTR) = offset >> 2;
/* Determine the offset for the quotient. */
offset += 4 * spacing;
/* Copy the quotient vector address location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load D ptr with the result location in PKA RAM. */
REG(PKA_DPTR) = offset >> 2;
/* Load the respective length registers. */
REG(PKA_ALENGTH) = dividend_size;
REG(PKA_BLENGTH) = divisor_size;
/* Set the PKA function to the multiplication and start it. */
REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_DIVIDE);
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
bignum_divide_get_result(uint32_t *buffer,
uint32_t *buffer_size,
const uint32_t result_vector)
{
uint32_t regMSWVal;
uint32_t len;
int i;
/* Check for arguments. */
ASSERT(NULL != buffer);
ASSERT(NULL != buffer_size);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* Verify that the operation is complete. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result. */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
/* Make sure that the length of the supplied result buffer is adequate
* to store the resultant. */
if(*buffer_size < len) {
return PKA_STATUS_BUF_UNDERFLOW;
}
/* Copy the resultant length. */
*buffer_size = len;
/* Copy the result from vector C into the pResult. */
for(i = 0; i < *buffer_size; i++) {
buffer[i] = REG(result_vector + 4 * i);
}
return PKA_STATUS_SUCCESS;
}
/** @} */