first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,717 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "AppleS5L8900XPKE-hardware.h"
|
||||
|
||||
|
||||
#define AppleS5L8900XPKE_hardware_DEBUG 0
|
||||
#undef absolutetime_to_nanoseconds
|
||||
|
||||
#if AppleS5L8900XPKE_hardware_DEBUG
|
||||
static void debug_data(uint8_t *data, size_t length)
|
||||
{
|
||||
uint32_t i=0;
|
||||
printf("data %p,%d\n" , data, length);
|
||||
for (i = 0; i < length; i++) {
|
||||
if( !(i%256) )
|
||||
printf("Seg : %p \n", data);
|
||||
printf("%02X, ", *(data + i));
|
||||
if ((i % 16) == 15)
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#define debug(fmt, args...) printf("AppleS5L8900XPKE-hardware::%s: " fmt "\n", __FUNCTION__ , ##args)
|
||||
#else
|
||||
#define debug(fmt, args...)
|
||||
#define debug_data(data, length)
|
||||
#endif
|
||||
|
||||
|
||||
#if IN_KERNEL
|
||||
extern uint64_t iodelay_time[3];
|
||||
static uint64_t delay_time;
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t
|
||||
PkeSetMode(uint32_t uSegSize)
|
||||
{
|
||||
uint32_t uWriteVal;
|
||||
|
||||
switch (uSegSize) {
|
||||
case PKE_SEG_SIZE_256:
|
||||
uWriteVal = PKE_REGVAL_SEG_SIZE_SEGSIZE_256;
|
||||
break;
|
||||
|
||||
case PKE_SEG_SIZE_128:
|
||||
uWriteVal = PKE_REGVAL_SEG_SIZE_SEGSIZE_128;
|
||||
break;
|
||||
|
||||
case PKE_SEG_SIZE_64:
|
||||
uWriteVal = PKE_REGVAL_SEG_SIZE_SEGSIZE_64;
|
||||
break;
|
||||
|
||||
default:
|
||||
uWriteVal = 0;
|
||||
debug("error setting segment size/mode\n");
|
||||
}
|
||||
|
||||
/* ! write SEG_SIZE and MODE_ID */
|
||||
return (uWriteVal | PKE_REGMASK_SEG_SIZE_MUSTBEONE);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PkeGetSegmentCount(uint32_t uSegSize)
|
||||
{
|
||||
/* return segment total number */
|
||||
switch (uSegSize) {
|
||||
case PKE_SEG_SIZE_256:
|
||||
return PKE_SEG_NUM_CASE256;
|
||||
case PKE_SEG_SIZE_128:
|
||||
return PKE_SEG_NUM_CASE128;
|
||||
case PKE_SEG_SIZE_64:
|
||||
return PKE_SEG_NUM_CASE64;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_precision(uint32_t uBitLen)
|
||||
{
|
||||
uint32_t uPrecision;
|
||||
|
||||
if (uBitLen <= PKE_LEN_BIT_512) {
|
||||
uPrecision = PKE_SIZE_PREC_0;
|
||||
} else if ((uBitLen <= PKE_LEN_BIT_1024) && (uBitLen != PKE_LEN_BIT_672) && (uBitLen != PKE_LEN_BIT_864)) {
|
||||
uPrecision = PKE_SIZE_PREC_1;
|
||||
} else if ((uBitLen <= PKE_LEN_BIT_1536) && (uBitLen != PKE_LEN_BIT_1280) && (uBitLen != PKE_LEN_BIT_1408)) {
|
||||
uPrecision = PKE_SIZE_PREC_2;
|
||||
} else {
|
||||
uPrecision = PKE_SIZE_PREC_3;
|
||||
}
|
||||
return uPrecision;
|
||||
}
|
||||
|
||||
static uint32_t get_chunkSize(uint32_t uBitLen, uint32_t uPrecision)
|
||||
{
|
||||
uint32_t uDiv, uChunk;
|
||||
|
||||
switch (uPrecision) {
|
||||
case PKE_SIZE_PREC_0:
|
||||
if (uBitLen < PKE_LEN_BIT_128) {
|
||||
uBitLen = PKE_LEN_BIT_128;
|
||||
}
|
||||
uDiv = uBitLen >> 5;
|
||||
uChunk = uDiv;
|
||||
if (uBitLen - (uChunk << 5)) {
|
||||
uDiv++;
|
||||
}
|
||||
uChunk = --uDiv;
|
||||
break;
|
||||
|
||||
case PKE_SIZE_PREC_1:
|
||||
uDiv = uBitLen >> 6;
|
||||
uChunk = uDiv;
|
||||
if (uBitLen - (uChunk << 6)) {
|
||||
uDiv++;
|
||||
}
|
||||
uChunk = --uDiv;
|
||||
break;
|
||||
|
||||
case PKE_SIZE_PREC_2:
|
||||
uDiv = (uBitLen / 3) >> 5;
|
||||
uChunk = uDiv;
|
||||
if (uBitLen - ((uChunk * 3) << 5)) {
|
||||
uDiv++;
|
||||
}
|
||||
uChunk = --uDiv;
|
||||
break;
|
||||
|
||||
case PKE_SIZE_PREC_3:
|
||||
uDiv = uBitLen >> 7;
|
||||
uChunk = uDiv;
|
||||
if (uBitLen - (uChunk << 7)) {
|
||||
uDiv++;
|
||||
}
|
||||
uChunk = --uDiv;
|
||||
break;
|
||||
default:
|
||||
debug("Unsupported precision value: %u", uPrecision);
|
||||
uChunk = 0;
|
||||
}
|
||||
return (((uChunk << 3) + 8) << 2);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
config_pke_key_len(uint32_t uBitLen)
|
||||
{
|
||||
uint32_t uDiv, uChunk, uPrecision;
|
||||
|
||||
/* 1. Get Precision */
|
||||
uPrecision = get_precision(uBitLen);
|
||||
|
||||
/* 2. Get chunck size */
|
||||
uChunk = get_chunkSize(uBitLen, uPrecision);
|
||||
|
||||
/* 3. Set precision and chunksize */
|
||||
uDiv = ((uChunk >> 2) - 8) | uPrecision;
|
||||
|
||||
#if IN_KERNEL
|
||||
//Set the IODelay time based on uBitLen.
|
||||
if (uBitLen <= PKE_LEN_BIT_512) {
|
||||
delay_time = iodelay_time[0];
|
||||
}
|
||||
else if (uBitLen <= PKE_LEN_BIT_1024) {
|
||||
delay_time = iodelay_time[1];
|
||||
}
|
||||
else {
|
||||
delay_time = iodelay_time[2];
|
||||
}
|
||||
#endif
|
||||
|
||||
return uDiv;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
RSAPkeSetInOut(uint32_t uDest, uint32_t uSrc1, uint32_t uSrc2)
|
||||
{
|
||||
uint32_t uPosition = 0;
|
||||
|
||||
/*! Set segment ID of src and dest */
|
||||
uPosition = ((uSrc1 << PKE_REGSHIFT_SEG_ID_A_SEG_ID)
|
||||
| (uSrc2 << PKE_REGSHIFT_SEG_ID_B_SEG_ID)
|
||||
| (uDest << PKE_REGSHIFT_SEG_ID_S_SEG_ID));
|
||||
|
||||
return uPosition;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
RSAPkeRun(volatile struct pke_regs *registers, uint32_t uCmdVal)
|
||||
{
|
||||
/*! Run PKE */
|
||||
registers->pke_start = uCmdVal;
|
||||
|
||||
#if IN_KERNEL
|
||||
IODelay(delay_time);
|
||||
#endif
|
||||
|
||||
do {
|
||||
if (!(registers->pke_start & PKE_REGMASK_START_EXEC_ON))
|
||||
return true;
|
||||
} while (1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool shift_left(uint32_t *data, uint32_t data_size)
|
||||
{
|
||||
int prev_carry = 0, cur_carry = 0;
|
||||
uint32_t itr = 0;
|
||||
|
||||
for (itr=0; itr < (data_size/sizeof(uint32_t)); itr++) {
|
||||
cur_carry = data[itr] >> 31;
|
||||
data[itr] = (data[itr] << 1) + prev_carry;
|
||||
prev_carry = cur_carry;
|
||||
}
|
||||
return prev_carry;
|
||||
}
|
||||
|
||||
|
||||
static int32_t highestSetBit(uint32_t *data1, uint32_t data_size)
|
||||
{
|
||||
int32_t ix = data_size/sizeof(uint32_t) - 1; // Most significant word.
|
||||
|
||||
while( ix>=0 && data1[ix]==0) {
|
||||
ix--;
|
||||
}
|
||||
|
||||
if(ix < 0)
|
||||
return -1; //mods is zero.
|
||||
|
||||
uint32_t msNZword = data1[ix];
|
||||
uint32_t b = ((ix+1) * sizeof(uint32_t) * DATA_BYTE_TO_BIT) - 1 ;
|
||||
// Now find the highest set bit.
|
||||
uint32_t mask = 0x80000000;
|
||||
while ((msNZword & mask) == 0) {
|
||||
mask >>= 1;
|
||||
b--;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
static bool is_greater(uint32_t *data1, uint32_t *data2, uint32_t data_size)
|
||||
{
|
||||
uint32_t itr = data_size/sizeof(uint32_t) - 1; //start at the last word.
|
||||
|
||||
do {
|
||||
if(data1[itr] > data2[itr])
|
||||
return true;
|
||||
else if(data1[itr] < data2[itr])
|
||||
return false;
|
||||
//check next word;
|
||||
}while(itr--);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Do data1 = data1 - data2 */
|
||||
static uint32_t sub(uint32_t *data1, uint32_t *data2, uint32_t data_size)
|
||||
{
|
||||
uint32_t borrow = 0;
|
||||
uint32_t itr = 0;
|
||||
|
||||
for(itr=0; itr < (data_size/sizeof(uint32_t)); itr++) {
|
||||
if(borrow) {
|
||||
if(data1[itr] != 0)
|
||||
borrow = 0; //No need to borrow again.
|
||||
data1[itr] -= 1;
|
||||
}
|
||||
|
||||
if( data1[itr] < data2[itr] )
|
||||
borrow = 1;
|
||||
|
||||
data1[itr] -= data2[itr];
|
||||
}
|
||||
if(borrow)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Do data1 = data1 + data2 */
|
||||
static uint32_t add(uint32_t *data1, uint32_t *data2, uint32_t data_size)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
int carry = 0;
|
||||
uint32_t itr = 0;
|
||||
|
||||
for(itr=0; itr < (data_size/sizeof(uint32_t)); itr++) {
|
||||
temp = data1[itr] + data2[itr] + carry;
|
||||
if(temp < data1[itr] || (temp == data1[itr] && carry))
|
||||
carry = 1;
|
||||
else
|
||||
carry = 0;
|
||||
data1[itr] = temp;
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
// The src buffer is assumed to be word aligned at this point.
|
||||
// The hardware register is 4 byte aligned.
|
||||
// The data is in little Endian.
|
||||
static inline void copy_into_segment(volatile uint8_t *memory, uint32_t segment_id, uint32_t segment_size, uint8_t *data, uint32_t length)
|
||||
{
|
||||
volatile uint8_t *dst = memory + segment_id * segment_size;
|
||||
uint32_t ii=0;
|
||||
|
||||
//Make sure the buffer is word aligned.
|
||||
//assert((data & 3) == 0); //We don't assert in iBoot. The only interface makes sure we have aligned buffer.
|
||||
|
||||
uint32_t newLength = length & ~3 ;
|
||||
//Copy words.
|
||||
for(ii=0; ii<(newLength/4); ii++)
|
||||
*((uint32_t*)dst + ii) = *((uint32_t*)data + ii);
|
||||
|
||||
//See if you have less than a word left to copy.
|
||||
if(length & 3) { //have less than 4 bytes left to copy.
|
||||
uint8_t wordData[4] = {0,0,0,0};
|
||||
uint8_t *bytesLeft = data + newLength;
|
||||
for(ii=0; ii<(length & 3); ii++) {
|
||||
wordData[ii] = *(bytesLeft + ii);
|
||||
}
|
||||
*((uint32_t*)(dst+newLength)) = *((uint32_t*)wordData);
|
||||
}
|
||||
|
||||
//zero fill the rest of the segment.
|
||||
uint32_t bytesCopied = ((length+3) & ~3);
|
||||
uint32_t left = segment_size - bytesCopied;
|
||||
if(left) {
|
||||
uint32_t *dest = (uint32_t *)(dst + bytesCopied);
|
||||
for(ii=0; ii<(left/4); ii++)
|
||||
*(dest+ii) = 0x00000000;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate R0 in software.
|
||||
rzero has memory allocated of size modulus_length and is zero filled.
|
||||
*/
|
||||
bool rsa_cal_R0(uint32_t * const mods, uint32_t modulus_length, uint32_t *rzero)
|
||||
{
|
||||
debug("called");
|
||||
|
||||
uint32_t precision = get_precision(modulus_length*DATA_BYTE_TO_BIT);
|
||||
uint32_t chunk_size = get_chunkSize(modulus_length*DATA_BYTE_TO_BIT, precision);
|
||||
|
||||
//precision is 1,2,3,4 instead of 0,1,2,3
|
||||
precision += 1;
|
||||
|
||||
/* Compute 2^b */
|
||||
uint32_t power = (chunk_size / 16) + 1;
|
||||
if (precision == 3)
|
||||
power = power * 3;
|
||||
power = power + (precision * (chunk_size + 16));
|
||||
|
||||
//compute the most significant bit set in the modulus.
|
||||
int32_t b = highestSetBit((uint32_t*)mods, modulus_length);
|
||||
if(b == -1)
|
||||
return false;
|
||||
|
||||
//store 2^b in rzero.
|
||||
bzero(rzero, modulus_length);
|
||||
rzero[(b/32)] = 1 << (b % 32);
|
||||
|
||||
/* Calculate (2^(power-b) * 2^b) mod M */
|
||||
uint32_t itr;
|
||||
for(itr=0; itr<(power-b); itr++) {
|
||||
bool carry = shift_left(rzero, modulus_length); //Shift left.
|
||||
if (carry || is_greater(rzero, mods, modulus_length))
|
||||
sub(rzero, (uint32_t*)mods, modulus_length);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Compute the value of R^2 using the hardware.
|
||||
The value of rzero (R0) is calculated in softare and passed into the function
|
||||
The hardware should be reset before calling this function.
|
||||
The value of R^2 is returned thru' rsquare (memory for this is allocated before calling this function and of modulus_length size)
|
||||
*/
|
||||
static bool rsa_cal_R2modM(volatile struct pke_regs *registers, volatile uint8_t *memory, uint32_t seg_size, uint32_t * const mods, uint32_t mods_length, uint32_t *rsquare, uint32_t *r2_segid)
|
||||
{
|
||||
debug("called");
|
||||
|
||||
if(!rsquare) //Need rzero (which should be in rsquare) to proceed
|
||||
return false;
|
||||
|
||||
//Set the key length;
|
||||
registers->pke_key_len = config_pke_key_len(mods_length*DATA_BYTE_TO_BIT);
|
||||
//Set segment size;
|
||||
registers->pke_seg_size = PkeSetMode(seg_size);
|
||||
registers->pke_seg_sign = 0;
|
||||
registers->pke_seg_id = 0;
|
||||
|
||||
/* Use hardware to calculate R1 thru' Rn and finally R^2 */
|
||||
//Load modulus always into seg0.
|
||||
copy_into_segment(memory, mod_segid, seg_size, (uint8_t*)mods, mods_length);
|
||||
|
||||
//based on seg_size compute the seg_ids to store the (2^(power-b) * 2^b) mod M
|
||||
// and the final value of R^2
|
||||
uint32_t rzero_segid, rsq_segid;
|
||||
switch (seg_size) {
|
||||
case PKE_SEG_SIZE_256:
|
||||
rzero_segid = PKE_SEG_ID_05;
|
||||
rsq_segid = PKE_SEG_ID_06;
|
||||
break;
|
||||
case PKE_SEG_SIZE_128:
|
||||
rzero_segid = PKE_SEG_ID_12;
|
||||
rsq_segid = PKE_SEG_ID_14;
|
||||
break;
|
||||
case PKE_SEG_SIZE_64:
|
||||
rzero_segid = PKE_SEG_ID_28;
|
||||
rsq_segid = PKE_SEG_ID_29;
|
||||
break;
|
||||
default:
|
||||
//Should not happen.
|
||||
return false;
|
||||
}
|
||||
//Load the rzero into the hardware.
|
||||
copy_into_segment(memory, rzero_segid, seg_size, (uint8_t*)rsquare, mods_length);
|
||||
|
||||
uint32_t precision = (registers->pke_key_len&PKE_REGMASK_KEY_LEN_PREC_ID) + 1;
|
||||
//Compute the number of hardware iterations based on precision.
|
||||
uint32_t square_count;
|
||||
if (precision == 1 || precision == 3)
|
||||
square_count = 4;
|
||||
else if (precision == 2)
|
||||
square_count = 5;
|
||||
else /* precision == 4 */
|
||||
square_count = 6;
|
||||
|
||||
//Set pre load modulus on when using the hardware for the first time.
|
||||
uint32_t start_mask = PKE_REGMASK_START_PLDM_ON | PKE_REGMASK_START_EXEC_ON;
|
||||
uint32_t itr = 1;
|
||||
uint32_t temp_segid = rsq_segid;
|
||||
while (itr <= square_count) {
|
||||
//setup seg_id pointers on the hardware
|
||||
registers->pke_seg_id = RSAPkeSetInOut(temp_segid, rzero_segid, rzero_segid);
|
||||
//kick the hardware.
|
||||
if(!RSAPkeRun(registers, start_mask))
|
||||
return false;
|
||||
itr++;
|
||||
if(itr > square_count)
|
||||
break;
|
||||
//swap the segids and do the square again.
|
||||
temp_segid += rzero_segid;
|
||||
rzero_segid = temp_segid - rzero_segid;
|
||||
temp_segid -= rzero_segid;
|
||||
start_mask = PKE_REGMASK_START_EXEC_ON; //dont have to laod M again.
|
||||
}
|
||||
|
||||
// Check the sign value of temp_segid and add modulus if negative.
|
||||
uint32_t uRead, uMask;
|
||||
uMask = (1 << temp_segid);
|
||||
uRead = registers->pke_seg_sign & uMask;
|
||||
//If negative then add modulus.
|
||||
if(uRead) {
|
||||
add( (uint32_t*)(memory+(temp_segid*seg_size)), (uint32_t*)mods, mods_length);
|
||||
}
|
||||
|
||||
*r2_segid = temp_segid;
|
||||
|
||||
//Clean up the temp space used.
|
||||
bzero((uint8_t*) memory+rzero_segid*seg_size, mods_length);
|
||||
|
||||
/* Reset the signbits */
|
||||
registers->pke_seg_sign = 0;
|
||||
memcpy(rsquare, (uint8_t *) memory+rsq_segid*seg_size, mods_length);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Calculate exponential.
|
||||
The options parameter passed in indicates if R^2 is passed in or needs to be computed.
|
||||
Options = 00 => Compute R^2 and don't care about caching. *rsquare is ignored.
|
||||
Options = 01 => Compute R^2 and return it for caching. *rsquare has mem allocated and is of size modulus_length
|
||||
Options = 10 => Use passed in R^2 value.
|
||||
|
||||
Reset the hardware before calling this function.
|
||||
*/
|
||||
bool rsa_cal_exp(void *dst, uint32_t *len, uint32_t options,
|
||||
uint8_t *rsquare, uint32_t *rsquare_length,
|
||||
uint8_t * const base, uint32_t base_length,
|
||||
uint8_t * const expn, uint32_t expn_length,
|
||||
uint8_t * const modulus, uint32_t modulus_length,
|
||||
volatile struct pke_regs *registers, volatile uint8_t *memory)
|
||||
{
|
||||
debug("called");
|
||||
|
||||
/* Perform validation checks */
|
||||
if(modulus_length % 4)
|
||||
return false;
|
||||
|
||||
uint32_t segment_size, num_segments;
|
||||
|
||||
if (modulus_length <= (PKE_SEG_SIZE_64)) {
|
||||
segment_size = PKE_SEG_SIZE_64;
|
||||
} else if (modulus_length <= (PKE_SEG_SIZE_128)) {
|
||||
segment_size = PKE_SEG_SIZE_128;
|
||||
} else if (modulus_length <= (PKE_SEG_SIZE_256)) {
|
||||
segment_size = PKE_SEG_SIZE_256;
|
||||
} else
|
||||
return false; /* key too long */
|
||||
|
||||
num_segments = PkeGetSegmentCount(segment_size);
|
||||
|
||||
if ( !num_segments ||
|
||||
base_length > segment_size ||
|
||||
expn_length > segment_size ||
|
||||
modulus_length > segment_size)
|
||||
return false;
|
||||
|
||||
/* Sane input, so proceed */
|
||||
|
||||
//rsquare segid must always be the last seg ID.
|
||||
uint32_t rsq_segid = num_segments - 1;
|
||||
|
||||
if( (options&kIOPKEAcceleratorComputeRsquareMask) == 0 ) { //Compute rsquare.
|
||||
if(!(options&kIOPKEAcceleratorPreProcessingDone)) { //R0 was not cacluated. should only happen in iBoot.
|
||||
if(!rsquare){
|
||||
//should not happen. The expectation is that memory for rsquare should be allocated.
|
||||
return false;
|
||||
}
|
||||
rsa_cal_R0((uint32_t*)modulus, modulus_length, (uint32_t*)rsquare);
|
||||
}
|
||||
//Compute R^2
|
||||
if(!rsa_cal_R2modM(registers, memory, segment_size, (uint32_t*)modulus, modulus_length, (uint32_t*)rsquare, &rsq_segid))
|
||||
return false;
|
||||
*rsquare_length = modulus_length;
|
||||
}
|
||||
else { //This would have been done while calculating R^2.
|
||||
//Set the key length;
|
||||
registers->pke_key_len = config_pke_key_len(modulus_length*DATA_BYTE_TO_BIT);
|
||||
//Set segment size;
|
||||
registers->pke_seg_size = PkeSetMode(segment_size);
|
||||
/* Reset the signbits */
|
||||
registers->pke_seg_sign = 0;
|
||||
registers->pke_seg_id = 0;
|
||||
|
||||
//Load modulus into seg0;
|
||||
copy_into_segment(memory, mod_segid, segment_size, modulus, modulus_length);
|
||||
//copy the rsquare into the hardware segment.
|
||||
memcpy((uint8_t*)memory+(rsq_segid*segment_size), rsquare, modulus_length);
|
||||
}
|
||||
|
||||
/* Compute (base * r^2 mod M) using hardware */
|
||||
//Copy base into tmp_segid.
|
||||
copy_into_segment(memory, tmp_segid, segment_size, base, base_length);
|
||||
//Setup the segid pointers.
|
||||
registers->pke_seg_id = RSAPkeSetInOut(iter_segid, tmp_segid, rsq_segid);
|
||||
|
||||
//Kick the hardware with pre load modulus bit set.
|
||||
if(!RSAPkeRun(registers, (PKE_REGMASK_START_PLDM_ON | PKE_REGMASK_START_EXEC_ON)))
|
||||
return false;
|
||||
|
||||
/* compute (1*R^2modM) using hardware. */
|
||||
registers->pke_seg_size |= PKE_REGVAL_SEG_SIZE_FUNC_ID_A1; // A*1
|
||||
//When PKE_REGVAL_SEG_SIZE_FUNC_ID_A1 is set, the hardware ignores the segid_B pointer
|
||||
registers->pke_seg_id = RSAPkeSetInOut(acum_segid, rsq_segid, rsq_segid);
|
||||
if(!RSAPkeRun(registers, PKE_REGMASK_START_EXEC_ON))
|
||||
return false;
|
||||
|
||||
// Clear the PKE_REGVAL_SEG_SIZE_FUNC_ID_A1 bit.
|
||||
registers->pke_seg_size &= ~PKE_REGVAL_SEG_SIZE_FUNC_ID_A1;
|
||||
|
||||
/* Run the PKE */
|
||||
uint32_t *exp_word = (uint32_t*)expn;
|
||||
/* word aligned byte length */
|
||||
uint32_t uExpLen = ((expn_length + (DATA_WORD_TO_BYTE - 1)) & (~0x3));
|
||||
|
||||
uint32_t last_word = exp_word[(uExpLen/DATA_WORD_TO_BYTE) - 1];
|
||||
uint32_t uIndex = (DATA_WORD_TO_BYTE*DATA_BYTE_TO_BIT) - (highestSetBit(&last_word, DATA_WORD_TO_BYTE) + 1);
|
||||
for (; uIndex < (uExpLen * DATA_BYTE_TO_BIT); uIndex++) {
|
||||
unsigned int word;
|
||||
unsigned int bit;
|
||||
|
||||
uint32_t offset = (uExpLen / DATA_WORD_TO_BYTE) - (uIndex / (DATA_WORD_TO_BYTE * DATA_BYTE_TO_BIT)) - 1;
|
||||
word = exp_word[offset];
|
||||
|
||||
registers->pke_seg_id = RSAPkeSetInOut(tmp_segid, acum_segid, acum_segid);
|
||||
if(!RSAPkeRun(registers, PKE_REGMASK_START_EXEC_ON))
|
||||
return false;
|
||||
|
||||
bit = word & (0x80000000 >> (uIndex % (DATA_WORD_TO_BYTE * DATA_BYTE_TO_BIT)));
|
||||
|
||||
if (bit) {
|
||||
//debug("bit %d set", uIndex);
|
||||
registers->pke_seg_id = RSAPkeSetInOut(acum_segid, tmp_segid, iter_segid);
|
||||
if(!RSAPkeRun(registers, PKE_REGMASK_START_EXEC_ON))
|
||||
return false;
|
||||
} else {
|
||||
memcpy( (uint8_t *) memory + acum_segid * segment_size,
|
||||
(uint8_t *) memory + tmp_segid * segment_size,
|
||||
segment_size);
|
||||
|
||||
if (registers->pke_seg_sign & (0x01 << tmp_segid))
|
||||
registers->pke_seg_sign |= (0x01 << acum_segid);
|
||||
else
|
||||
registers->pke_seg_sign &= ~(0x01 << acum_segid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Factor out R^-1 from the result */
|
||||
registers->pke_seg_size |= PKE_REGVAL_SEG_SIZE_FUNC_ID_A1; // A*1
|
||||
registers->pke_seg_id = RSAPkeSetInOut(tmp_segid, acum_segid, acum_segid);
|
||||
if (!RSAPkeRun(registers, PKE_REGMASK_START_EXEC_ON))
|
||||
return false;
|
||||
registers->pke_seg_size &= ~PKE_REGVAL_SEG_SIZE_FUNC_ID_A1; // A*B
|
||||
|
||||
// Check the sign value of tmp_segid and add modulus if negative.
|
||||
uint32_t uRead, uMask;
|
||||
uMask = (1 << tmp_segid);
|
||||
uRead = registers->pke_seg_sign & uMask;
|
||||
//If negative then add modulus.
|
||||
if(uRead) {
|
||||
registers->pke_seg_sign &= ~uMask; //clear the sign.
|
||||
add( (uint32_t*)(memory+(tmp_segid*segment_size)), (uint32_t*)modulus, modulus_length);
|
||||
}
|
||||
|
||||
/* Copy data out */
|
||||
memcpy(dst, (uint8_t*)memory+(tmp_segid*segment_size), modulus_length);
|
||||
*len = modulus_length;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if IN_KERNEL
|
||||
|
||||
bool internalTest(volatile struct pke_regs *registers, volatile uint8_t *memory, uint32_t mod_size, uint64_t *time_micro)
|
||||
{
|
||||
uint8_t buff[mod_size];
|
||||
uint32_t segment_size;
|
||||
|
||||
if (mod_size <= (PKE_SEG_SIZE_64)) {
|
||||
segment_size = PKE_SEG_SIZE_64;
|
||||
} else if (mod_size <= (PKE_SEG_SIZE_128)) {
|
||||
segment_size = PKE_SEG_SIZE_128;
|
||||
} else if (mod_size <= (PKE_SEG_SIZE_256)) {
|
||||
segment_size = PKE_SEG_SIZE_256;
|
||||
} else
|
||||
return false; /* key too long */
|
||||
|
||||
uint32_t rsq_segid;
|
||||
switch (segment_size) {
|
||||
case PKE_SEG_SIZE_256:
|
||||
rsq_segid = PKE_SEG_ID_06;
|
||||
break;
|
||||
case PKE_SEG_SIZE_128:
|
||||
rsq_segid = PKE_SEG_ID_14;
|
||||
break;
|
||||
case PKE_SEG_SIZE_64:
|
||||
rsq_segid = PKE_SEG_ID_29;
|
||||
break;
|
||||
default:
|
||||
//Should not happen.
|
||||
return false;
|
||||
}
|
||||
|
||||
registers->pke_key_len = config_pke_key_len(mod_size*DATA_BYTE_TO_BIT);
|
||||
//Set segment size;
|
||||
registers->pke_seg_size = PkeSetMode(segment_size);
|
||||
/* Reset the signbits */
|
||||
registers->pke_seg_sign = 0;
|
||||
registers->pke_seg_id = 0;
|
||||
|
||||
debug("key: %x, reg_key: %x, modsize:%u, reg_segsize: %u", config_pke_key_len(mod_size*DATA_BYTE_TO_BIT), registers->pke_key_len, mod_size, registers->pke_seg_size);
|
||||
|
||||
//Load modulus into seg0;
|
||||
memset(buff, 0xF0, mod_size);
|
||||
copy_into_segment(memory, mod_segid, segment_size, buff, mod_size);
|
||||
//Set R^2
|
||||
memset(buff, 0xE5, mod_size);
|
||||
copy_into_segment(memory, rsq_segid, segment_size, buff, mod_size);
|
||||
//Set A
|
||||
memset(buff, 0xD2, mod_size);
|
||||
copy_into_segment(memory, iter_segid, segment_size, buff, mod_size);
|
||||
|
||||
|
||||
//Setup the segid pointers.
|
||||
registers->pke_seg_id = RSAPkeSetInOut(iter_segid, tmp_segid, tmp_segid);
|
||||
|
||||
uint64_t tasm0, tasm1, tasm2, asm_ns;
|
||||
tasm0 = mach_absolute_time();
|
||||
tasm1 = mach_absolute_time();
|
||||
|
||||
//Kick the hardware with pre load modulus bit set.
|
||||
if(!RSAPkeRun(registers, (PKE_REGMASK_START_PLDM_ON | PKE_REGMASK_START_EXEC_ON)))
|
||||
return false;
|
||||
|
||||
tasm2 = mach_absolute_time();
|
||||
absolutetime_to_nanoseconds( (tasm2 + tasm0 - tasm1 - tasm1), &asm_ns);
|
||||
//debug("Single multiply time: %lluns\n", asm_ns);
|
||||
|
||||
*time_micro = (asm_ns/1000) - 5;
|
||||
|
||||
//clear the hardware.
|
||||
registers->pke_key_len = 0;
|
||||
registers->pke_seg_size = 0;
|
||||
registers->pke_seg_sign = 0;
|
||||
registers->pke_seg_id = 0;
|
||||
|
||||
bzero((uint8_t*)memory+(tmp_segid*segment_size), mod_size);
|
||||
bzero((uint8_t*)memory+(mod_segid*segment_size), mod_size);
|
||||
bzero((uint8_t*)memory+(iter_segid*segment_size), mod_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#ifndef _IOKIT_APPLES5L8900XPKE_HARDWARE_H
|
||||
#define _IOKIT_APPLES5L8900XPKE_HARDWARE_H
|
||||
|
||||
#define IN_KERNEL 0
|
||||
|
||||
#if IN_KERNEL
|
||||
#include <IOKit/IOLib.h>
|
||||
#endif
|
||||
|
||||
struct pke_regs {
|
||||
uint32_t pke_key_len; // 0x000
|
||||
#define S5L8900XPKE_key_len(_precision, _chunk_size) (((_precision) & 0x03) | ((((_chunk_size) / 32) & 0x0f) << 3))
|
||||
uint32_t pad004; // 0x004
|
||||
uint32_t pke_start; // 0x008
|
||||
#define S5L8900XPKE_exec_on (1<<0)
|
||||
#define S5L8900XPKE_pldm_on (1<<3)
|
||||
uint32_t pke_seg_id; // 0x00c
|
||||
#define S5L8900XPKE_seg_ids(_a, _b, _m, _s) (((_a) << 24 ) | ((_b) << 16) | ((_m) << 8) | (_s))
|
||||
uint32_t pke_seg_sign; // 0x010
|
||||
uint32_t pke_seg_size; // 0x014
|
||||
#define S5L8900XPKE_func_id (1<<0)
|
||||
#define S5L8900XPKE_seg_256 (0x00 << 6)
|
||||
#define S5L8900XPKE_seg_128 (0x01 << 6)
|
||||
#define S5L8900XPKE_seg_64 (0x02 << 6)
|
||||
uint32_t pke_intmode; // 0x018
|
||||
#define S5L8900XPKE_interrupt (1<<0)
|
||||
uint32_t pke_int; // 0x01c
|
||||
#define S5L8900XPKE_end_int (1<<0)
|
||||
uint32_t pke_int_mask; // 0x020
|
||||
#define S5L8900XPKE_end_mask (1<<0)
|
||||
uint32_t pke_sw_reset;
|
||||
#define S5L8900XPKE_reset (1<<0)
|
||||
};
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
/* D E F I N E S */
|
||||
/* ========================================================================= */
|
||||
|
||||
#define kIOPKEAcceleratorComputeRsquareMask 0x10
|
||||
#define kIOPKEAcceleratorCacheRsquare 0x01
|
||||
#define kIOPKEAcceleratorPreProcessingDone 0x100
|
||||
#define kIOPKEMaxBits 2048
|
||||
#define kIOPKEUserDataEndianessMask (1<<7)
|
||||
|
||||
/** \define
|
||||
* definition of data format size
|
||||
*/
|
||||
#define DATA_WORD_TO_BYTE 4 /*4BYTE=1WORD*/
|
||||
#define DATA_BYTE_TO_BIT 8 /*1BYTE=8BIT*/
|
||||
|
||||
#define DATA_SHIFT_FOR_256 8 /*2^8=256*/
|
||||
#define DATA_SHIFT_FOR_128 7 /*2^7=128*/
|
||||
#define DATA_SHIFT_FOR_64 6 /*2^6=64*/
|
||||
|
||||
#define PKE_REGSHIFT_KEY_LEN_CHNK_SZ 3
|
||||
|
||||
/** \define
|
||||
* definition of PKE precision size
|
||||
*/
|
||||
#define PKE_SIZE_PREC_0 0 /*single*/
|
||||
#define PKE_SIZE_PREC_1 1
|
||||
#define PKE_SIZE_PREC_2 2
|
||||
#define PKE_SIZE_PREC_3 3
|
||||
|
||||
|
||||
/** \define
|
||||
* definition of PKE key bit length
|
||||
*/
|
||||
#define PKE_LEN_BIT_128 128 /* min size of bit length*/
|
||||
#define PKE_LEN_BIT_512 512
|
||||
#define PKE_LEN_BIT_672 672
|
||||
#define PKE_LEN_BIT_864 864
|
||||
#define PKE_LEN_BIT_1024 1024
|
||||
#define PKE_LEN_BIT_1280 1280
|
||||
#define PKE_LEN_BIT_1408 1408
|
||||
#define PKE_LEN_BIT_1536 1536
|
||||
#define PKE_LEN_BIT_2048 2048 /*max size of bit length*/
|
||||
|
||||
/** \define
|
||||
* definition of PKE Segment Size
|
||||
*/
|
||||
#define PKE_SEG_SIZE_256 (1<<DATA_SHIFT_FOR_256) /*256 byte*/
|
||||
#define PKE_SEG_SIZE_128 (1<<DATA_SHIFT_FOR_128) /*128 byte*/
|
||||
#define PKE_SEG_SIZE_64 (1<<DATA_SHIFT_FOR_64) /*64 byte*/
|
||||
|
||||
/** \define
|
||||
* definition of PKE Segment Max Number (depend on segment size)
|
||||
*/
|
||||
#define PKE_SEG_NUM_CASE256 7
|
||||
#define PKE_SEG_NUM_CASE128 15
|
||||
#define PKE_SEG_NUM_CASE64 30
|
||||
|
||||
/** \define
|
||||
* definition of PKE Function mode
|
||||
*/
|
||||
#define PKE_FUNC_MODE_AB 0
|
||||
#define PKE_FUNC_MODE_A1 1
|
||||
|
||||
|
||||
/** \define
|
||||
* definition of PKE Register field data
|
||||
*/
|
||||
/* key len bits */
|
||||
#define PKE_REGSHIFT_KEY_LEN_CHNK_SZ 3
|
||||
#define PKE_REGSHIFT_KEY_LEN_PREC_ID 0
|
||||
|
||||
#define PKE_REGMASK_KEY_LEN_CHNK_SZ (15 << PKE_REGSHIFT_KEY_LEN_CHNK_SZ )
|
||||
#define PKE_REGMASK_KEY_LEN_PREC_ID (3 << PKE_REGSHIFT_KEY_LEN_PREC_ID )
|
||||
|
||||
/* start bits */
|
||||
#define PKE_REGSHIFT_START_PLDM_ON 3
|
||||
#define PKE_REGSHIFT_START_EXEC_ON 0
|
||||
|
||||
#define PKE_REGMASK_START_PLDM_ON (1 << PKE_REGSHIFT_START_PLDM_ON )
|
||||
#define PKE_REGMASK_START_EXEC_ON (1 << PKE_REGSHIFT_START_EXEC_ON )
|
||||
|
||||
/* seg id bits */
|
||||
#define PKE_REGSHIFT_SEG_ID_A_SEG_ID 24
|
||||
#define PKE_REGSHIFT_SEG_ID_B_SEG_ID 16
|
||||
#define PKE_REGSHIFT_SEG_ID_M_SEG_ID 8
|
||||
#define PKE_REGSHIFT_SEG_ID_S_SEG_ID 0
|
||||
|
||||
/* seg size bits */
|
||||
#define PKE_REGSHIFT_SEG_SIZE_SEGSIZE 6
|
||||
#define PKE_REGSHIFT_SEG_SIZE_FUNC_ID 1
|
||||
#define PKE_REGSHIFT_SEG_SIZE_MUSTBEONE 0
|
||||
|
||||
#define PKE_REGMASK_SEG_SIZE_SEGSIZE (3 << PKE_REGSHIFT_SEG_SIZE_SEGSIZE)
|
||||
#define PKE_REGMASK_SEG_SIZE_FUNC_ID (1 << PKE_REGSHIFT_SEG_SIZE_FUNC_ID)
|
||||
#define PKE_REGMASK_SEG_SIZE_MUSTBEONE (1 << PKE_REGSHIFT_SEG_SIZE_MUSTBEONE )
|
||||
|
||||
#define PKE_REGVAL_SEG_SIZE_SEGSIZE_256 (0 << PKE_REGSHIFT_SEG_SIZE_SEGSIZE)
|
||||
#define PKE_REGVAL_SEG_SIZE_SEGSIZE_128 (1 << PKE_REGSHIFT_SEG_SIZE_SEGSIZE)
|
||||
#define PKE_REGVAL_SEG_SIZE_SEGSIZE_64 (2 << PKE_REGSHIFT_SEG_SIZE_SEGSIZE)
|
||||
#define PKE_REGVAL_SEG_SIZE_FUNC_ID_AB (0 << PKE_REGSHIFT_SEG_SIZE_FUNC_ID)
|
||||
#define PKE_REGVAL_SEG_SIZE_FUNC_ID_A1 (1 << PKE_REGSHIFT_SEG_SIZE_FUNC_ID)
|
||||
|
||||
/** \enum PKE_SegID_et
|
||||
* enumeation of segment ID
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PKE_SEG_ID_00 = 0,
|
||||
PKE_SEG_ID_01,
|
||||
PKE_SEG_ID_02,
|
||||
PKE_SEG_ID_03,
|
||||
PKE_SEG_ID_04,
|
||||
PKE_SEG_ID_05,
|
||||
PKE_SEG_ID_06, /*last segment ID in the 256byte segment block*/
|
||||
PKE_SEG_ID_07,
|
||||
PKE_SEG_ID_08,
|
||||
PKE_SEG_ID_09,
|
||||
PKE_SEG_ID_10,
|
||||
PKE_SEG_ID_11,
|
||||
PKE_SEG_ID_12,
|
||||
PKE_SEG_ID_13,
|
||||
PKE_SEG_ID_14, /*last segment ID in the 128byte segment block*/
|
||||
PKE_SEG_ID_15,
|
||||
PKE_SEG_ID_16,
|
||||
PKE_SEG_ID_17,
|
||||
PKE_SEG_ID_18,
|
||||
PKE_SEG_ID_19,
|
||||
PKE_SEG_ID_20,
|
||||
PKE_SEG_ID_21,
|
||||
PKE_SEG_ID_22,
|
||||
PKE_SEG_ID_23,
|
||||
PKE_SEG_ID_24,
|
||||
PKE_SEG_ID_25,
|
||||
PKE_SEG_ID_26,
|
||||
PKE_SEG_ID_27,
|
||||
PKE_SEG_ID_28,
|
||||
PKE_SEG_ID_29 /*last segment ID in the 64byte segment block*/
|
||||
}PKE_SegID_et;
|
||||
|
||||
enum {
|
||||
mod_segid = PKE_SEG_ID_00, /* ! moduler seg id MUST be '0' */
|
||||
tmp_segid = PKE_SEG_ID_01,
|
||||
acum_segid = PKE_SEG_ID_02,
|
||||
iter_segid = PKE_SEG_ID_03
|
||||
};
|
||||
|
||||
|
||||
#endif /* _IOKIT_APPLES5L8900XPKE_HARDWARE_H */
|
||||
@@ -0,0 +1,930 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
# $Copyright:
|
||||
# ----------------------------------------------------------------
|
||||
# This confidential and proprietary software may be used only as
|
||||
# authorized by a licensing agreement from Samsung Limited
|
||||
# (C) COPYRIGHT 1999,2001,2002 Samsung Limited
|
||||
# ALL RIGHTS RESERVED
|
||||
# The entire notice above must be reproduced on all authorized
|
||||
# copies and copies may only be made to the extent permitted
|
||||
# by a licensing agreement from Samsung Limited.
|
||||
# ----------------------------------------------------------------
|
||||
# File: DevPke_R2modM.s
|
||||
# Tornado2 File: tor_cal_R2modM.s
|
||||
# Revision: 1.0
|
||||
# 2004.05.18. V1.0
|
||||
# - Calculate R^2 modM value
|
||||
# 2005.01.12 V1.1
|
||||
# - ARM/Thumb interworking enabled in ARMv4(SC100)
|
||||
#
|
||||
# ----------------------------------------------------------------
|
||||
# Assembler Tornado device driver
|
||||
#
|
||||
# adapted for as(1); comments are bumped to the next line.
|
||||
|
||||
#include <platform/soc/hwregbase.h>
|
||||
|
||||
.text
|
||||
|
||||
.globl _L_TCR_BASE
|
||||
.globl _L_SEG_BASE
|
||||
|
||||
# TORNADO2 control area 0x3D000000
|
||||
# Segment base address 0x3D000800
|
||||
_L_TCR_BASE: .long PKE_BASE_ADDR
|
||||
_L_SEG_BASE: .long PKE_BASE_ADDR+0x0800
|
||||
|
||||
# segment ids used for calculation depending on segment size
|
||||
.set SEG_4, 04
|
||||
.set SEG_5, 05
|
||||
.set SEG_6, 06
|
||||
.set SEG_12, 12
|
||||
.set SEG_13, 13
|
||||
.set SEG_14, 14
|
||||
.set SEG_27, 27
|
||||
.set SEG_28, 28
|
||||
.set SEG_29, 29
|
||||
|
||||
L_00000040: .long 0x00000040
|
||||
L_00004000: .long 0x00004000
|
||||
L_20000000: .long 0x20000000
|
||||
|
||||
# segment operand operation config
|
||||
L_04040006: .long 0x04040006
|
||||
L_05050004: .long 0x05050004
|
||||
L_05050006: .long 0x05050006
|
||||
L_06060005: .long 0x06060005
|
||||
L_0C0C000E: .long 0x0C0C000E
|
||||
L_0D0D000C: .long 0x0D0D000C
|
||||
L_0D0D000E: .long 0x0D0D000E
|
||||
L_0E0E000D: .long 0x0E0E000D
|
||||
L_1B1B001D: .long 0x1B1B001D
|
||||
L_1C1C001D: .long 0x1C1C001D
|
||||
L_1C1C001b: .long 0x1C1C001b
|
||||
L_1D1D001C: .long 0x1D1D001C
|
||||
|
||||
# bit test mask
|
||||
L_80000000: .long 0x80000000
|
||||
|
||||
|
||||
# BIT_LEN is programmer defined real key size.
|
||||
|
||||
###############################################
|
||||
#### NAME : PkeCalR2modM ####
|
||||
#### Tornado NAME : tor_cal_R2modM ####
|
||||
###############################################
|
||||
.globl _PkeCalR2modM
|
||||
#================================================
|
||||
# Name : PkeCalR2modM(int BIT_LEN)
|
||||
# Tornado Name : tor_cal_R2modM(int BIT_LEN)
|
||||
# Function : 1. Clear the last 3 segment area
|
||||
# 2. Calculate R*2^((C/16)+1) modM value
|
||||
# 3. Calculate R*RmodM by using TORNADO
|
||||
# and save this value in Seg6 or Seg14 or Seg29.
|
||||
# 4. Clear temp segment area.
|
||||
# Requisite : Modulus value must be copied from memory to Seg0
|
||||
# before using this function.
|
||||
# Argument
|
||||
# int BIT_LEN : real Key size
|
||||
#================================================
|
||||
_PkeCalR2modM:
|
||||
stmfd sp!, {r1-r12,lr}
|
||||
# reserved register values
|
||||
# r0 = BIT_LEN
|
||||
# r12= Loop_count(hw_size/32)
|
||||
#====================
|
||||
# Clear CryptoRAM area (Seg4 ~ Seg6) when SEG_SIZE=0
|
||||
#====================
|
||||
# read SEG_SIZE
|
||||
ldr r1, _L_TCR_BASE
|
||||
ldr r2, [r1,$0x14]
|
||||
and r2, r2, $0xC0
|
||||
mov r2, r2, LSR #6
|
||||
cmp r2, #1
|
||||
bhi clr_64
|
||||
# 1 segment = 64byte
|
||||
blt clr_256
|
||||
# 1 segment = 256byte
|
||||
|
||||
## else 1 segment =128byte
|
||||
ldr r1, =SEG_12
|
||||
# Start position
|
||||
ldr r2,_L_SEG_BASE
|
||||
orr r1,r2,r1, lsl #7
|
||||
ldr r2, =96
|
||||
b start_clr
|
||||
clr_64:
|
||||
ldr r1, =SEG_27
|
||||
# Start position
|
||||
ldr r2,_L_SEG_BASE
|
||||
orr r1,r2,r1, lsl #6
|
||||
ldr r2, =48
|
||||
b start_clr
|
||||
clr_256:
|
||||
ldr r1, =SEG_4
|
||||
# Start position
|
||||
ldr r2,_L_SEG_BASE
|
||||
orr r1,r2,r1, lsl #8
|
||||
ldr r2, =192
|
||||
start_clr:
|
||||
mov r3,#0
|
||||
mov r4,r3
|
||||
mov r5,r3
|
||||
mov r6,r3
|
||||
mov r7,r3
|
||||
mov r8,r3
|
||||
mov r9,r3
|
||||
mov r10,r3
|
||||
clear_loop_cal:
|
||||
stmia r1!, {r3-r10}
|
||||
subs r2,r2,#8
|
||||
bne clear_loop_cal
|
||||
#====================================================
|
||||
# Calculate Montgomery constant
|
||||
#====================================================
|
||||
# 1. Calculate R0=R*2^((c/16)+1)modM
|
||||
# 2. Calculate R1,R2, .. Rn
|
||||
# R[i]=(R[i-1]^2)*R^(-1)modM
|
||||
# n such that 2^n=p*16 (p=1 ==> n=4 # ... P=4 ==> n=6)
|
||||
# 3. If final output is neg, change it to pos one
|
||||
#=====================================================
|
||||
mov r1,r0
|
||||
# save BIT_LEN in r1
|
||||
#====================
|
||||
# Calculate R0=R*2^((c/16)+1)modM
|
||||
#====================
|
||||
|
||||
# cal power=(p*(c+16)+(c/16)+1)
|
||||
ldr r0, _L_TCR_BASE
|
||||
ldr r0,[r0]
|
||||
and r2,r0,#0x03
|
||||
add r2,r2,#1
|
||||
# p value
|
||||
and r3,r0,#0x78
|
||||
add r3,r3,#0x08
|
||||
mov r3,r3, lsl #2
|
||||
# c value
|
||||
mul r12,r2,r3
|
||||
mov r12,r12,LSR #5
|
||||
# r12= Loop_count(hw_size/32)
|
||||
add r4,r3,#16
|
||||
mul r6,r4,r2
|
||||
# r6=p*(c+16)
|
||||
mov r5,r3, LSR #4
|
||||
add r5,r5,#1
|
||||
# r5=(c/16)+1
|
||||
mov r0, #3
|
||||
mov r3,r5
|
||||
cmp r2, #3
|
||||
muleq r5,r3,r0
|
||||
# precision = 0x10 case
|
||||
add r2,r6,r5
|
||||
# store power in r2
|
||||
|
||||
# calculate b value
|
||||
ldr r0, _L_SEG_BASE
|
||||
add r3,r1,#31
|
||||
mov r3,r3,LSR #5
|
||||
# r3= (BIT_LEN+31)/32
|
||||
mov r3,r3,lsl #2
|
||||
sub r3,r3,#4
|
||||
add r0,r0,r3
|
||||
# r0 = MSW address of Modulus
|
||||
mov r7,r1
|
||||
# r7= BIT_LEN
|
||||
add r7,r7,#0x1F
|
||||
mov r7,r7,LSR #5
|
||||
mov r7,r7,lsl #5
|
||||
# r7=(r7+31)/32*32
|
||||
next_MSW:
|
||||
# Searching MSW
|
||||
cmp r7,#0
|
||||
beq end_tor_calR2
|
||||
## if r2=0 then goto end_...
|
||||
ldr r4,[r0],#-4
|
||||
cmp r4,#0
|
||||
subeq r7,r7,#32
|
||||
beq next_MSW
|
||||
ldr r5,L_80000000
|
||||
next_MSB:
|
||||
ands r6,r4,r5
|
||||
subeq r7,r7,#1
|
||||
mov r5,r5,LSR #1
|
||||
beq next_MSB
|
||||
|
||||
# b = r7
|
||||
sub r3,r2,r7
|
||||
# r3=power - b
|
||||
|
||||
# b is real bit size of Modulus
|
||||
|
||||
# cal a=8-(power-b)%8 (1<= a <=8)
|
||||
mod8_loop:
|
||||
cmp r3,#8
|
||||
blt cal_a
|
||||
sub r3,r3,#8
|
||||
b mod8_loop
|
||||
cal_a:
|
||||
rsb r3,r3,#8
|
||||
# r3=a
|
||||
|
||||
# read SEG_SIZE
|
||||
ldr r4, _L_TCR_BASE
|
||||
ldr r8, [r4,#0x14]
|
||||
and r8, r8, #0xC0
|
||||
mov r8, r8, LSR #6
|
||||
cmp r8, #1
|
||||
bhi cal_64
|
||||
# 1 segment = 64byte
|
||||
blt cal_256
|
||||
# 1 segment = 256byte
|
||||
|
||||
## else 1 segment =128byte
|
||||
ldr r4, =SEG_12
|
||||
# Start position
|
||||
ldr r8,_L_SEG_BASE
|
||||
orr r4,r8,r4, lsl #7
|
||||
b cal_segset_endup
|
||||
cal_64:
|
||||
ldr r4, =SEG_28
|
||||
# Start position
|
||||
ldr r8,_L_SEG_BASE
|
||||
orr r4,r8,r4, lsl #6
|
||||
b cal_segset_endup
|
||||
cal_256:
|
||||
ldr r4, =SEG_5
|
||||
# Start position
|
||||
ldr r8,_L_SEG_BASE
|
||||
orr r4,r8,r4, lsl #8
|
||||
cal_segset_endup:
|
||||
sub r5,r7,r3
|
||||
mov r6,r5, LSR #5
|
||||
add r4,r4,r6, lsl #2
|
||||
# r4=SEG_4+((b-a)/32)*4
|
||||
mod32_loop:
|
||||
cmp r5,#32
|
||||
blt load_power
|
||||
sub r5,r5,#32
|
||||
# r5=(b-a)%32
|
||||
b mod32_loop
|
||||
load_power:
|
||||
mov r6,#0x01
|
||||
mov r6,r6, lsl r5
|
||||
str r6,[r4]
|
||||
# (0x01<<(BIT_LEN-a)%32)
|
||||
div_modM:
|
||||
#loop round value < ((power-b+a)/8)
|
||||
sub r2,r2,r7
|
||||
add r2,r2,r3
|
||||
mov r0,r2,LSR #3
|
||||
# r0=(power-b+a)/8
|
||||
|
||||
# reserved reg : r0, r1=BIT_LEN, r12=hw_size/32
|
||||
|
||||
# available reg :r2-11
|
||||
stmfd sp!, {r0}
|
||||
# available reg :r0,r2-r12 r1=store r12 value while shift_block
|
||||
#====================
|
||||
# Start div_byte
|
||||
#====================
|
||||
start_div_byte:
|
||||
mov r3,#9
|
||||
# 9=8 count value +1
|
||||
stmfd sp!,{r3}
|
||||
# !!tor_dev_byte 8 count value is saved in stack!!
|
||||
mov r1,r12
|
||||
reload_shift:
|
||||
# read SEG_SIZE
|
||||
ldr r0, _L_TCR_BASE
|
||||
ldr r2, [r0,#0x14]
|
||||
and r2, r2, #0xC0
|
||||
mov r2, r2, LSR #6
|
||||
cmp r2, #1
|
||||
bhi reload_64
|
||||
# 1 segment = 64byte
|
||||
blt reload_256
|
||||
# 1 segment = 256byte
|
||||
|
||||
## else 1 segment =128byte
|
||||
ldr r0, =SEG_12
|
||||
# Start position
|
||||
ldr r2,_L_SEG_BASE
|
||||
orr r0,r2,r0, lsl #7
|
||||
b reload_segset_endup
|
||||
reload_64:
|
||||
ldr r0, =SEG_28
|
||||
# Start position
|
||||
ldr r2,_L_SEG_BASE
|
||||
orr r0,r2,r0, lsl #6
|
||||
b reload_segset_endup
|
||||
reload_256:
|
||||
ldr r0, =SEG_5
|
||||
# Start position
|
||||
ldr r2,_L_SEG_BASE
|
||||
orr r0,r2,r0, lsl #8
|
||||
reload_segset_endup:
|
||||
mov r3,#0
|
||||
# clr r3
|
||||
mov r12,r1
|
||||
ldmfd sp!,{r5}
|
||||
subs r5,r5,#1
|
||||
stmfd sp!,{r5}
|
||||
beq end_div_byte
|
||||
cmp r12,#8
|
||||
blt shift_one
|
||||
#====================
|
||||
# Start shift left operation
|
||||
#====================
|
||||
shift_block:
|
||||
|
||||
# r0=address,r3=carry1,r2=carry2
|
||||
|
||||
# r4-r11=working reg,r12=shift loop counter
|
||||
#ldm r0, {r4-r11}
|
||||
ldmia r0, {r4,r5,r6,r7,r8,r9,r10,r11}
|
||||
mov r2,r4, LSR #31
|
||||
# save carry
|
||||
add r4,r3,r4, lsl #1
|
||||
# shift
|
||||
mov r3,r5, LSR #31
|
||||
# save carry
|
||||
add r5,r2,r5, lsl #1
|
||||
# shift
|
||||
mov r2,r6, LSR #31
|
||||
# save carry
|
||||
add r6,r3,r6, lsl #1
|
||||
# shift
|
||||
mov r3,r7, LSR #31
|
||||
# save carry
|
||||
add r7,r2,r7, lsl #1
|
||||
# shift
|
||||
mov r2,r8, LSR #31
|
||||
# save carry
|
||||
add r8,r3,r8, lsl #1
|
||||
# shift
|
||||
mov r3,r9, LSR #31
|
||||
# save carry
|
||||
add r9,r2,r9, lsl #1
|
||||
# shift
|
||||
mov r2,r10, LSR #31
|
||||
# save carry
|
||||
add r10,r3,r10, lsl #1
|
||||
# shift
|
||||
mov r3,r11, LSR #31
|
||||
# save carry
|
||||
add r11,r2,r11, lsl #1
|
||||
# shift
|
||||
stmia r0!,{r4-r11}
|
||||
sub r12,r12,#8
|
||||
cmp r12,#8
|
||||
bge shift_block
|
||||
shift_one:
|
||||
cmp r12,#0
|
||||
beq cmp_carry1
|
||||
ldr r4,[r0]
|
||||
mov r2,r4, LSR #31
|
||||
add r4,r3,r4, lsl #1
|
||||
mov r3,r2
|
||||
str r4,[r0],#4
|
||||
sub r12,r12,#1
|
||||
b shift_one
|
||||
#====================
|
||||
# Start compare operation
|
||||
#====================
|
||||
cmp_carry1:
|
||||
cmp r3,#0
|
||||
bne tor_sub
|
||||
greater_equal:
|
||||
|
||||
# available reg:r2-r12
|
||||
sub r0,r0 ,#4
|
||||
# MSW address of power(0xE04XX)
|
||||
ldr r2, _L_SEG_BASE
|
||||
# Modulus pointer value
|
||||
and r3,r0,#0xFF
|
||||
add r2,r2,r3
|
||||
# MSW address of Modulus(0xE00XX)
|
||||
test_loop:
|
||||
ldr r3,[r0],#-4
|
||||
# r3=power value
|
||||
ldr r4,[r2],#-4
|
||||
# r2=Modulus value
|
||||
cmp r3,r4
|
||||
beq test_loop
|
||||
bhi tor_sub
|
||||
# pow>Mod
|
||||
|
||||
# pow <Mod
|
||||
mov r3,#0
|
||||
# clr carry1 for shift_block
|
||||
mov r12,r1
|
||||
# reload hw_size/32 (word count value)
|
||||
b reload_shift
|
||||
#====================
|
||||
# Do Power - Modulus
|
||||
#====================
|
||||
tor_sub:
|
||||
|
||||
# read SEG_SIZE
|
||||
ldr r0, _L_TCR_BASE
|
||||
ldr r3, [r0,#0x14]
|
||||
and r3, r3, #0xC0
|
||||
mov r3, r3, LSR #6
|
||||
cmp r3, #1
|
||||
bhi sub_64
|
||||
# 1 segment = 64byte
|
||||
blt sub_256
|
||||
# 1 segment = 256byte
|
||||
|
||||
## else 1 segment =128byte
|
||||
ldr r0, =SEG_12
|
||||
# Start position
|
||||
cmp r0, #0
|
||||
# !! Set carry for sub !!
|
||||
ldr r3,_L_SEG_BASE
|
||||
orr r0,r3,r0, lsl #7
|
||||
b sub_segset_endup
|
||||
sub_64:
|
||||
ldr r0, =SEG_28
|
||||
# Start position
|
||||
cmp r0, #0
|
||||
# !! Set carry for sub !!
|
||||
ldr r3,_L_SEG_BASE
|
||||
orr r0,r3,r0, lsl #6
|
||||
b sub_segset_endup
|
||||
sub_256:
|
||||
ldr r0, =SEG_5
|
||||
# Start position
|
||||
cmp r0, #0
|
||||
# !! Set carry for sub !!
|
||||
ldr r3,_L_SEG_BASE
|
||||
orr r0,r3,r0, lsl #8
|
||||
sub_segset_endup:
|
||||
mov r12,r1
|
||||
# reload hw_size/32 (word count value)
|
||||
mov r2,#0
|
||||
# clear r2
|
||||
and r4,r12,#0x07
|
||||
# check multiple of 8
|
||||
teq r4,#0
|
||||
beq multy_sub
|
||||
single_sub:
|
||||
ldr r5,[r0]
|
||||
# load power
|
||||
ldr r6,[r3],#4
|
||||
# load M
|
||||
sbcs r5,r5,r6
|
||||
str r5,[r0],#4
|
||||
sub r12,r12,#1
|
||||
sub r4,r4,#1
|
||||
teq r4,#0
|
||||
bne single_sub
|
||||
teq r12,#0
|
||||
beq sub_end
|
||||
#r4,r5,r6,....r11 available
|
||||
multy_sub:
|
||||
ldmia r0, {r4-r7}
|
||||
# load power
|
||||
ldmia r3!, {r8-r11}
|
||||
# load M
|
||||
sbcs r4, r4, r8
|
||||
sbcs r5, r5, r9
|
||||
sbcs r6, r6, r10
|
||||
sbcs r7, r7, r11
|
||||
stmia r0!, {r4-r7}
|
||||
|
||||
ldmia r0, {r4-r7}
|
||||
# load power
|
||||
ldmia r3!, {r8-r11}
|
||||
# load M
|
||||
sbcs r4, r4, r8
|
||||
sbcs r5, r5, r9
|
||||
sbcs r6, r6, r10
|
||||
sbcs r7, r7, r11
|
||||
stmia r0!, {r4-r7}
|
||||
sub r12, r12, #8
|
||||
# don't change carry
|
||||
teq r12, #0
|
||||
# don't change carry
|
||||
bne multy_sub
|
||||
sub_end:
|
||||
b reload_shift
|
||||
#====================
|
||||
# End div_byte
|
||||
#====================
|
||||
end_div_byte:
|
||||
mov r12,r1
|
||||
ldmfd sp!,{r4,r5}
|
||||
# r4 = 8 counter, r5=(pwr-b+a)/8
|
||||
subs r5,r5,#1
|
||||
stmfd sp!,{r5}
|
||||
bne start_div_byte
|
||||
# restart tor_div_byte
|
||||
ldmfd sp!,{r5}
|
||||
# release SP (stack pointer)
|
||||
#====================
|
||||
# Calculate R1 to Rn
|
||||
#====================
|
||||
ldr r0, _L_TCR_BASE
|
||||
mov r2,#0x01
|
||||
ldr r3,[r0]
|
||||
ldr r5,[r0,#0x14]
|
||||
and r5, r5, #0xC0
|
||||
mov r5, r5, LSR #6
|
||||
# SEG_SIZE value
|
||||
and r4,r3,#0x03
|
||||
# r4=precision
|
||||
cmp r4,#1
|
||||
bhi mon_mul_6
|
||||
beq mon_mul_5
|
||||
mon_mul_4:
|
||||
|
||||
# run 1
|
||||
ldr r3, L_1C1C001D
|
||||
# Seg29=Seg28*Seg28
|
||||
cmp r5,#0
|
||||
ldreq r3, L_05050006
|
||||
# Seg6=Seg5 * Seg5
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0C0C000E
|
||||
# Seg14=Seg12*Seg12
|
||||
mov r4,#0x09
|
||||
# run TORNADO with preload
|
||||
str r3,[r0,#0xC]
|
||||
# write TCR_1
|
||||
str r4,[r0,#8]
|
||||
# write CTR2
|
||||
## !!! S/W Pooling !!!
|
||||
bl sw_polling_loop
|
||||
|
||||
|
||||
# run 2
|
||||
ldr r3, L_1D1D001C
|
||||
# Seg28=Seg29*Seg29
|
||||
cmp r5,#0
|
||||
ldreq r3, L_06060005
|
||||
# Seg5=Seg6 * Seg6
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0E0E000D
|
||||
# Seg13=Seg14*Seg14
|
||||
bl start_tor_cal
|
||||
|
||||
# run 3
|
||||
ldr r3, L_1C1C001b
|
||||
# Seg27=Seg28*Seg28
|
||||
cmp r5,#0
|
||||
ldreq r3, L_05050004
|
||||
# Seg4=Seg5 * Seg5
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0D0D000C
|
||||
# Seg12=Seg13*Seg13
|
||||
bl start_tor_cal
|
||||
|
||||
# run 4
|
||||
ldr r3, L_1B1B001D
|
||||
# Seg29=Seg27*Seg27
|
||||
ldr r6, L_20000000
|
||||
# check SEG_SIGN of Seg29
|
||||
cmp r5,#0
|
||||
ldreq r3, L_04040006
|
||||
# Seg6=Seg4 * Seg4
|
||||
ldreq r6, L_00000040
|
||||
# check SEG_SIGN of Seg6
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0C0C000E
|
||||
# Seg14=Seg12*Seg12
|
||||
ldreq r6, L_00004000
|
||||
# check SEG_SIGN of Seg14
|
||||
bl start_tor_cal
|
||||
|
||||
ldr r5,[r0,#0x10]
|
||||
ands r5,r5,r6
|
||||
# read SOS bit
|
||||
bne add_modulus
|
||||
b clear_end
|
||||
mon_mul_5:
|
||||
|
||||
# run 1
|
||||
ldr r3, L_1C1C001D
|
||||
# Seg29=Seg28*Seg28
|
||||
cmp r5,#0
|
||||
ldreq r3, L_05050006
|
||||
# Seg6=Seg5 * Seg5
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0C0C000E
|
||||
# Seg14=Seg12*Seg12
|
||||
mov r4,#0x09
|
||||
# run TORNADO with preload
|
||||
str r3,[r0,#0xC]
|
||||
# write CTR1
|
||||
str r4,[r0,#8]
|
||||
# write CTR2
|
||||
## !!! S/W Pooling !!!
|
||||
bl sw_polling_loop
|
||||
|
||||
|
||||
# run 2
|
||||
ldr r3, L_1D1D001C
|
||||
# Seg28=Seg29*Seg29
|
||||
cmp r5,#0
|
||||
ldreq r3, L_06060005
|
||||
# Seg5=Seg6 * Seg6
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0E0E000D
|
||||
# Seg13=Seg14*Seg14
|
||||
bl start_tor_cal
|
||||
|
||||
# run 3
|
||||
ldr r3, L_1C1C001D
|
||||
# Seg29=Seg28*Seg28
|
||||
cmp r5,#0
|
||||
ldreq r3, L_05050006
|
||||
# Seg6=Seg5 * Seg5
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0D0D000E
|
||||
# Seg14=Seg13*Seg13
|
||||
bl start_tor_cal
|
||||
|
||||
# run 4
|
||||
ldr r3, L_1D1D001C
|
||||
# Seg28=Seg29*Seg29
|
||||
cmp r5,#0
|
||||
ldreq r3, L_06060005
|
||||
# Seg5=Seg6 * Seg6
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0E0E000D
|
||||
# Seg13=Seg14*Seg14
|
||||
bl start_tor_cal
|
||||
|
||||
# run 5
|
||||
ldr r3, L_1C1C001D
|
||||
# Seg29=Seg28*Seg28
|
||||
ldr r6, L_20000000
|
||||
# check SEG_SIGN of Seg29
|
||||
cmp r5,#0
|
||||
ldreq r3, L_05050006
|
||||
# Seg6=Seg5 * Seg5
|
||||
ldreq r6, L_00000040
|
||||
# check SEG_SIGN of Seg6
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0D0D000E
|
||||
# Seg14=Seg13*Seg13
|
||||
ldreq r6, L_00004000
|
||||
# check SEG_SIGN of Seg14
|
||||
bl start_tor_cal
|
||||
|
||||
ldr r5,[r0,#0x10]
|
||||
ands r5,r5,r6
|
||||
# read SOS bit
|
||||
bne add_modulus
|
||||
b clear_end
|
||||
mon_mul_6:
|
||||
cmp r4,#0x02
|
||||
# In case of precision=3
|
||||
beq mon_mul_4
|
||||
|
||||
# run 1
|
||||
ldr r3, L_1C1C001D
|
||||
# Seg29=Seg28*Seg28
|
||||
cmp r5,#0
|
||||
ldreq r3, L_05050006
|
||||
# Seg6=Seg5 * Seg5
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0C0C000E
|
||||
# Seg14=Seg12*Seg12
|
||||
mov r4,#0x09
|
||||
# run TORNADO with preload
|
||||
str r3,[r0,#0xC]
|
||||
# write CTR1
|
||||
str r4,[r0,#8]
|
||||
# write CTR2
|
||||
## !!! S/W Pooling !!!
|
||||
bl sw_polling_loop
|
||||
|
||||
|
||||
# run 2
|
||||
ldr r3, L_1D1D001C
|
||||
# Seg28=Seg29*Seg29
|
||||
cmp r5,#0
|
||||
ldreq r3, L_06060005
|
||||
# Seg5=Seg6 * Seg6
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0E0E000D
|
||||
# Seg13=Seg14*Seg14
|
||||
bl start_tor_cal
|
||||
|
||||
# run 3
|
||||
ldr r3, L_1C1C001D
|
||||
# Seg29=Seg28*Seg28
|
||||
cmp r5,#0
|
||||
ldreq r3, L_05050006
|
||||
# Seg6=Seg5 * Seg5
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0D0D000E
|
||||
# Seg14=Seg13*Seg13
|
||||
bl start_tor_cal
|
||||
|
||||
# run 4
|
||||
ldr r3, L_1D1D001C
|
||||
# Seg28=Seg29*Seg29
|
||||
cmp r5,#0
|
||||
ldreq r3, L_06060005
|
||||
# Seg5=Seg6 * Seg6
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0E0E000D
|
||||
# Seg13=Seg14*Seg14
|
||||
bl start_tor_cal
|
||||
|
||||
# run 5
|
||||
ldr r3, L_1C1C001b
|
||||
# Seg27=Seg28*Seg28
|
||||
cmp r5,#0
|
||||
ldreq r3, L_05050004
|
||||
# Seg4=Seg5 * Seg5
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0D0D000C
|
||||
# Seg12=Seg13*Seg13
|
||||
bl start_tor_cal
|
||||
|
||||
# run 6
|
||||
ldr r3, L_1B1B001D
|
||||
# Seg29=Seg27*Seg27
|
||||
ldr r6, L_20000000
|
||||
# check SEG_SIGN of Seg29
|
||||
cmp r5,#0
|
||||
ldreq r3, L_04040006
|
||||
# Seg6=Seg4 * Seg4
|
||||
ldreq r6, L_00000040
|
||||
# check SEG_SIGN of Seg6
|
||||
cmp r5,#1
|
||||
ldreq r3, L_0C0C000E
|
||||
# Seg14=Seg12*Seg12
|
||||
ldreq r6, L_00004000
|
||||
# check SEG_SIGN of Seg14
|
||||
bl start_tor_cal
|
||||
|
||||
ldr r5,[r0,#0x10]
|
||||
ands r5,r5,r6
|
||||
# read SOS bit
|
||||
bne add_modulus
|
||||
b clear_end
|
||||
|
||||
start_tor_cal:
|
||||
str r3,[r0,#0xC]
|
||||
# write TCR_3
|
||||
str r2,[r0,#8]
|
||||
# write TCR_2
|
||||
## sw polling for FPGA and CO-Working processor setting
|
||||
sw_polling_loop:
|
||||
ldr r4,[r0,#0x08]
|
||||
ands r4,r4,#0x01
|
||||
bne sw_polling_loop
|
||||
mov pc,lr
|
||||
|
||||
add_modulus:
|
||||
|
||||
# read SEG_SIZE
|
||||
ldr r0, _L_TCR_BASE
|
||||
ldr r1, [r0,#0x14]
|
||||
and r1, r1, #0xC0
|
||||
mov r1, r1, LSR #6
|
||||
cmp r1, #1
|
||||
bhi add_64
|
||||
# 1 segment = 64byte
|
||||
blt add_256
|
||||
# 1 segment = 256byte
|
||||
|
||||
## else 1 segment =128byte
|
||||
ldr r0, =SEG_14
|
||||
# Start position
|
||||
ldr r1,_L_SEG_BASE
|
||||
orr r0,r1,r0, lsl #7
|
||||
b add_segset_endup
|
||||
add_64:
|
||||
ldr r0, =SEG_29
|
||||
# Start position
|
||||
ldr r1,_L_SEG_BASE
|
||||
orr r0,r1,r0, lsl #6
|
||||
b add_segset_endup
|
||||
add_256:
|
||||
ldr r0, =SEG_6
|
||||
# Start position
|
||||
ldr r1,_L_SEG_BASE
|
||||
orr r0,r1,r0, lsl #8
|
||||
add_segset_endup:
|
||||
movs r2,r2, LSR #2
|
||||
# clear Carry
|
||||
and r4,r12,#0x03
|
||||
# check multiple of 4
|
||||
teq r4,#0
|
||||
beq multy_add
|
||||
single_add:
|
||||
ldr r5,[r0]
|
||||
ldr r6,[r1],#4
|
||||
adcs r5,r5,r6
|
||||
str r5,[r0],#4
|
||||
sub r12,r12,#1
|
||||
sub r4,r4,#1
|
||||
teq r4,#0
|
||||
bne single_add
|
||||
teq r12,#0
|
||||
beq clear_end
|
||||
multy_add:
|
||||
ldmia r0, {r3-r6}
|
||||
# load Source data
|
||||
ldmia r1!, {r7-r10}
|
||||
# load M
|
||||
adcs r3, r3, r7
|
||||
adcs r4, r4, r8
|
||||
adcs r5, r5, r9
|
||||
adcs r6, r6, r10
|
||||
stmia r0!, {r3-r6}
|
||||
sub r12,r12, #4
|
||||
teq r12,#0
|
||||
bne multy_add
|
||||
|
||||
#====================
|
||||
# clear used temp area
|
||||
#====================
|
||||
clear_end:
|
||||
|
||||
# read SEG_SIZE
|
||||
ldr r0, _L_TCR_BASE
|
||||
ldr r0,[r0,#0x14]
|
||||
and r1,r0,#0xC0
|
||||
mov r1, r1, LSR #6
|
||||
cmp r1, #1
|
||||
bhi clear_64
|
||||
# 1 segment = 64byte
|
||||
blt clear_256
|
||||
# 1 segment = 256byte
|
||||
|
||||
## else 1 segment =128byte
|
||||
ldr r0, =SEG_12
|
||||
# Start position
|
||||
ldr r1,_L_SEG_BASE
|
||||
orr r0,r1,r0, lsl #7
|
||||
ldr r1, =64
|
||||
b start_clear
|
||||
clear_64:
|
||||
ldr r0, =SEG_27
|
||||
# Start position
|
||||
ldr r1,_L_SEG_BASE
|
||||
orr r0,r1,r0, lsl #6
|
||||
ldr r1, =32
|
||||
b start_clear
|
||||
clear_256:
|
||||
ldr r0, =SEG_4
|
||||
# Start position
|
||||
ldr r1,_L_SEG_BASE
|
||||
orr r0,r1,r0, lsl #8
|
||||
ldr r1, =128
|
||||
# clear 2 segment
|
||||
start_clear:
|
||||
mov r2,#0
|
||||
mov r3,r2
|
||||
mov r4,r2
|
||||
mov r5,r2
|
||||
mov r6,r2
|
||||
mov r7,r2
|
||||
mov r8,r2
|
||||
mov r9,r2
|
||||
mov r10,r2
|
||||
clear_temp:
|
||||
stmia r0!, {r3-r10}
|
||||
subs r1,r1,#8
|
||||
bne clear_temp
|
||||
# clear the last segment sign value
|
||||
# read SEG_SIZE
|
||||
ldr r0, _L_TCR_BASE
|
||||
ldr r1, [r0,#0x14]
|
||||
and r1, r1, #0xC0
|
||||
mov r1, r1, LSR #6
|
||||
mov r0, #6
|
||||
cmp r1, #1
|
||||
moveq r0, #14
|
||||
# r0 = the last segment Num
|
||||
movhi r0, #29
|
||||
mov r1, #0x01
|
||||
mov r2,r1, lsl r0
|
||||
ldr r3, _L_TCR_BASE
|
||||
add r3,r3,#0x10
|
||||
ldr r4,[r3]
|
||||
bic r4,r4,r2
|
||||
str r4,[r3]
|
||||
end_tor_calR2:
|
||||
ldmfd sp!, {r1-r12,r14}
|
||||
# END PkeCalR2modM
|
||||
bx r14
|
||||
|
||||
# END
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#include <drivers/pke.h>
|
||||
#include <platform/clocks.h>
|
||||
#include <platform/power.h>
|
||||
#include <platform/soc/hwclocks.h>
|
||||
#include <platform/soc/hwregbase.h>
|
||||
#include <string.h>
|
||||
#include <sys.h>
|
||||
|
||||
#include "AppleS5L8900XPKE-hardware.h"
|
||||
|
||||
|
||||
#define Pke_Shim_DEBUG 0
|
||||
|
||||
#if Pke_Shim_DEBUG
|
||||
static void debug_data(uint8_t *data, size_t length)
|
||||
{
|
||||
uint32_t i=0;
|
||||
printf("data %p,%d\n" , data, length);
|
||||
for (i = 0; i < length; i++) {
|
||||
if( !(i%256) )
|
||||
printf("Seg : %p \n", data);
|
||||
printf("%02X, ", *(data + i));
|
||||
if ((i % 16) == 15)
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#define debug(fmt, args...) printf("pke_new::%s: " fmt "\n", __FUNCTION__ , ##args)
|
||||
#else
|
||||
#define debug(fmt, args...)
|
||||
#define debug_data(data, length)
|
||||
#endif
|
||||
|
||||
|
||||
//PKE hardware memory map.
|
||||
static volatile struct pke_regs *registers = (struct pke_regs *)PKE_BASE_ADDR;
|
||||
static volatile uint8_t *memory = (uint8_t*)(PKE_BASE_ADDR + 0x800);
|
||||
|
||||
extern bool rsa_cal_exp(void *dst, uint32_t *len, uint32_t options,
|
||||
uint8_t *rsquare, uint32_t *rsquare_length,
|
||||
uint8_t * const base, uint32_t base_length,
|
||||
uint8_t * const expn, uint32_t expn_length,
|
||||
uint8_t * const modulus, uint32_t modulus_length,
|
||||
volatile struct pke_regs *registers, volatile uint8_t *memory);
|
||||
|
||||
bool pke_do_exp(uint8_t *dst, size_t *len, size_t key_length,
|
||||
uint8_t * const base, size_t base_length,
|
||||
uint8_t * const expn, size_t expn_length,
|
||||
uint8_t * const mods, size_t mods_length)
|
||||
{
|
||||
bool ret = false;
|
||||
uint32_t rsquare[64]; //word aligned 256byte buffer.
|
||||
uint32_t rlen = sizeof(rsquare);
|
||||
|
||||
clock_gate(CLK_PKE, true);
|
||||
platform_power_set_gate(PWRBIT_USB, true);
|
||||
|
||||
#if Pke_Shim_DEBUG
|
||||
utime_t st, et;
|
||||
st = system_time();
|
||||
#endif
|
||||
ret = rsa_cal_exp(dst, (uint32_t*)len, 0,
|
||||
(uint8_t*)rsquare, &rlen,
|
||||
base, (uint32_t)base_length,
|
||||
expn, (uint32_t)expn_length,
|
||||
mods, (uint32_t)mods_length,
|
||||
registers, memory);
|
||||
#if Pke_Shim_DEBUG
|
||||
et = system_time();
|
||||
debug("rsa_cal_exp took %llu micros for keylen: %lu", (et-st), key_length);
|
||||
//debug("The result:");
|
||||
//debug_data(dst, *len);
|
||||
#endif
|
||||
|
||||
clock_gate(CLK_PKE, false);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright (C) 2007-2008 Apple Inc. All rights reserved.
|
||||
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OPTIONS += \
|
||||
WITH_HW_PKE=1
|
||||
|
||||
MODULES += \
|
||||
lib/pki
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/pke.o \
|
||||
$(LOCAL_DIR)/AppleS5L8900XPKE-hardware.o
|
||||
Reference in new issue
Block a user