first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
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 */
+930
View File
@@ -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
+87
View File
@@ -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;
}
+21
View File
@@ -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