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