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_pal_mutex.h"
10 #include "cc_hal_plat.h"
11 #include "cc_sram_map.h"
12 #include "dx_crys_kernel.h"
13 #include "cc_common.h"
14 #include "cc_common_math.h"
15 #include "pka_hw_defs.h"
16 #include "pki.h"
17 #include "ec_wrst.h"
18 #include "pka_hw_defs.h"
19 #include "pka.h"
20 #include "pka_error.h"
21 #ifdef DEBUG
22         #include <assert.h>
23 #endif
24 
25 extern const int8_t regTemps[PKA_MAX_COUNT_OF_PHYS_MEM_REGS];
26 
27 #if defined PKA_DEBUG && defined DEBUG
28 uint32_t tempRes[PKA_MAX_REGISTER_SIZE_IN_32BIT_WORDS];
29 uint32_t tempRes1[PKA_MAX_REGISTER_SIZE_IN_32BIT_WORDS];
30 #endif
31 
32 
33 /***********    PkiCalcNp  function      **********************/
34 /**
35  * The function uses physical data pointers to calculate and output
36  * the Barrett tag Np.
37  *
38  *  For RSA it uses truncated sizes:
39  *      Np = truncated(2^(3*A+3*X-1) / ceiling(n/(2^(N-2*A-2*X)));
40  *  For ECC - full sizes of not truncated input arguments:
41  *      Np = truncated(2^(N+A+X-1) / n);
42  *
43  * @author reuvenl (5/1/2014)
44  *
45  * @return  CC_OK On success, otherwise indicates failure
46  */
PkiCalcNp(uint32_t * pNp,uint32_t * pN,uint32_t sizeNbits)47 CCError_t  PkiCalcNp(uint32_t *pNp, /*!< [out] The pointer to the Barrett tag Np buffer. If pNp = Null,
48                             the function not outputs calculated Np. */
49                         uint32_t *pN,       /*!< [out] The pointer to the modulus n. */
50                         uint32_t  sizeNbits)    /*!< [in] The exact size of the modulus. */
51 {
52         CCError_t err = 0;
53         uint32_t  A = CC_PKA_WORD_SIZE_IN_BITS;
54         uint32_t  X = PKA_EXTRA_BITS;
55         uint32_t pkaReqRegs = 6;
56         int32_t wN, wNp;
57 
58         /* usage of PKA registers */
59         int8_t  rN = PKA_REG_N;
60         int8_t  rNp = PKA_REG_NP;
61         int8_t  rT2 = regTemps[2];
62         int8_t  rT4 = regTemps[4];
63 
64         /* Calc. sizes of modulus in words and reminder in bits */
65         wN = CALC_FULL_32BIT_WORDS(sizeNbits);
66         wNp = CALC_FULL_32BIT_WORDS(A + X - 1);
67 
68         err = PkaInitAndMutexLock(sizeNbits, &pkaReqRegs);
69         if (err != CC_SUCCESS) {
70                 CC_PalAbort("Fail to acquire mutex\n");
71         }
72         /* Set modulus in T1 */
73         PkaCopyDataIntoPkaReg(rN/*dstReg*/, LEN_ID_MAX_BITS/*lenId*/, pN/*src_ptr*/, wN);
74         err = PkaCalcNpIntoPkaReg(LEN_ID_N_BITS, sizeNbits, rN /* regN */, rNp /* regNp */, rT2, rT4);
75         if (err != CC_SUCCESS) {
76                 goto End;
77         }
78         /* Output Np */
79         PkaCopyDataFromPkaReg(pNp/*dst_ptr*/, wNp, rNp/*srcReg*/);
80 End:
81         PkaFinishAndMutexUnlock(pkaReqRegs);
82 
83 
84         return err;
85 }
86 
87 
88 /***********    PkiLongNumDiv   function      **********************/
89 /**
90  * @brief  This function performs division of big numbers, passed by physical pointers,
91  *              using the PKA.
92  *              .
93  *     Computes modRes = A mod B. divRes_ptr = floor(A/B)
94  *     Lengths: A[ALen], B[BLen], modRes[BLen], divRes[ALen].
95  *     Assumes:  c > 0.
96  *
97  *     PKA registers using: A=>r2, B=>r3, divRes=>r4, modRes=>r2 (r2 is rewritten by remainder).
98  *
99  * Author: R.Levin
100  *
101  * Last Revision: 1.00.00
102  *
103  * @return  CC_OK On success, otherwise indicates failure
104  *
105  * Update History:
106  * Rev 1.00.00, Date 4 Feb. 2008,
107  *
108  */
PkiLongNumDiv(uint32_t * pNumA,uint32_t numASizeInWords,uint32_t * pNumB,uint32_t numBSizeInWords,uint32_t * pModRes,uint32_t * pDivRes)109 CCError_t  PkiLongNumDiv(uint32_t *pNumA,        /*!< [in] The pointer to numerator A vector. */
110                            uint32_t numASizeInWords,  /*!< [in] Length of numerator A in words.*/
111                            uint32_t *pNumB,        /*!< [in] The pointer to divider B (modulus).*/
112                            uint32_t numBSizeInWords,  /*!< [in] The size of B vector in words.*/
113                            uint32_t *pModRes,   /*!< [out] The pointer to modulus result (reminder of division). */
114                            uint32_t *pDivRes)   /*!< [out] The pointer to result of division.*/
115 {
116         CCError_t error = CC_OK;
117         uint32_t  opSizeWords;
118         uint32_t status;
119         uint32_t pkaReqRegs = 6;
120     int8_t  rT2 = regTemps[2];
121         int8_t  rT3 = regTemps[3];
122         int8_t  rT4 = regTemps[4];
123 
124 
125         opSizeWords = CC_MAX(numASizeInWords, numBSizeInWords);
126 
127         error = PkaInitAndMutexLock(CC_BITS_IN_32BIT_WORD*opSizeWords, &pkaReqRegs);
128         if (error != CC_OK) {
129                 return error;
130         }
131 
132         /* copying all needed data into PKA memory before starting PKA operations */
133         /* A=>r2, B=>r3,                                                          */
134         /* copy numerator into PKA register: A=>r2 */
135         PkaCopyDataIntoPkaReg( rT2/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pNumA/*src_ptr*/, numASizeInWords);
136 
137         /* copy divisor into PKA register: B=>r3 */
138         PkaCopyDataIntoPkaReg( rT3/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pNumB/*src_ptr*/, numBSizeInWords);
139 
140         /* check, that divisor is not null, else return error */
141         PKA_ADD_IM( LEN_ID_N_PKA_REG_BITS/*LenID*/, rT4/*Res*/, rT3/*OpA*/, 0/*Imm OpB*/);
142         PKA_GET_STATUS_ALU_OUT_ZERO(status);
143         if (status == 1) {
144                 error = PKA_DIVIDER_IS_NULL_ERROR;
145                 goto End;
146         }
147 
148         /* division in PKA: quotient: r4 = r2 / r3; remainder: r2 = r2 % r3        */
149         PKA_DIV( LEN_ID_N_PKA_REG_BITS/*LenID*/, rT4/*Res*/, rT2/*OpA*/, rT3/*OpB*/);
150 
151 
152         /*        output the results                                               */
153         if (pDivRes != NULL) {
154                 PkaCopyDataFromPkaReg(pDivRes,  numASizeInWords, rT4/*srcReg*/);
155         }
156 
157         if (pModRes != NULL) {
158                 PkaCopyDataFromPkaReg(pModRes,  numBSizeInWords, rT2/*srcReg*/);
159         }
160 
161 End:
162         PkaFinishAndMutexUnlock(pkaReqRegs);
163 
164         return error;
165 
166 }
167 
168 
169 /***********     PkiLongNumMul  function     **********************/
170 /**
171  * @brief This function performs multiplication of big numbers, passed by physical
172  *              pointers, using the PKA.
173  *
174  *        The RMul operation is : (A * B)
175  *
176  *        The function performs the following algorithm:
177  *
178  * @return  CC_OK On success, otherwise indicates failure
179  */
PkiLongNumMul(uint32_t * pNumA,uint32_t numASizeInBits,uint32_t * pNumB,uint32_t * pRes)180 CCError_t PkiLongNumMul(uint32_t *pNumA ,      /*!< [in] The pointer of A words array (LS word is left most). */
181                           uint32_t  numASizeInBits, /*!< [in] The size of vectors in bits. */
182                           uint32_t *pNumB ,      /*!< [in] The pointer of B words array (LS word is left most). */
183                           uint32_t *pRes)    /*!< [out] The pointer to the result buffer. */
184 {
185         CCError_t error = CC_OK;
186         uint32_t  OpSizeInWords;
187         uint32_t pkaReqRegs = 6;
188         int8_t  rT2 = regTemps[2];
189         int8_t  rT3 = regTemps[3];
190         int8_t  rT4 = regTemps[4];
191 
192 #ifdef LLF_PKI_PKA_DEBUG
193         /* check the operands size, used for RSA only */
194         if (2*numASizeInBits > (CC_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS+CC_PKA_WORD_SIZE_IN_BITS)) {
195                return PKA_ILLEGAL_OPERAND_LEN_ERROR;
196     }
197 #endif
198 
199         /* set operation size in words */
200         if (CALC_FULL_32BIT_WORDS(2*numASizeInBits) < CALC_FULL_32BIT_WORDS(PKA_MIN_OPERATION_SIZE_BITS))
201                 OpSizeInWords = CALC_FULL_32BIT_WORDS(PKA_MIN_OPERATION_SIZE_BITS);
202 
203         else
204                 OpSizeInWords = CALC_FULL_32BIT_WORDS(2*numASizeInBits);
205 
206 
207         error = PkaInitAndMutexLock(CC_BITS_IN_32BIT_WORD*OpSizeInWords, &pkaReqRegs);
208         if (error != CC_OK) {
209                 return error;
210         }
211 
212         /* copying all needed data into PKA memory before starting PKA operations */
213         /* A=>r2, B=>r3,                                                          */
214         /* copy A into PKA register: A=>r2 */
215         PkaCopyDataIntoPkaReg(rT2/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pNumA/*src_ptr*/,
216                                CALC_FULL_32BIT_WORDS(numASizeInBits));
217 
218         /* copy B into PKA register: B=>r2 */
219         PkaCopyDataIntoPkaReg(rT3/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pNumB/*src_ptr*/,
220                                CALC_FULL_32BIT_WORDS(numASizeInBits));
221 
222 
223         /* multiply in PKA:  r4 = r2 * r3; */
224         PKA_MUL_LOW(LEN_ID_N_PKA_REG_BITS/*lenId*/, rT4/*Res*/, rT2/*OpA*/, rT3/*OpB*/);
225 
226         /* output the results */
227         PkaCopyDataFromPkaReg(pRes, OpSizeInWords, rT4/*srcReg*/ );
228 
229         PkaFinishAndMutexUnlock(pkaReqRegs);
230 
231 
232         return error;
233 }
234 
235 
236 /***********     PkiConditionalSecureSwapUint32  function     **********************/
237 /**
238  * @brief The function performs conditional swapping of two values in secure
239  *  mode
240  *
241  *  if(swp == 1) {tmp = *x; *x = *y; *y = tmp;}
242  *
243  * @return None
244  */
PkiConditionalSecureSwapUint32(uint32_t * x,uint32_t * y,uint32_t swp)245 void PkiConditionalSecureSwapUint32(uint32_t *x,    /*!< [in/out] the pointer to x-variable. */
246                     uint32_t *y,    /*!< [in/out] the pointer to y-variable. */
247                     uint32_t swp)   /*!< [in] swapping condition [0,1]. */
248 {
249         int32_t tmpX = *x;
250         int32_t tmpY = *y;
251         int32_t tmp  = tmpX ^ tmpY;
252 
253         swp = -swp;
254         tmp &= swp;
255         *x = tmpX ^ tmp;
256         *y = tmpY ^ tmp;
257 }
258 
259 
260 /***********     PkiClearAllPka  function     **********************/
261 /**
262  * @brief This function clears the PKA memory.
263  *
264  * @return  None
265  */
PkiClearAllPka(void)266 void PkiClearAllPka(void)
267 {
268         uint32_t pkaRegCount = PKA_MAX_COUNT_OF_PHYS_MEM_REGS;
269         uint32_t regSizeInBits = ((CC_PKA_SRAM_SIZE_IN_KBYTES*CC_1K_SIZE_IN_BYTES*CC_BITS_IN_BYTE)/PKA_MAX_COUNT_OF_PHYS_MEM_REGS)-CC_PKA_WORD_SIZE_IN_BITS;
270 
271         if (PkaInitAndMutexLock(regSizeInBits, &pkaRegCount) != CC_SUCCESS) {
272                 return;
273         }
274 
275         PkaFinishAndMutexUnlock(pkaRegCount);
276         return;
277 
278 }
279 
280 /*!< get next two bits of scalar*/
PkiGetNextTwoMsBits(uint32_t * pScalar,uint32_t * pWord,int32_t i)281 uint32_t PkiGetNextTwoMsBits(uint32_t *pScalar, uint32_t *pWord, int32_t i)
282 {
283         uint32_t twoBits = 0;
284         //        twoBits = (*pWord >> (i & (CC_BITS_IN_32BIT_WORD - 1))) & 3;
285         twoBits = (*pWord >> (CC_BITS_IN_32BIT_WORD - 2));
286         /* get next bit of scalar */
287         if ((i % CC_BITS_IN_32BIT_WORD) != 0) {
288                 *pWord <<= 2;
289         } else {
290                 *pWord = pScalar[(i / CC_BITS_IN_32BIT_WORD)-1];
291         }
292         //        i--;
293 
294         return twoBits;
295 }
296 
297 
298 /*!< the function checks is array equal to 0: *
299 *    if arr == 0, then return 0, else 1.      */
PkiIsUint8ArrayEqualTo0(const uint8_t * arr,size_t size)300 bool PkiIsUint8ArrayEqualTo0(const uint8_t *arr, size_t size)
301 {
302         uint32_t i;
303         uint8_t  s = 0;
304         for (i = 0; i < size; i++)
305                 s |= arr[i];
306         /* if(arr == 0) return 1, else 0. */
307         return !(bool)((0UL - s) >> 31);
308 
309 }
310 
311 /*!< the function compares equality of two buffers of same size:
312      if they are equal - return 0, else 1. */
PkiAreBuffersEqual(const void * buff1,const void * buff2,size_t sizeInBytes)313 bool PkiAreBuffersEqual(const void *buff1, const void *buff2, size_t sizeInBytes)
314 {
315         uint32_t i;
316         uint8_t  s = 0;
317         for (i = 0; i < sizeInBytes; i++)
318                 s |= (((uint8_t*)buff1)[i] ^ ((uint8_t*)buff2)[i]);
319         /* if equalled return 0, else 1. */
320         return !(bool)((0UL - s) >> 31);
321 
322 }
323 
324 /************************************************************************/
325 /**
326  * @brief The function copies uint8 big endianness data into PKA register.
327  *
328  *  Notes: Assumed all parameters are checked before calling this function.
329  *         PKA registers used: dstReg.
330  *         The size of pTemp buffer is at least PKA register size (appropriate to
331  *         register size lenID) and dataSizeBytes <= temp buffer size (in bytes).
332  *
333  * @return  no return value
334  */
PkaCopyBe8DataIntoPkaReg(uint32_t dstReg,uint32_t lenId,const uint8_t * pSrc,uint32_t dataSizeBytes,uint32_t * pTemp)335 void PkaCopyBe8DataIntoPkaReg(uint32_t  dstReg,       /* [out] virtual pointer to destination PKA register. */
336                  uint32_t lenId,          /* [in] PKA register length ID.*/
337                  const uint8_t *pSrc,     /* [in] pointer to source buffer. */
338                  uint32_t dataSizeBytes,  /* [in] size of the data in bytes */
339                  uint32_t *pTemp)         /* [in] pointer to the temp buffer of
340                                              size >= PKA SRAM register size. */
341 {
342     uint32_t  regSizeBits, regSizeWords;
343 //  uint32_t currAddr, word, dataSizeWords;
344 //  int32_t i, j = 0;
345 
346     PKA_GET_REG_SIZE(regSizeBits, lenId);
347     regSizeWords = CALC_FULL_32BIT_WORDS(regSizeBits); /*size in words*/
348 
349 //  CC_CommonConvertMsbLsbBytesToLswMswWords(pTemp, regSizeWords*CC_32BIT_WORD_SIZE, pSrc, dataSizeBytes);
350     CC_PalMemSetZero((uint8_t*)pTemp + dataSizeBytes, regSizeWords*CC_32BIT_WORD_SIZE - dataSizeBytes);
351     CC_CommonReverseMemcpy((uint8_t*)pTemp, (uint8_t*)pSrc, dataSizeBytes);
352 //  dataSizeWords = CALC_32BIT_WORDS_FROM_BYTES(dataSizeBytes);
353     PkaCopyDataIntoPkaReg(dstReg, lenId, pTemp, regSizeWords);
354 
355 //  dataSizeWords = CALC_32BIT_WORDS_FROM_BYTES(dataSizeBytes);
356 //  PKA_GET_REG_ADDRESS(dstReg, currAddr);
357 //
358 //  if(i > 3) {
359 //      for(i = dataSizeBytes-1; i > 0; i -= 4, j++) {
360 //          word = (pSrc[i] << 24) | (pSrc[i-1] << 16) |
361 //                 (pSrc[i-2] << 8) | pSrc[i-3];
362 //          PKA_HW_LOAD_VALUE_TO_PKA_MEM(currAddr, word);
363 //          currAddr += CC_32BIT_WORD_SIZE;
364 //      }
365     return;
366 }
367 
368 
369 /************************************************************************/
370 /**
371  * @brief The function copies data from PKA register into uint8 buffer in big endianness order.
372  *
373  *  Notes: Assumed all parameters are checked before calling this function.
374  *         PKA registers used: srcReg.
375  *         The size (in 32-bit words) of pTemp buffer is at least the data size,
376  *         in words (rounded up).
377  *
378  * @return  no return value
379  */
PkaCopyDataFromPkaRegToBe8Buff(uint8_t * pDst,uint32_t srcReg,uint32_t sizeBytes,uint32_t * pTemp)380 void PkaCopyDataFromPkaRegToBe8Buff(
381             uint8_t  *pDst,      /* [out] pointer to the destination buffer of size >= sizeBytes. */
382             uint32_t  srcReg,    /* [in] virtual pointer to source PKA register. */
383             uint32_t  sizeBytes, /* [in] size of the data in PKA register in bytes */
384             uint32_t  *pTemp)    /* [in] pointer to the temp buffer of size (in bytes) >= sizeBytes. */
385 {
386     PkaCopyDataFromPkaReg(pTemp, CALC_32BIT_WORDS_FROM_BYTES(sizeBytes), srcReg);
387     CC_CommonReverseMemcpy(pDst, (uint8_t*)pTemp, sizeBytes);
388 
389     return;
390 }
391 
392 
393 
394 /***********     PkiExecExpBe  function      **********************/
395 /**
396  * @brief Executes the modular exponentiation using PKA for BE input parameters.
397  *
398  *  The function input/output arrays are in big endianness order of bytes.
399  *
400  *  Notes: Assumed all parameters are checked before calling this function.
401  *         All sizes aligned to 32-bit words, leading zeros are present if exist.
402  *         PKA registers used: r0,r1,r2,r3,r4, r30,r31.
403  *         The size of pTemp buffer should be at least modulus size plus 2*PKA_WORD_SIZE,
404  *         where all sizes are rounded up to uint32 size.
405  *
406  * @return  no return value
407  */
PkiExecModExpBe(uint8_t * pOut,uint8_t * pIn,uint32_t inSizeBytes,uint8_t * pMod,uint32_t modSizeBits,uint8_t * pExp,uint32_t expSizeBytes,uint32_t * pTemp)408 CCError_t  PkiExecModExpBe(
409                 uint8_t *pOut,        /* [out] pointer to the exponentiation result with size >= modulus size (in bytes),
410                                                equaled to modulus size in bytes (including leading zeros. */
411                 uint8_t *pIn,         /* [in]  pointer to the input data. */
412                 uint32_t inSizeBytes, /* [in]  input data size in bytes */
413                 uint8_t *pMod,        /* [in]  pointer to the modulus. */
414                 uint32_t modSizeBits, /* [in]  modulus size in bits */
415                 uint8_t *pExp,        /* [in]  pointer to the exponent buffer. */
416                 uint32_t expSizeBytes,/* [in]  exponent size in bytes; should be <= modulus size (in bytes). */
417                 uint32_t *pTemp)      /* [in]  pointer to the temp buffer of size >= modulus size. */
418 {
419     CCError_t err = CC_OK;
420     uint32_t modSizeBytes;
421     uint32_t pkaRegsCount = 7;
422         /* define virtual registers pointers  */
423     #define IN_REG  2
424     #define EXP_REG 3
425     #define OUT_REG 4
426 
427 
428     err = PkaInitAndMutexLock(modSizeBits, &pkaRegsCount);
429     if (err != CC_OK) {
430         return err;
431     }
432 
433     modSizeBytes = CALC_FULL_BYTES(modSizeBits);
434 
435     /*  copy modulus into PKA */
436     PkaCopyBe8DataIntoPkaReg(PKA_REG_N/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pMod/*srcPtr*/,
437                          modSizeBytes, pTemp);
438 
439     /* Calculate NP */
440     err =  PkaCalcNpIntoPkaReg(LEN_ID_N_BITS,
441             modSizeBits,  /* [in] The exact size of the modulus. */
442             PKA_REG_N,    /* [in] PKA reg, holding the modulus n. */
443             PKA_REG_NP,   /* [out PKA reg. - Np result. */
444                     IN_REG, OUT_REG);  /* PKA regs, used as temporaries. */
445 
446     if (err != CC_OK) {
447         goto End;
448     }
449 
450 
451         /*  copy the Data and Exponent into PKA registers                  */
452     PkaCopyBe8DataIntoPkaReg(IN_REG/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pIn, inSizeBytes, pTemp);
453     PkaCopyBe8DataIntoPkaReg(EXP_REG/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pExp, expSizeBytes, pTemp);
454 
455         /*  calculate the exponent result: OUT_REG */
456     PKA_MOD_EXP(LEN_ID_N_BITS/*LenID*/, OUT_REG, IN_REG/*OpA*/, EXP_REG/*OpB*/);
457 
458     /* output result as big endiannness bytes array */
459     PkaCopyDataFromPkaRegToBe8Buff(pOut, OUT_REG, modSizeBytes, pTemp);
460 
461 End:
462     /*  Finish PKA and copy result */
463     PkaFinishAndMutexUnlock(pkaRegsCount);
464 
465         /* undef virtual registers pointers  */
466     #undef IN_REG
467     #undef EXP_REG
468     #undef OUT_REG
469 
470     return err;
471 
472 }
473 
474 /***********     PkiExecExpLeW  function      **********************/
475 /**
476  * @brief Executes modular exponentiation using PKA for LE input parameters.
477  *
478  *  The function input/output arrays are given as little endianness words arrays.
479  *
480  *  Notes: Assumed all parameters are checked before calling this function.
481  *         All sizes aligned to 32-bit words, leading zeros are present if exist.
482  *         PKA registers used: r0,r1,r2,r3,r4, r30,r31.
483  *
484  * @return  no return value
485  */
PkiExecModExpLeW(uint32_t * pOut,uint32_t * pIn,uint32_t inSizeWords,uint32_t * pMod,uint32_t modSizeBits,uint32_t * pExp,uint32_t expSizeWords)486 CCError_t  PkiExecModExpLeW(
487                 uint32_t *pOut,         /* [out] pointer to the exponentiation result with size, equalled
488                                                 to modulus size in words (including leading zeros). */
489                 uint32_t *pIn,         /* [in]  pointer to the input data. */
490                 uint32_t inSizeWords,  /* [in]  input data size in words */
491                 uint32_t *pMod,        /* [in]  pointer to the modulus. */
492                 uint32_t modSizeBits,  /* [in]  modulus size in bits */
493                 uint32_t *pExp,        /* [in]  pointer to the exponent buffer. */
494                 uint32_t expSizeWords) /* [in]  exponent size: should be <= modulus size (in words). */
495 {
496     CCError_t err = CC_OK;
497     uint32_t modSizeWords;
498     uint32_t pkaRegsCount = 7;
499         /* define virtual registers pointers  */
500     #define IN_REG  2
501     #define EXP_REG 3
502     #define OUT_REG 4
503 
504 
505     err = PkaInitAndMutexLock(modSizeBits, &pkaRegsCount);
506     if (err != CC_OK) {
507         return err;
508     }
509 
510     modSizeWords = CALC_FULL_32BIT_WORDS(modSizeBits);
511 
512     /*  copy modulus into PKA */
513     PkaCopyDataIntoPkaReg(PKA_REG_N/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/,
514                   pMod/*srcPtr*/, modSizeWords);
515 
516     /* Calculate NP */
517     err =  PkaCalcNpIntoPkaReg(LEN_ID_N_BITS,
518             modSizeBits,  /* [in] The exact size of the modulus. */
519             PKA_REG_N,    /* [in] PKA reg, holding the modulus n. */
520             PKA_REG_NP,   /* [out PKA reg. - Np result. */
521             IN_REG, OUT_REG);  /* PKA regs, used as temporaries. */
522     if(err) {
523           goto End;
524     }
525 
526     /*  copy the Data and Exponent into PKA registers  */
527     PkaCopyDataIntoPkaReg(IN_REG/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pIn, inSizeWords);
528     PkaCopyDataIntoPkaReg(EXP_REG/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pExp, expSizeWords);
529 
530         /*  calculate the exponent result: OUT_REG */
531     PKA_MOD_EXP(LEN_ID_N_BITS/*LenID*/, OUT_REG, IN_REG/*OpA*/, EXP_REG/*OpB*/);
532 
533     /* output result as big endiannness bytes array */
534     PkaCopyDataFromPkaReg(pOut, modSizeWords, OUT_REG);
535 
536 End:
537     /*  Finish PKA and copy result */
538     PkaFinishAndMutexUnlock(pkaRegsCount);
539 
540         /* undef virtual registers pointers  */
541     #undef IN_REG
542     #undef EXP_REG
543     #undef OUT_REG
544 
545     return err;
546 
547 }
548 
549 
550 
551