1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "cc_pal_mem.h"
8 #include "cc_pal_types.h"
9 #include "cc_hal_plat.h"
10 #include "cc_sram_map.h"
11 #include "dx_crys_kernel.h"
12 #include "cc_regs.h"
13 #include "pka_hw_defs.h"
14 #include "pki.h"
15 #include "pki_dbg.h"
16 #include "pka.h"
17 #include "ec_wrst.h"
18 #include "pka_error.h"
19 #include "cc_common_math.h"
20 #include "cc_hal.h"
21 #include "cc_int_general_defs.h"
22
23 extern CC_PalMutex CCAsymCryptoMutex;
24
25 /* Maximum allowed PKA registers are 32 (PKA_MAX_COUNT_OF_PHYS_MEM_REGS): first 2 (PKA_REG_N & PKA_REG_NP) servers for N (modulus) and Np respectivly.
26 last 2 (PKA_REG_T0 & PKA_REG_T1) are reserved for HW use. so we have total of 28 registers for SW usage
27 list of maximum 28 allowed temp PKA registers for functions.
28 Note: last 2 are numbered 0xFF - for debug goals */
29 const int8_t regTemps[PKA_MAX_COUNT_OF_PHYS_MEM_REGS] = {PKA_REG_N, PKA_REG_NP,
30 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
31 0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,
32 0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,PKA_REG_T0,PKA_REG_T1};
33
34 #if defined PKA_DEBUG && defined DEBUG
35 uint32_t tempRes[PKA_MAX_REGISTER_SIZE_IN_32BIT_WORDS];
36 uint32_t tempRes1[PKA_MAX_REGISTER_SIZE_IN_32BIT_WORDS];
37 #endif
38
39
40 /*********** PkaSetRegsMapTab function **********************/
41 /**
42 * @brief This function initializes the PKA registers sizes table.
43 *
44 * The function checks input parameters and sets the physical memory registers mapping-table
45 * according to parameters, passed by the user:
46 * - start address of register 0 is the start address of PKA data registers memory
47 * CC_SRAM_PKA_BASE_ADDRESS (defined in cc_sram_map.h file);
48 * - special registers are set as follows: N=0,NP=1,T0=30,T1=31;
49 * - all registers have the same size, equalled to given size;
50 *
51 * @return - None.
52 *
53 */
PkaSetRegsMapTab(int32_t countOfRegs,int32_t regSizeInPkaWords)54 static void PkaSetRegsMapTab(int32_t countOfRegs, /*!< [in] The count of registeres, requirred by the user. */
55 int32_t regSizeInPkaWords) /*!< [in] Size of registers in PKA big words (e.g. 128-bit words). */
56 {
57 uint32_t currentAddr;
58 int32_t i;
59
60 /* start addres of PKA mem. */
61 currentAddr = CC_SRAM_PKA_BASE_ADDRESS;
62
63 /* set addresses of the user requested registers (excluding T0,T1) */
64 for (i = 0; i < PKA_MAX_COUNT_OF_PHYS_MEM_REGS-2; i++) {
65 if (i < countOfRegs - 2) {
66 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, MEMORY_MAP0) + i*sizeof(uint32_t), currentAddr);
67 currentAddr += regSizeInPkaWords*PKA_WORD_SIZE_IN_32BIT_WORDS;
68 } else {
69 /* write designation, that PKI entry is not in use */
70 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET (CRY_KERNEL, MEMORY_MAP0)+ i*sizeof(uint32_t), PKA_ADDRESS_ENTRY_NOT_USED);
71 }
72 }
73 /* set addresses of 2 temp registers: T0=30, T1=31 */
74 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, MEMORY_MAP0) + 30*sizeof(uint32_t), currentAddr);
75 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, MEMORY_MAP0) + 31*sizeof(uint32_t),
76 currentAddr + regSizeInPkaWords*PKA_WORD_SIZE_IN_32BIT_WORDS);
77
78 /* set default virtual addresses of N,NP,T0,T1 registers into N_NP_T0_T1_Reg */
79 PKA_DEFAULT_N_NP_T0_T1_REG();
80
81 return;
82
83 }
84
85
86 /*********** PkaDivLongNum function **********************/
87 /**
88 * @brief The function divides long number A*(2^S) by B:
89 * Res = A*(2^S) / B, remainder A = A*(2^S) % B.
90 * where: A,B - are numbers of size, which is not grate than, maximal operands size,
91 * and B > 2^S;
92 * S - exponent of binary factor of A.
93 * ^ - exponentiation operator.
94 *
95 * The function algorithm:
96 *
97 * 1. Let nWords = S/32; nBits = S % 32;
98 * 2. Set Res = 0, rT1 = OpA;
99 * 3. for(i=0; i<=nWords; i++) do:
100 * 3.1. if(i < nWords )
101 * s1 = 32;
102 * else
103 * s1 = nBits;
104 * 3.2. rT1 = rT1 << s1;
105 * 3.3. call PKA_div for calculating the quotient and remainder:
106 * rT2 = floor(rT1/opB) //quotient;
107 * rT1 = rT1 % opB //remainder (is in rT1 register);
108 * 3.4. Res = (Res << s1) + rT2;
109 * end do;
110 * 4. Exit.
111 *
112 * Assuming:
113 * - 5 PKA registers are used: OpA, OpB, Res, rT1, rT2.
114 * - The registers sizes and mapping tables are set on default mode
115 * according to operands size.
116 * - The PKA clocks are initialized.
117 * NOTE ! Operand OpA shall be overwritten by remainder.
118 *
119 * @return CC_OK On success, otherwise indicates failure
120 *
121 */
PkaDivLongNum(uint8_t lenId,int8_t OpA,uint32_t S,int8_t OpB,int8_t Res,int8_t rT1,int8_t rT2)122 static CCError_t PkaDivLongNum(uint8_t lenId, /*!< [in] ID of operation size (modSize+32). */
123 int8_t OpA, /*!< [in] Operand A: virtual register pointer of A . */
124 uint32_t S, /*!< [in] exponent of binary factor of A. */
125 int8_t OpB, /*!< [in] Operand B: virtual register pointer of B. */
126 int8_t Res, /*!< [out] Virtual register pointer for result quotient. */
127 int8_t rT1, /*!< [in] Virtual pointer to remainder. */
128 int8_t rT2) /*!< [in] Virtual pointer of temp register. */
129 {
130 uint32_t nBits, nWords;
131 uint32_t i;
132 int8_t s1 = 0; /* current shift count */
133
134
135 /* calculate shifting parameters (words and bits ) */
136 nWords = (CALC_FULL_32BIT_WORDS((uint32_t)S));
137 nBits = (uint32_t)S % CC_BITS_IN_32BIT_WORD;
138
139 /* copy operand OpA (including extra word) into temp reg rT1 */
140 PKA_COPY(LEN_ID_MAX_BITS, rT1/*dst*/, OpA/*src*/);
141
142 /* set Res = 0 (including extra word) */
143 PKA_2CLEAR(LEN_ID_MAX_BITS, Res/*dst*/);
144
145
146 /* Step 1. Shifting and dividing loop */
147 for (i = 0; i < nWords; i++) {
148 /* 3.1 set shift value s1 */
149 if (i > 0)
150 s1 = CC_BITS_IN_32BIT_WORD;
151 else
152 s1 = nBits;
153
154 /* 3.2. shift: rT1 = rT1 * 2**s1 (in code (s1-1), because PKA performs S+1 shifts) */
155 if (s1 > 0) {
156 PKA_SHL_FILL0( lenId+1, rT1/*Res*/, rT1/*OpA*/, (s1-1)/*S*/);
157 }
158
159 /* 3.3. perform PKA_DIV for calculating a quotient rT2 = floor(rT1 / N)
160 and remainder rT1 = rT1 % OpB */
161 PKA_DIV( lenId+1, rT2/*Res*/, rT1 /*OpA*/, OpB /*B*/);
162
163 #ifdef LLF_PKI_PKA_DEBUG_
164 /* debug copy result into temp buffer */
165 CC_PalMemSetZero((uint8_t*)tempRes, sizeof(tempRes));
166 PkaCopyDataFromPkaReg(
167 tempRes/*dst_ptr*/, RegSizeWords,
168 rT1/*srcReg*/);
169 #endif
170
171 /* 3.4. Res = Res * 2**s1 + Res; */
172 if (s1 > 0) {
173 PKA_SHL_FILL0( lenId+1, Res /*Res*/, Res /*OpA*/, (s1-1)/*S*/);
174 }
175
176 PKA_ADD( lenId+1, Res /*Res*/, Res /*OpA*/, rT2 /*OpB*/);
177 }
178
179 PKA_WAIT_ON_PKA_DONE();
180
181 return CC_OK;
182
183 }
184
185
186
187 /*********** PkaModDivideBy2 **********************/
188 /**
189 * @brief This function performs modular division by 2: rRes = rX / 2 mod rN.
190 *
191 * @return - None.
192 *
193 */
PkaModDivideBy2(uint32_t lenId,uint32_t rX,uint32_t rN,uint32_t rRes)194 void PkaModDivideBy2(uint32_t lenId, /*!< [in] ID of entry of regsSizesTable containing rX modulus exact length. */
195 uint32_t rX, /*!< [in] Virtual pointer to PKA register X. */
196 uint32_t rN, /*!< [out] Virtual pointer to PKA register, containing the modulus N. */
197 uint32_t rRes) /*!< [out] Virtual pointer to PKA register, containing the result. */
198 {
199 uint32_t bitVal = 0;
200
201 if (rX != rRes) {
202 PKA_COPY(LEN_ID_MAX_BITS, rRes/*dst*/, rX/*src*/);
203 }
204
205 /* if the vector rX is odd, then add the modulus and then divide by 2 */
206
207 PKA_READ_BIT0(lenId+1, rRes/*regNum*/, bitVal);
208 if (bitVal == 1) {
209 PKA_ADD(lenId+1, rRes/*Res*/, rRes/*P*/, rN/*OpB=N=0*/);
210 }
211
212 /* divide by 2 */
213 PKA_SHR_FILL0(lenId+1, rRes/*Res*/, rRes/*P*/, 1-1/*S*/);
214
215
216 }
217
218
219 /*********** PkaGetRegEffectiveSizeInBits function **********************/
220 /**
221 * @brief This function returns effective size in bits of data placed in PKA register.
222 *
223 * @return - Effective size of data in register (bits).
224 *
225 */
PkaGetRegEffectiveSizeInBits(uint32_t reg)226 uint32_t PkaGetRegEffectiveSizeInBits(uint32_t reg) /*!< [in] Register virt. pointer. */
227 {
228 // RL Do resistant and add flag to arg.
229 int size = 1, i;
230 uint32_t addr;
231 uint32_t currWord = 0, mask = 1Ul << 31;
232
233 /* read register address and full operation size in bits */
234 PKA_GET_REG_ADDRESS(reg, addr);
235 PKA_GET_REG_SIZE(size, LEN_ID_MAX_BITS/*lenID*/);
236
237 /* register size in words */
238 size = CALC_FULL_32BIT_WORDS(size);
239
240 /* read words and find MSWord */
241 for (i = size-1 ; i >= 0 ; i--) {
242 PKA_HW_READ_VALUE_FROM_PKA_MEM(addr + i, currWord);
243 if (currWord != 0)
244 break;
245 }
246
247 size = CC_BITS_IN_32BIT_WORD*(i+1); //in bits
248
249 if (currWord == 0)
250 return size;
251
252 /* find number of bits in the MS word */
253 for (i = 1; i <= CC_BITS_IN_32BIT_WORD; i++) {
254 if (currWord & mask)
255 break;
256 size--;
257 mask >>= 1;
258 }
259
260 return size;
261 }
262
263
264 /*********** PkaGetNextMsBit function **********************/
265 /**
266 * @brief The function returns MS-bit from register r.
267 *
268 *
269 * @author reuvenl (6/12/2014)
270 *
271 * @return uint32_t - bit's value
272 */
PkaGetNextMsBit(uint32_t rX,int32_t i,uint32_t * pW,uint32_t * pIsNew)273 uint32_t PkaGetNextMsBit(uint32_t rX, /*!< [in] Register virt. pointer. */
274 int32_t i, /*!< [in] Index of the requirred bit. */
275 uint32_t *pW, /*!< [in] Pointer to 32-bit current word, which must be saved by
276 caller through reading bits from the register. */
277 uint32_t *pIsNew) /*!< [in] Pointer to indicator is this a new start (pIsNew=1) of
278 the function for this register. The value is updated
279 to 0 by the function after first start. */
280 {
281 uint32_t b;
282
283 if (*pIsNew || (i & 31UL) == 31) {
284 PKA_READ_WORD_FROM_REG(*pW, i>>5, rX);
285 /* ones only */
286 if ((i & 31UL) != 31)
287 *pW <<= (31 - (i & 31UL));
288 *pIsNew = 0;
289 }
290
291 b = *pW >> 31;
292 *pW <<= 1;
293
294 return b;
295 }
296
297
298
299 /*********** PkaGet2MsBits function **********************/
300 /**
301 * @brief The function returns 2 MS-bits from register r.
302 *
303 * @author reuvenl (6/12/2014)
304 *
305 * @return uint32_t - bit's value
306 */
PkaGet2MsBits(uint32_t rX,int32_t i,uint32_t * pW,uint32_t * pIsNew)307 uint32_t PkaGet2MsBits(uint32_t rX, /*!< [in] Register virt. pointer. */
308 int32_t i, /*!< [in] Index of the required bit. */
309 uint32_t *pW, /*!< [in] Pointer to 32-bit current word, which must be saved by
310 caller through reading bits from the register. */
311 uint32_t *pIsNew) /*!< [in] Pointer to indicator is it a new start other function
312 for this register or not. The value is updated
313 to FALSE by the function after start. */
314 {
315 uint32_t b;
316
317 PKA_ASSERT(!(i&1), "PkaGet2MsBits: even bit");
318
319 if (*pIsNew || (i & 0x1F) == 30) {
320 PKA_READ_WORD_FROM_REG(*pW, i>>5, rX);
321 *pIsNew = 0;
322 }
323
324 b = (*pW >> (i&0x1F)) & 0x3;
325
326 return b;
327 }
328
329
330 /*********** PkaFinishAndMutexUnlock function **********************/
331 /**
332 * @brief This function clears the PKA memory and clock, and unlocks the Asymmetric mutex.
333 *
334 * @return None
335 */
PkaSetLenIds(uint32_t sizeInBits,uint32_t lenId)336 void PkaSetLenIds(uint32_t sizeInBits, /*!< [in] The exact size operation for the LenId. */
337 uint32_t lenId) /*!< [in] ID of entry of regsSizesTable defines register length
338 with word extension. */
339 {
340
341 PKA_SET_REG_SIZE(sizeInBits, lenId);
342 PKA_SET_REG_SIZE(GET_FULL_OP_SIZE_BITS(sizeInBits), lenId+1);
343
344 }
345
346
347 /*********** PkaInitAndMutexLock function **********************/
348 /**
349 * @brief This function Inialize the PKA memory and clock, and locks the Asymmetric mutex.
350 *
351 * @return CC_OK On success, otherwise indicates failure
352 */
353
PkaInitAndMutexLock(uint32_t sizeInBits,uint32_t * pkaRegCount)354 CCError_t PkaInitAndMutexLock(uint32_t sizeInBits, /*!< [in] Operation (modulus) exact size in bits. The value must
355 be in interval from defined min. to max. size in bits. */
356 uint32_t *pkaRegCount) /*!< [in/out] As input - required registers for operation.
357 As output - actual available regs, must be at least as required. */
358 {
359 CCError_t err = CC_OK;
360
361 err = CC_PalMutexLock(&CCAsymCryptoMutex, CC_INFINITE);
362 if (err != CC_SUCCESS) {
363 CC_PalAbort("Fail to acquire mutex\n");
364 }
365
366 /* verify that the device is not in fatal error state before activating the PKA engine */
367 CC_IS_FATAL_ERR_ON(err);
368 if (err == CC_TRUE) {
369 err = PKA_FATAL_ERR_STATE_ERROR;
370 goto EndUnlockMutex;
371 }
372
373 /* increase CC counter at the beginning of each operation */
374 err = CC_IS_WAKE;
375 if (err != CC_SUCCESS) {
376 CC_PalAbort("Fail to increase PM counter\n");
377 }
378
379 /* initialize the PKA engine on default mode with size of registers */
380 err = PkaInitPka(sizeInBits, 0 /*sizeInWords*/, pkaRegCount);
381
382 if (err != CC_SUCCESS) {
383 /* decrease CC counter at the end of each operation */
384 if (CC_IS_IDLE != CC_SUCCESS) {
385 CC_PalAbort("Fail to decrease PM counter\n");
386 }
387 }
388
389 EndUnlockMutex:
390 if (err != CC_SUCCESS) {
391 if (CC_PalMutexUnlock(&CCAsymCryptoMutex) != 0) {
392 CC_PalAbort("Fail to release mutex\n");
393 }
394 }
395
396 return err;
397 }
398
399
400 /*********** PkaFinishAndMutexUnlock function **********************/
401 /**
402 * @brief This function clears the PKA memory and clock, and unlocks the Asymmetric mutex.
403 *
404 * @return None
405 */
PkaFinishAndMutexUnlock(uint32_t pkaRegCount)406 void PkaFinishAndMutexUnlock(uint32_t pkaRegCount) /*!< [in] Number of registers to clear. */
407 {
408 // clear used registers
409 if (pkaRegCount > 0) {
410 pkaRegCount = CC_MIN(PKA_MAX_COUNT_OF_PHYS_MEM_REGS-2, pkaRegCount);
411 /* clear used PKA registers for security goals */
412 PkaClearBlockOfRegs(PKA_REG_N/*FirstReg*/, pkaRegCount, LEN_ID_MAX_BITS/*LenID*/);
413 }
414
415 /* Finish PKA operations (waiting PKI done and close PKA clocks) */
416 PkaFinishPka();
417
418 /* decrease CC counter at the end of each operation */
419 if (CC_IS_IDLE != CC_SUCCESS) {
420 CC_PalAbort("Fail to decrease PM counter\n");
421 }
422
423 /* release the hardware semaphore */
424 if (CC_PalMutexUnlock(&CCAsymCryptoMutex) != CC_SUCCESS) {
425 CC_PalAbort("Fail to release mutex\n");
426 }
427
428 }
429
430
431 /*********** PkaSetRegsSizesTab function **********************/
432 /**
433 * @brief This function initializes the PKA registers sizes table.
434 *
435 * The function sets sizes table as follows:
436 * - tab[0] = MaxSizeBits; //maximal size, usually this is exact modulus size in bits
437 * - tab[1] = Extended size with extra bits, aligned to big words.
438 * - other entrie,
439 uint32_t Xs = PKA_SIZE_ENTRY_NOT_USED, means - not used.
440 *
441 * @return - None.
442 *
443 */
PkaSetRegsSizesTab(uint32_t opSizeInBits,int32_t regSizeInPkaWords)444 void PkaSetRegsSizesTab(uint32_t opSizeInBits, /*!< [in] Size of PKA operations (modulus) in bits. The value must be in interval
445 * from defined Min. to Max. size bits */
446 int32_t regSizeInPkaWords) /*!< [in] Size of registers in PKA big words (e.g. 128-bit words). */
447 {
448
449 uint32_t i;
450
451 /* Set exact op. size */
452 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET (CRY_KERNEL, PKA_L0), opSizeInBits);
453 /* Set size with extra bits aligned to big words */
454 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET (CRY_KERNEL, PKA_L0) + CC_32BIT_WORD_SIZE, GET_FULL_OP_SIZE_BITS(opSizeInBits));
455
456 /* remaining entries set to PKA_SIZE_ENTRY_NOT_USED for debugging goals */
457 for (i = 2; i < PKA_NUM_OF_PKA_LEN_IDS_REGS; i++) {
458 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET (CRY_KERNEL, PKA_L0) + CC_32BIT_WORD_SIZE*i,
459 regSizeInPkaWords*CC_PKA_WORD_SIZE_IN_BITS);
460 }
461
462 return;
463
464 }
465
466 /*********** PkaInitPka function **********************/
467 /**
468 * @brief This function initializes the PKA engine.
469 *
470 * The function performs the following:
471 * - initializes the PKA_SizesTable, PKA_MappingTable and special register
472 * N_NP_T0_T1 according to user passed register sizes, registers mapping
473 * and default N_NP_T0_T1 value.
474 *
475 * The function calls the PkaSetRegsSizesTab and PkaSetRegsMapTab
476 * functions and sets N_NP_T0_T1 value into N_NP_T0_T1 register.
477 * Notes:
478 * - See remarks to PkaSetRegsSizesTab and PkaSetRegsMapTab functions.
479 * - The function allocates one additional word for each register if it is needed for extra bits.
480 *
481 * @return CC_OK On success, otherwise indicates failure
482 *
483 */
PkaInitPka(uint32_t opSizeInBits,uint32_t regSizeInPkaWords,uint32_t * pRegsCount)484 CCError_t PkaInitPka(uint32_t opSizeInBits, /*!< [in] Operation (modulus) exact size in bits. The value must
485 be in interval from defined min. to max. size in bits. */
486 uint32_t regSizeInPkaWords, /*!< [in] PKA register size. not exact for operation (== modulus). */
487 uint32_t *pRegsCount) /*!< [in/out] As input - required registers for operation (including PKA
488 temp registers T0,T1). As output - actual available regs, must be
489 at least as required. */
490 {
491 int32_t regsCount;
492 uint32_t regSizeIn32BitWords;
493 uint32_t minRegSizeInPkaWords;
494 uint32_t mask = 0;
495
496 if (opSizeInBits < PKA_MIN_OPERATION_SIZE_BITS ) {
497 return PKA_REGISTER_SIZES_ERROR;
498 }
499
500 /* calculate pka register size */
501 if (opSizeInBits < (2*(CC_PKA_WORD_SIZE_IN_BITS+PKA_EXTRA_BITS))) {
502 regSizeIn32BitWords = CALC_FULL_32BIT_WORDS(opSizeInBits+CC_PKA_WORD_SIZE_IN_BITS+PKA_EXTRA_BITS-1);
503 if ((opSizeInBits+CC_PKA_WORD_SIZE_IN_BITS+PKA_EXTRA_BITS-1) % CC_BITS_IN_32BIT_WORD) {
504 regSizeIn32BitWords++;
505 }
506 } else {
507 regSizeIn32BitWords = CALC_FULL_32BIT_WORDS(opSizeInBits);
508 }
509
510 minRegSizeInPkaWords = GET_FULL_OP_SIZE_PKA_WORDS(regSizeIn32BitWords*CC_BITS_IN_32BIT_WORD);
511
512 /* check given regs size or set it, if is not given */
513 if (regSizeInPkaWords > 0) {
514 if (regSizeInPkaWords < minRegSizeInPkaWords)
515 return PKA_REGISTER_SIZES_ERROR;
516 } else {
517 regSizeInPkaWords = minRegSizeInPkaWords;
518 }
519
520 /* actually avaliable count of PKA registers */
521 regsCount = CC_MIN(CC_SRAM_PKA_SIZE_IN_BYTES / (regSizeInPkaWords*PKA_WORD_SIZE_IN_BYTES),
522 PKA_MAX_COUNT_OF_PHYS_MEM_REGS);
523
524 if (pRegsCount != NULL) {
525 #ifdef PKA_DEBUG
526 // checking number of registers are enough to execute this function
527 if ((size_t)regsCount < *pRegsCount) {
528 return PKA_REGS_COUNT_ERROR;
529 }
530 #endif
531 *pRegsCount = regsCount;
532 }
533
534 /* Mask PKA interrupt */
535 mask = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR));
536 CC_REG_FLD_SET(HOST_RGF, HOST_IMR, PKA_EXP_MASK, mask, 1);
537 CC_HalMaskInterrupt(mask);
538
539 /* enabling the PKA clocks */
540 CC_HAL_WRITE_REGISTER( CC_REG_OFFSET(CRY_KERNEL, PKA_CLK_ENABLE), 0x1UL );
541
542 /* setting the PKA registers mapping table */
543 PkaSetRegsMapTab(regsCount, regSizeInPkaWords);
544
545 /* setting the PKA registers sizes table */
546 PkaSetRegsSizesTab(opSizeInBits, regSizeInPkaWords);
547
548 return CC_OK;
549
550 }
551
552
553 /*********** PkaCalcNpIntoPkaReg function **********************/
554 /**
555 * The function uses physical data pointers to calculate and output
556 * the Barrett tag Np.
557 *
558 * For RSA it uses truncated sizes:
559 * Np = truncated(2^(3*A+3*X-1) / ceiling(n/(2^(N-2*A-2*X)));
560 * For ECC - full sizes of not truncated input arguments:
561 * Np = truncated(2^(N+A+X-1) / n);
562 *
563 * function assumes modulus in PKA reg 0, and output is to PKA reg 1
564 *
565 * @author reuvenl (5/1/2014)
566 *
567 * @return CC_OK On success, otherwise indicates failure
568 */
PkaCalcNpIntoPkaReg(uint32_t lenId,uint32_t sizeNbits,int8_t regN,int8_t regNp,int8_t regTemp1,int8_t regTempN)569 CCError_t PkaCalcNpIntoPkaReg(uint32_t lenId, /*!< [in] ID of entry of regsSizesTable defines register length
570 with word extension. */
571 uint32_t sizeNbits, /*!< [in] The exact size of the modulus. */
572 int8_t regN, /*!< [in] Virtual address (number) holding the modulus n. */
573 int8_t regNp, /*!< [out] Virtual address (number) holding Np. */
574 int8_t regTemp1, /*!< [in] Virtual address (number) for temporary usage. */
575 int8_t regTempN) /*!< [in] Virtual address (number) for temporary usage. */
576 {
577 CCError_t err = 0;
578 int32_t i;
579 uint32_t A = CC_PKA_WORD_SIZE_IN_BITS;
580 uint32_t X = PKA_EXTRA_BITS;
581 int32_t wT,bNom,wNom; /*Sizes in words and bits */
582 uint32_t val;
583 int32_t sh, st;
584
585 // clear temp registers
586 PKA_2CLEAR(LEN_ID_MAX_BITS, regTemp1);
587 PKA_2CLEAR(LEN_ID_MAX_BITS, regTempN);
588 PKA_2CLEAR(LEN_ID_MAX_BITS, regNp);
589
590 // copy modulus (regN) into temprarty register - regTempN
591 PKA_COPY(LEN_ID_MAX_BITS /* LenID */, regTempN /* OpDest */, regN /* OpSrc */);
592
593 if (sizeNbits <= (2*A + 2*X)) {
594 wNom = CALC_FULL_32BIT_WORDS(sizeNbits+A+X-1);
595 /* Sizes of nominator (N+A+X-1) in 32-bit words */
596 bNom = (sizeNbits+A+X-1) % CC_BITS_IN_32BIT_WORD; /*remain bits*/
597 if (bNom) {
598 val = 1UL << bNom;
599 } else {
600 wNom++;
601 val = 1UL;
602 }
603
604 /* Set rT2 = 2^(N+A+X-1) */
605 PKA_WRITE_WORD_TO_REG(val, wNom-1, regTemp1);
606 // use LEN_ID_MAX_BITS for small sizes, since lenId is exact mod size which is not enought in this case!!!
607 PKA_DIV(LEN_ID_MAX_BITS/*LenID*/, regNp, regTemp1, regTempN);
608 }
609 /* If (N > 2*A + 2*X) - truncated */
610 else {
611 /* Set rT1 = 2^D, where D=(3*A+3*X-1) division nominator size */
612 wNom = CALC_FULL_32BIT_WORDS(3*A + 3*X - 1); /*words count in nominator */
613 /* Calc. sizes of Nominator */
614 bNom = (3*A + 3*X - 1) % CC_BITS_IN_32BIT_WORD; /*remain bits count*/
615 if (bNom) {
616 val = 1UL << bNom;
617 } else {
618 wNom++;
619 val = 1UL;
620 }
621
622 /* Set rT1 = 2^D, where D=(3*A+3*X-1) */
623 PKA_WRITE_WORD_TO_REG(val, wNom-1, regTemp1);
624
625 /* Set rN = high part of the modulus as divisor */
626 /* count low bits to truncate the modulus */
627 st = sizeNbits - 2*A - 2*X;
628 /* count of words to truncate */
629 wT = st / CC_BITS_IN_32BIT_WORD;
630 /* shift for truncation */
631 sh = st % CC_BITS_IN_32BIT_WORD;
632
633
634 /* prevent further ceiling increment, if it not needed */
635 PKA_SUB_IM(lenId+1/*LenID*/, regTempN, regTempN, 1/*OpBIm*/);
636
637 /* truncate modulus by words and then by bits */
638 for (i=0; i<wT; i++) {
639 PKA_SHR_FILL0(lenId+1/*LenID*/, regTempN, regTempN, CC_BITS_IN_32BIT_WORD-1);
640 }
641 if (sh) {
642 PKA_SHR_FILL0(lenId+1/*LenID*/, regTempN, regTempN, sh-1);
643 }
644
645 /* Ceiling */
646 PKA_ADD_IM(lenId+1/*LenID*/, regTempN, regTempN, 1/*OpBIm*/);
647 PKA_DIV(LEN_ID_MAX_BITS/*LenID*/, regNp, regTemp1, regTempN); //use LEN_ID_MAX_BITS to make sure we catch the whole size
648 }
649
650 // clear temp registers
651 PKA_2CLEAR(LEN_ID_MAX_BITS, regTemp1);
652 PKA_2CLEAR(LEN_ID_MAX_BITS, regTempN);
653
654 return err;
655 }
656
657
658 /*********** PkaClearBlockOfRegs function **********************/
659 /**
660 * @brief This function clears block of PKA registers + temp registers 30,31.
661 *
662 * Assumings: - PKA is initialized properly.
663 * - Length of extended (by word) registers is placed into LenID entry of
664 * sizes table.
665 * - Meets condition: firstReg <= 30.
666 * - All registers, given to cleaning, are inside the allowed memory.
667 *
668 * @return - None.
669 *
670 */
PkaClearBlockOfRegs(uint32_t firstReg,int32_t countOfRegs,uint32_t lenId)671 void PkaClearBlockOfRegs( uint32_t firstReg, /*!< [in] Virtual address (number) of first register in block. */
672 int32_t countOfRegs, /*!< [in] Count of registers to clear. */
673 uint32_t lenId) /*!< [in] ID of entry of regsSizesTable defines register length
674 with word extension. */
675 {
676 int32_t i;
677 uint32_t size, addr;
678
679 /* check registers count */
680 PKA_ASSERT(!(firstReg >= 32 || firstReg + countOfRegs > 32), "PkaClearBlockOfRegs: firstReg > 32 or firstReg + countOfRegs > 32");
681
682 /* calculate size of register in words */
683 PKA_GET_REG_SIZE(size, lenId);
684 size = CALC_FULL_32BIT_WORDS(size);
685
686 /* clear ordinary and temp registers without PKA operations */
687
688 for (i = 0; i < countOfRegs; i++) {
689 PKA_GET_REG_ADDRESS(firstReg+i/*VirtReg*/,addr/*physAddr*/);
690 PKA_HW_CLEAR_PKA_MEM(addr, size);
691 }
692 PKA_GET_REG_ADDRESS(PKA_REG_T1/*VirtReg*/,addr/*physAddr*/);
693 PKA_HW_CLEAR_PKA_MEM(addr, size);
694 PKA_GET_REG_ADDRESS(PKA_REG_T0/*VirtReg*/,addr/*physAddr*/);
695 PKA_HW_CLEAR_PKA_MEM(addr, size);
696
697 return;
698 }
699
700 /*********** PkaCopyDataFromPkaReg **********************/
701 /**
702 * @brief This function copies data from PKA register into output buffer .
703 *
704 * Assumings: - PKA is initialized.
705 * - Length of extended (by word) registers is placed into LenID entry of
706 * sizes table.
707 * - If the extra word of register must be cleared also the user must
708 * set LenID according to extended register size
709 *
710 * @return - None.
711 *
712 */
PkaCopyPkaRegIntoBeByteBuff(uint8_t * dst_ptr,uint32_t sizeWords,uint32_t srcReg)713 void PkaCopyPkaRegIntoBeByteBuff(uint8_t *dst_ptr, /*!< [out] Virtual address (number) of source PKA register. */
714 uint32_t sizeWords, /*!< [in] Buffer size in words. */
715 uint32_t srcReg) /*!< [in] Source register. */
716 {
717 uint32_t currAddr;
718 uint32_t tempWord;
719 int32_t ii;
720
721 /* copy data from src buffer into PKA register with 0-padding *
722 * in the last PKA-word */
723 PKA_GET_REG_ADDRESS(srcReg, currAddr);
724
725 PKA_MUTEX_LOCK;
726 PKA_WAIT_ON_PKA_DONE();
727 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_SRAM_RADDR), currAddr);
728 for(ii = sizeWords-1; ii >= 0; ii--) {
729 WAIT_SRAM_DATA_READY;
730 tempWord = CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_SRAM_RDATA));
731 tempWord = CC_COMMON_REVERSE32(tempWord);
732 CC_PalMemCopy(&dst_ptr[ii*CC_32BIT_WORD_SIZE], (uint8_t *)&tempWord, CC_32BIT_WORD_SIZE);
733 }
734 WAIT_SRAM_DATA_READY;
735 PKA_MUTEX_UNLOCK;
736 return;
737
738 }
739
740
741 /*********** PkaCopyDataFromPkaReg **********************/
742 /**
743 * @brief This function copies data from PKA register into output buffer .
744 *
745 * Assumings: - PKA is initialized.
746 * - Length of extended (by word) registers is placed into LenID entry of
747 * sizes table.
748 * - If the extra word of register must be cleared also the user must
749 * set LenID according to extended register size
750 *
751 * @return - None.
752 *
753 */
PkaCopyDataFromPkaReg(uint32_t * dst_ptr,uint32_t sizeWords,uint32_t srcReg)754 void PkaCopyDataFromPkaReg(uint32_t *dst_ptr, /*!< [out] Pointer to destination buffer. */
755 uint32_t sizeWords, /*!< [in] Source size in words. */
756 uint32_t srcReg) /*!< [in] Virtual address (number) of source PKA register. */
757 {
758 uint32_t currAddr;
759
760 PKA_GET_REG_ADDRESS(srcReg, currAddr/*PhysAddr*/);
761 PKA_HW_READ_BLOCK_FROM_PKA_MEM(currAddr, dst_ptr, sizeWords );
762
763 return;
764
765 }
766
767
PkaCopyByteBuffIntoPkaReg(uint32_t dstReg,uint32_t lenId,const uint8_t * src_ptr,uint32_t size)768 void PkaCopyByteBuffIntoPkaReg(uint32_t dstReg, /*!< [out] Virtual address (number) of destination register. */
769 uint32_t lenId, /*!< [in] ID of entry of regsSizesTable defines registers length with word extension. */
770 const uint8_t *src_ptr, /*!< [in] Pointer to source buffer big endian. */
771 uint32_t size) /*!< [in] Data size in bytes. */
772 {
773 uint32_t currAddr;
774 uint32_t regSize;
775 uint32_t sizeWords;
776 uint32_t tempWord;
777 uint32_t remainBytes = size % CC_32BIT_WORD_SIZE;
778 uint32_t ii;
779
780 /* copy data from src buffer into PKA register with 0-padding *
781 * in the last PKA-word */
782 PKA_GET_REG_ADDRESS(dstReg, currAddr);
783 size -= remainBytes;
784
785 PKA_MUTEX_LOCK;
786 PKA_WAIT_ON_PKA_DONE();
787 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_SRAM_ADDR), currAddr);
788 for(ii = 0; ii< size; ii+=CC_32BIT_WORD_SIZE) {
789 CC_PalMemCopy((uint8_t *)&tempWord, &src_ptr[ii], CC_32BIT_WORD_SIZE);
790 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_SRAM_WDATA), tempWord);
791 WAIT_SRAM_DATA_READY;
792 }
793 if (remainBytes > 0) {
794 tempWord = 0;
795 CC_PalMemCopy((uint8_t *)&tempWord, &src_ptr[ii], remainBytes);
796 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_SRAM_WDATA), tempWord);
797 WAIT_SRAM_DATA_READY;
798 }
799 PKA_MUTEX_UNLOCK;
800 /* data size aligned to full PKA-word */
801 sizeWords = ((CALC_32BIT_WORDS_FROM_BYTES(size+remainBytes)+PKA_WORD_SIZE_IN_32BIT_WORDS-1)/PKA_WORD_SIZE_IN_32BIT_WORDS) * \
802 PKA_WORD_SIZE_IN_32BIT_WORDS;
803 currAddr = currAddr + sizeWords;
804
805 /* register size in bits */
806 PKA_GET_REG_SIZE(regSize, lenId);
807 regSize = CALC_FULL_32BIT_WORDS(regSize);
808
809 /* zeroe not significant high words of the register */
810 if (regSize > sizeWords) {
811 PKA_HW_CLEAR_PKA_MEM(currAddr, regSize - sizeWords);
812 }
813
814 return;
815 }
816
817 /*********** PkaCopyDataIntoPkaReg function **********************/
818 /**
819 * @brief This function copies source data BE byte buffer into PKA register LE word buffer.
820 *
821 * Assumings: - PKA is initialized.
822 * - Length of extended (by word) registers is placed into LenID entry of
823 * sizes table.
824 * - If the extra word of register must be cleared also the user must
825 * set LenID according to extended register size
826 *
827 * @return - None.
828 *
829 */
PkaCopyBeByteBuffIntoPkaReg(uint32_t dstReg,uint32_t lenId,const uint8_t * src_ptr,uint32_t sizeWords)830 void PkaCopyBeByteBuffIntoPkaReg(uint32_t dstReg, /*!< [out] Virtual address (number) of destination register. */
831 uint32_t lenId, /*!< [in] ID of entry of regsSizesTable defines registers length with word extension. */
832 const uint8_t *src_ptr, /*!< [in] Pointer to source buffer big endian. */
833 uint32_t sizeWords) /*!< [in] Data size in word. */
834 {
835 uint32_t currAddr;
836 uint32_t regSize;
837 uint32_t tempWord;
838 uint32_t size = sizeWords*CC_32BIT_WORD_SIZE;
839 int32_t ii;
840
841 /* copy data from src buffer into PKA register with 0-padding *
842 * in the last PKA-word */
843 PKA_GET_REG_ADDRESS(dstReg, currAddr);
844
845 PKA_MUTEX_LOCK;
846 PKA_WAIT_ON_PKA_DONE();
847 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_SRAM_ADDR), currAddr);
848 for(ii = size-CC_32BIT_WORD_SIZE; ii >= 0; ii-=CC_32BIT_WORD_SIZE) {
849 CC_PalMemCopy((uint8_t *)&tempWord, &src_ptr[ii], CC_32BIT_WORD_SIZE);
850 tempWord = CC_COMMON_REVERSE32(tempWord);
851 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_SRAM_WDATA), tempWord);
852 WAIT_SRAM_DATA_READY;
853 }
854 PKA_MUTEX_UNLOCK;
855 /* data size aligned to full PKA-word */
856 sizeWords = ((sizeWords+PKA_WORD_SIZE_IN_32BIT_WORDS-1)/PKA_WORD_SIZE_IN_32BIT_WORDS) * \
857 PKA_WORD_SIZE_IN_32BIT_WORDS;
858 currAddr = currAddr + sizeWords;
859
860 /* register size in bits */
861 PKA_GET_REG_SIZE(regSize, lenId);
862 regSize = CALC_FULL_32BIT_WORDS(regSize);
863
864 /* zeroe not significant high words of the register */
865 if (regSize > sizeWords) {
866 PKA_HW_CLEAR_PKA_MEM(currAddr, regSize - sizeWords);
867 }
868
869 #if defined PKA_DEBUG && defined DEBUG
870 /*! PKA_DEBUG */
871 PkaCopyDataFromPkaReg(tempRes, regSize, dstReg);
872 #endif
873 return;
874 }
875
876
877 /*********** PkaCopyDataIntoPkaReg function **********************/
878 /**
879 * @brief This function copies source data into PKA register .
880 *
881 * Assumings: - PKA is initialized.
882 * - Length of extended (by word) registers is placed into LenID entry of
883 * sizes table.
884 * - If the extra word of register must be cleared also the user must
885 * set LenID according to extended register size
886 *
887 * @return - None.
888 *
889 */
PkaCopyDataIntoPkaReg(uint32_t dstReg,uint32_t lenId,const uint32_t * src_ptr,uint32_t sizeWords)890 void PkaCopyDataIntoPkaReg(uint32_t dstReg, /*!< [out] Virtual address (number) of destination register. */
891 uint32_t lenId, /*!< [in] ID of entry of regsSizesTable defines registers length with word extension. */
892 const uint32_t *src_ptr, /*!< [in] Pointer to source buffer. */
893 uint32_t sizeWords ) /*!< [in] Data size in words. */
894 {
895 uint32_t currAddr;
896 uint32_t regSize;
897
898 /* copy data from src buffer into PKA register with 0-padding *
899 * in the last PKA-word */
900 PKA_GET_REG_ADDRESS(dstReg, currAddr);
901 PKA_HW_LOAD_BLOCK_TO_PKA_MEM(currAddr, src_ptr, sizeWords);
902
903 /* data size aligned to full PKA-word */
904 sizeWords = ((sizeWords+PKA_WORD_SIZE_IN_32BIT_WORDS-1)/PKA_WORD_SIZE_IN_32BIT_WORDS) * \
905 PKA_WORD_SIZE_IN_32BIT_WORDS;
906 currAddr = currAddr + sizeWords;
907
908 /* register size in words */
909 PKA_GET_REG_SIZE(regSize, lenId);
910 regSize = CALC_FULL_32BIT_WORDS(regSize);
911
912 /* zeroe not significant high words of the register */
913 if (regSize > sizeWords) {
914 PKA_HW_CLEAR_PKA_MEM(currAddr, regSize - sizeWords);
915 }
916
917 #if defined PKA_DEBUG && defined DEBUG
918 /*! PKA_DEBUG */
919 PkaCopyDataFromPkaReg(tempRes, regSize, dstReg);
920 #endif
921 return;
922 }
923
924
925 /*********** PkaFinishPka function **********************/
926 /**
927 * @brief This function disables PKA clock .
928 *
929 * @return - None.
930 *
931 */
PkaFinishPka(void)932 void PkaFinishPka(void)
933 {
934 /* disable the PKA clocks */
935 CC_HAL_WRITE_REGISTER( CC_REG_OFFSET(CRY_KERNEL,PKA_CLK_ENABLE) , 0x0UL );
936 return;
937 }
938
939
940 /*********** PkaClearPkaRegWords function **********************/
941 /**
942 * @brief This function clears words in a PKA register .
943 *
944 * @return - None.
945 *
946 */
PkaClearPkaRegWords(uint32_t pkaReg,uint32_t addrWordOffset)947 void PkaClearPkaRegWords(uint32_t pkaReg, /*!< [in/out] Virtual address (number) of the register. */
948 uint32_t addrWordOffset ) /*!< [in] Word offset to start clearing. */
949 {
950 uint32_t currAddr;
951 uint32_t regSize;
952
953 /* copy data from src buffer into PKA register with 0-padding *
954 * in the last PKA-word */
955 PKA_GET_REG_ADDRESS(pkaReg, currAddr);
956 currAddr = currAddr + addrWordOffset;
957
958 /* register size in words */
959 PKA_GET_REG_SIZE(regSize, LEN_ID_MAX_BITS);
960 regSize = CALC_FULL_32BIT_WORDS(regSize);
961
962 /* zeroe not significant high words of the register */
963 if (regSize > addrWordOffset) {
964 PKA_HW_CLEAR_PKA_MEM(currAddr, regSize - addrWordOffset);
965 }
966
967 return;
968 }
969
970
971 /*********** PkaIsRegModEqual function **********************/
972 /**
973 * The function returns result (x == y mod n).
974 * Assumed: n - in reg. 0, lenId = 1.
975 *
976 * @author reuvenl (6/20/2014)
977 *
978 * @return True if equal, otherwise false
979 */
PkaIsRegModEqual(uint32_t reg1,uint32_t reg2,uint32_t regTmp1,uint32_t regTmp2)980 bool PkaIsRegModEqual(uint32_t reg1, /*!< [in] Virtual address (number) of the register1. */
981 uint32_t reg2, /*!< [in] Virtual address (number) of the register2. */
982 uint32_t regTmp1, /*!< [in] Virtual address (number) of the tmp register1. */
983 uint32_t regTmp2) /*!< [in] Virtual address (number) of the tmp register2. */
984 {
985 uint32_t status;
986
987 PKA_REDUCE(LEN_ID_N_BITS, reg1, regTmp1);
988 PKA_REDUCE(LEN_ID_N_BITS, reg2, regTmp2);
989 PKA_COMPARE_STATUS(LEN_ID_N_PKA_REG_BITS, regTmp1, regTmp2, status);
990 return(bool)(status==1);
991 }
992
993
994 /*********** PkaGetBitFromPkaReg function **********************/
995 /**
996 * @brief This function returns bit i from PKA register.
997 *
998 * @return - returns the bit number i (counting from left).
999 *
1000 */
PkaGetBitFromPkaReg(uint32_t rX,uint32_t LenID,int32_t i,uint32_t rT)1001 uint8_t PkaGetBitFromPkaReg(uint32_t rX, /*!< [in] Virtual pointer to PKA register. */
1002 uint32_t LenID, /*!< [in] ID of entry of regsSizesTable containing rX register length
1003 with word extension. */
1004 int32_t i, /*!< [in] Number of bit to be tested. */
1005 uint32_t rT) /*!< [in] Temp register. If it is not necessary to keep rX, then
1006 set rT=rX for saving memory space. */
1007 {
1008 uint32_t j;
1009 uint32_t numWords, numBits; /* number shifts by word and by bit */
1010 uint32_t bitVal;
1011
1012 /* copy extended rX=>rT */
1013 if (rX != rT)
1014 PKA_COPY(LEN_ID_MAX_BITS, rT/*dst*/, rX/*src*/);
1015
1016 /* number shifts */
1017 numWords = i / CC_BITS_IN_32BIT_WORD;
1018 numBits = i % CC_BITS_IN_32BIT_WORD;
1019
1020 /* shift by words */
1021 for (j = 0; j < numWords; j++) {
1022 PKA_SHR_FILL0(LenID+1, rT/*Result*/, rT/*N*/, CC_BITS_IN_32BIT_WORD-1/*S*/);
1023 }
1024
1025 /* shift by bits */
1026 if (numBits >= 1)
1027 PKA_SHR_FILL0(LenID+1, rT/*Result*/, rT/*N*/, numBits-1/*S*/);
1028
1029 /* test LS Bit */
1030 PKA_READ_BIT0( LenID+1, rT/**/, bitVal);
1031 return(bitVal);
1032
1033
1034 }
1035
1036
1037 /*********** PkaExecFullModInv function **********************/
1038 /**
1039 * @brief This function calculates modular inversion Res = 1/B mod N for both odd and even modulus.
1040 *
1041 * The function works with virtual pointers to PKA registers (sequence numbers)
1042 * and does the following:
1043 *
1044 * 1. Checks the parity of modulus N (in register 0) and operand B. If they both are even,
1045 * returns an error (inverse is not exist)
1046 * 2. If the modulus is odd, then calls the LLF_PKI_PKA_ModInv function for calculating
1047 * the inverse.
1048 * 3. If the modulus is even, then the function performs the following:
1049 * 3.1 Saves modulus N: rT0<=N;
1050 * 3.2. Sets B into reg N: N<=B.
1051 * 3.3. Res = N^-1 mod B (call LLF_PKI_PKA_ModInv ); Restore mod: N<=rT0;
1052 * 3.4. rT0 = high(N*N^-1) = LLF_PKI_PKA_HMul(N,Res,rT0);
1053 * 3.5. Shift right rT0 >> 32;
1054 * 3.6. rT1 = low(N*N^-1) = LLF_PKI_PKA_LMul(N,Res,rT1);
1055 * 3.7. Res = rT0 / B : call LLF_PKI_PKA_LongDiv(rT0,B,Res);
1056 * 3.7. rT0 = rT1 / B : call LLF_PKI_PKA_Div(rT1,B,rT0);
1057 * 3.8. Res = Res + rT0 : ModAdd(Res,rT0,Res);
1058 * 3.9. If reminder of division > 0, then Res= Res+1;
1059 * 3.10. Res = N-Res;
1060 * 4. Exit.
1061 *
1062 * NOTE:
1063 * - The operand B shal be rewritten by GCD(N,B).
1064 * - The function needs 6 PKA regs: N(0), OpB, Res, rT0, rT1, rT2.
1065 * - PKA sizes table entrys must be set: 0 - exact modSizeBits, 1 - modSizeBits+32 bits,
1066 * - Before executing modular operations, the modulus must be set into r0 register of PKA.
1067 * - The function not checks the input parameters, because they must be checked previously.
1068 *
1069 * @return CC_OK On success, otherwise indicates failure
1070 */
PkaExecFullModInv(int8_t OpB,int8_t Res,int8_t rT0,int8_t rT1,int8_t rT2,int8_t rT3)1071 CCError_t PkaExecFullModInv(int8_t OpB, /*!< [in] Operand B: virtual register pointer. Valid values: 0 <= OpA <= 31. */
1072 int8_t Res, /*!< [out] Virtual register pointer for result data. Valid values: 0 <= Res <= 31. */
1073 int8_t rT0, /*!< [in] The virtual pointers to temp register. */
1074 int8_t rT1, /*!< [in] The virtual pointers to temp register. */
1075 int8_t rT2, /*!< [in] The virtual pointers to temp register. */
1076 int8_t rT3) /*!< [in] The virtual pointers to temp register. */
1077 {
1078 CCError_t error = CC_OK;
1079 uint32_t ModSizeBits, ModSizeWords;
1080 uint32_t status;
1081 uint32_t bitVal;
1082 /* virtual pointer to modulus register, by default: N=0 */
1083 uint8_t N = PKA_REG_N;
1084
1085 /* get modulus size */
1086 PKA_GET_REG_SIZE(ModSizeBits, LEN_ID_N_BITS);
1087 ModSizeWords = CALC_FULL_32BIT_WORDS(ModSizeBits);
1088
1089 /* Step 1. Check the parity of the modulus */
1090 /* test: is the modulus even? */
1091 PKA_READ_BIT0(LEN_ID_N_PKA_REG_BITS, PKA_REG_N/*N*/, bitVal);
1092 if (bitVal == 1 /*odd N*/) {
1093 /* Step 2. Process case of odd modulus */
1094 PKA_MOD_INV(LEN_ID_N_BITS, Res, OpB);
1095 } else { /*even N*/
1096 /* Step 3. Process case of even modulus */
1097 /* in case of even B: calculate GCD and return error message, */
1098 /* that inverse does not exists */
1099 /* check, is the operand B odd or even */
1100 PKA_READ_BIT0(LEN_ID_N_PKA_REG_BITS, OpB, bitVal);
1101 if (bitVal == 0) {
1102 return PKA_INVERSION_NOT_EXISTS_ERROR;
1103 }
1104
1105 /* in case of odd B: calculate modular inverse and GCD */
1106 /* 3.1. Save previous modulus also into rT0 and into rT1 (rT1 - working copy)*/
1107 PKA_COPY(LEN_ID_MAX_BITS/*LenID*/, rT0/*OpDest*/, N/*OpSrc*/);
1108 PKA_COPY(LEN_ID_MAX_BITS/*LenID*/, rT1/*OpDest*/, N/*OpSrc*/);
1109
1110 /* 3.2. Set OpB into modulus register 0 ) */
1111 PKA_COPY(LEN_ID_MAX_BITS/*LenID*/, N/*OpDest*/, OpB/*OpSrc*/);
1112
1113 /* 3.3 Calculate Res = 1/N mod B */
1114 PKA_MOD_INV(LEN_ID_N_BITS/*LenID*/, Res, rT1/*mod N*/);
1115
1116
1117 /* restore modulus */
1118 PKA_COPY(LEN_ID_MAX_BITS/*LenID*/, N/*OpDest*/, rT0/*OpSrc*/);
1119
1120 /* 3.4. Calculate rT0 = PKA_MUL_HIGH(N*Res) i.e. HighHalf + 1 word of(N*Res)
1121 Note: LenId=0, because this operation adds extra word itself */
1122 PKA_MUL_HIGH(LEN_ID_N_BITS, rT0/*Result*/, N, Res);
1123
1124
1125 /* 3.5. Shift right rT0 for deleting 1 low word - no need in new HW */
1126
1127 /* 3.6. Calculate rT2 = PKA_MUL_LOW(N*Res) i.e. LowHalf of(N*Res) */
1128 PKA_MUL_LOW(LEN_ID_N_BITS, rT2/*Result*/, N, Res);
1129
1130 /* 3.6. Divide long num Res = (rT1 * 2**(ModSizeBits - 32))/B */
1131 error = PkaDivLongNum(LEN_ID_N_BITS, /*LenID of exact size*/
1132 rT0, /*numerator*/
1133 CC_BITS_IN_32BIT_WORD*ModSizeWords+CC_BITS_IN_32BIT_WORD, /*Shift*/
1134 OpB, /*divider*/
1135 Res, /*result*/
1136 rT1,
1137 rT3);
1138
1139 if (error != CC_OK) {
1140 return error;
1141 }
1142
1143 /* 3.7. Subtract 1 from low part and divide it by B */
1144 PKA_SUB_IM(LEN_ID_N_PKA_REG_BITS, rT2/*Result*/, rT2/*numerat*/, 1/*OpB*/);
1145 PKA_DIV(LEN_ID_N_PKA_REG_BITS, rT0/*Result*/, rT2/*numerat*/, OpB/*divider*/);
1146
1147 /* 3.8. Calculate: Res = Res+rT0, Res=Res+1, Res = N - Res; */
1148 PKA_ADD(LEN_ID_N_PKA_REG_BITS, Res, Res, rT0);
1149
1150 /* 3.9. If remainder rT2 is not 0, then add 1 to rT0 result */
1151 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rT2/*OpA*/, 0/*OpB*/, status);
1152 if (status != 1) {
1153 PKA_ADD_IM(LEN_ID_N_PKA_REG_BITS, Res, Res, 1 );
1154 }
1155 /* 3.10. Res = N - Res; */
1156 PKA_SUB(LEN_ID_N_PKA_REG_BITS, Res, N, Res);
1157 }
1158
1159 return error;
1160 }
1161
1162
1163
1164
1165