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_common_math.h"
9 #include "pki.h"
10 #include "pka_ec_wrst.h"
11 #include "pka_error.h"
12 #include "pki_dbg.h"
13 
14 /* temp buffers used for debugging of PKA operations */
15 #if defined PKA_DEBUG && defined DEBUG
16 
17 uint32_t tempRes[PKA_MAX_REGISTER_SIZE_IN_32BIT_WORDS];
18 uint32_t tempRes1[PKA_MAX_REGISTER_SIZE_IN_32BIT_WORDS];
19 
20 /***********     PkiDbgPrintReg  function     **********************/
21 /**
22  * @brief The function prints label and PKA register as big endian bytes array.
23  *
24  * @author reuvenl (8/25/2013)
25  *
26  * @return  None
27  */
PkiDbgPrintReg(const char * label,const uint32_t reg)28 void PkiDbgPrintReg(const char*  label,  /*!< [in] Label string. */
29                    const uint32_t reg)   /*!< [in] Register virt. pointer. */
30 {
31         uint32_t tmp[PKA_MAX_REGISTER_SIZE_IN_32BIT_WORDS] = {0};
32         uint32_t sizeBits;
33         uint32_t sizeBytes;
34         uint32_t sizeWords;
35         int32_t i;
36 
37         if (reg > PKA_REG_T1) {
38                 PKA_PRINTF("Can't print reg %d, reg is too big \n", reg);
39                 exit(1);
40         }
41         sizeBits = PkaGetRegEffectiveSizeInBits(reg);
42         sizeBytes = CALC_FULL_BYTES(sizeBits);
43         sizeWords = CALC_FULL_32BIT_WORDS(sizeBits);
44         if ((sizeBytes > sizeof(tmp)) ||
45             ((sizeBits == 0) && (reg < PKA_REG_T0))) {
46                 PKA_PRINTF("Can't print reg %d, size in %d\n", reg, sizeBytes);
47         }
48         PkaCopyDataFromPkaReg(tmp, sizeWords, reg);
49 
50         PKA_PRINTF("%s [%d] ", label, sizeBits);
51         for (i=(sizeBytes - 1); i>=0; i--) {
52                 PKA_PRINTF("%02X", ((uint8_t*)tmp)[i] & 0xFF);
53         }
54         PKA_PRINTF("\n");
55 }
56 
57 
58 /***********     PkiDbgPrintUint32BuffAsNum  function     **********************/
59 /**
60  * @brief This The function prints the label and 32-bit words buffer (LS-word is
61  *  a left most) as a big hexadecimal number (MS-digit is a left most).
62  *
63  * @author reuvenl (8/25/2013)
64  *
65  * @return  None
66  */
PkiDbgPrintUint32BuffAsNum(const char * label,const uint32_t * pBuf,uint32_t sizeWords)67 void PkiDbgPrintUint32BuffAsNum(const char     *label, /*!< [in] Label string. */
68                      const uint32_t *pBuf,  /*!< [in] 32-bit words buffer to print. */
69                      uint32_t  sizeWords)   /*!< [in] size of pBuff in 32-bit words. */
70 {
71         uint32_t sizeBits;
72         int32_t i;
73 
74         sizeBits = CC_CommonGetWordsCounterEffectiveSizeInBits(pBuf, sizeWords);
75 
76         PKA_PRINTF("%s [%d] ", label, sizeBits);
77         for (i=(sizeWords - 1); i>=0; i--) {
78                 PKA_PRINTF("%08X", pBuf[i]);
79         }
80         PKA_PRINTF("\n");
81 }
82 
83 /***********     PkiDbgPrintUint8BuffAsNum  function     **********************/
84 /**
85  * @brief This The function prints the label and bytes array (LS-byte is
86  *  a left most) as a big hexadecimal number (MS-digit is a left most).
87  *
88  * @author reuvenl (14/02/2016)
89  *
90  * @return  None
91  */
PkiDbgPrintUint8BuffAsNum(const char * label,const uint8_t * pBuf,uint32_t sizeBytes)92 void PkiDbgPrintUint8BuffAsNum(const char     *label, /*!< [in] Label string. */
93                      const uint8_t *pBuf,  /*!< [in] 32-bit words buffer to print. */
94                      uint32_t  sizeBytes)   /*!< [in] size of pBuff in 32-bit words. */
95 {
96         uint32_t sizeBits;
97         int32_t i;
98 
99         sizeBits = CC_CommonGetBytesCounterEffectiveSizeInBits(pBuf, sizeBytes);
100 
101         PKA_PRINTF("%s [%d] ", label, sizeBits);
102         for (i=(sizeBytes - 1); i>=0; i--) {
103                 PKA_PRINTF("%02X", pBuf[i]);
104         }
105         PKA_PRINTF("\n");
106 }
107 
108 /***********     PkiDbgPrintUintBuf  function     **********************/
109 /**
110  * @brief This The function prints the label and bytes array as string.
111  *
112  * @author reuvenl (14/02/2016)
113  *
114  * @return  None
115  */
PkiDbgPrintUint8Buff(const char * label,const uint8_t * pBuf,uint32_t sizeBytes)116 void PkiDbgPrintUint8Buff(const char     *label, /*!< [in] Label string. */
117                      const uint8_t *pBuf,  /*!< [in] 32-bit words buffer to print. */
118                      uint32_t  sizeBytes)   /*!< [in] size of pBuff in 32-bit words. */
119 {
120         uint32_t sizeBits;
121         uint32_t i;
122 
123         sizeBits = CC_CommonGetBytesCounterEffectiveSizeInBits(pBuf, sizeBytes);
124 
125         PKA_PRINTF("%s [%d] ", label, sizeBits);
126         for (i=0; i<sizeBytes; i++) {
127                 PKA_PRINTF("%02X", pBuf[i]);
128         }
129         PKA_PRINTF("\n");
130 }
131 #endif
132 
133 #if defined PKA_DEBUG && defined DEBUG
134 /***********    PkiDbgExecOperation (with virtual pointers)     ******************/
135 /**
136  * @brief This function executes any allowed PKA mathematic operation according to
137  *        user passed Opcode.
138  *
139  *        The function receives code of operation, virtual pointers to PKI registers
140  *        (sequence number), for arguments and result, and operates PKA machine by writing
141  *        full operation code into OPCODE register. Then the function calls macros for
142  *        waiting the PKA pipe ready signal.
143  *        If opcode is illegal or one of operands is illegal, the function returns an
144  *        error code defined in pka_error.h file.
145  *
146  *        The user don't call this function directly. For user convenience, in llf_pki.h file  are
147  *        given some macros for calling this function according to each performed operation.
148  *
149  *     NOTES:
150  *       -  Before executing modular operations, the modulus must be set into N=r0 register of PKA.
151  *       -  Before modular multiplication and exponentiation must be calculated and set into NP=r1
152  *          register the Barrett modulus tag NP = 2**(sizeN+132) / N.
153  *       -  In operations with immediate operands (IsImmediate bit = 1), the operand value (5-bit)
154  *          is treated as sign-extended. That means: low 4 bits are treated as unsigned operand
155  *          value in range 0-15 and bit 5 is a sign (with extension to all high bits of register,
156  *          in which the full operand shall be set).
157  *       -  In shift operations the 5-bits shift operand is treated as unsigned value in range 0-31
158  *          (count of shifts is equaled to shift operand value + 1).
159  *       -  The LMul operation gives the low half of multiplication result of length equaled to
160  *          operation size. The leading not significant bits of the operands and result (including
161  *          the the extra word) must be zeroed.
162  *       -  The HMul operation gives the high half of multiplication result plus one high word of low
163  *          half of full multiplication result. Therefore this result is by one word large, than
164  *          operation size. The leading not significant bits of the operands and result,
165  *          including extra word must be zeroed.
166  *       -  The ModInv operation calculates Res = 1/OpB mod N for odd modulus. Operand A is ignored.
167  *          In case of even modulus the function returns an error. Therefore in this case
168  *          (also for odd modulus) the user may call the PkaExecFullModInv function.
169  *
170  * @return  CC_OK On success, otherwise indicates failure
171  */
PkiDbgExecOperation(uint32_t Opcode,uint32_t lenId,uint32_t isAImmed,uint32_t OpA,uint32_t isBImmed,uint32_t OpB,uint32_t ResDiscard,uint32_t Res,uint32_t Tag)172 CCError_t PkiDbgExecOperation(uint32_t       Opcode,      /*!< [in] The operation code according HW PKA definitions. Valid values: 0 - max Opcode. */
173                                uint32_t       lenId,        /*!< [in] ID of the length of operands according to register sizes table
174                                     (means the number of entry in the table). Valid values: 0...7. */
175                                uint32_t       isAImmed,     /*!< [in] If isBImmed = 1, then operand A treated as immediate value, else -
176                                     as virtual register pointer. Valid values:0,1. */
177                                uint32_t       OpA,          /*!< [in] Operand A: an immediate value or virtual register pointer,
178                                     according to isAImmed parameter. */
179                                uint32_t       isBImmed,     /*!< [in] If isBImmed = 1, then operand B treated as immediate value, else -
180                                     as virtual register pointer. Valid values:0,1. */
181                                uint32_t       OpB,          /*!< [in] Operand B: an immediate value or virtual register pointer,
182                                     according to isBImmed parameter. */
183                                uint32_t       ResDiscard,   /*!< [in] If ResDiscard = 1, then result is discarded. */
184                                uint32_t       Res,          /*!< [Out] Virtual register pointer for result data.
185                                     Value Res = RES_DISCARD means result must be discarded. */
186                                uint32_t       Tag )         /*!< [in] The user defined value (Tag <= 31), used for indication goals. */
187 
188 {
189         CCError_t Error = CC_OK;
190         uint32_t FullOpCode;
191         uint32_t status;
192         uint8_t  OpPrint;
193         uint32_t opSizeInBits, RegSizeWords;
194 
195         /* if Res == RES_DISCARD , then result is discarded */
196         if (Res == (int8_t)RES_DISCARD) {
197                 ResDiscard = 1;
198                 Res = 0;
199         }
200 
201         /* set operation size according to lenId+1 for debug copy and clearing registers */
202         if (lenId == LEN_ID_MAX_BITS) {
203                 PKA_GET_REG_SIZE(opSizeInBits, LEN_ID_MAX_BITS);
204         } else if (lenId & 1) {
205                 PKA_GET_REG_SIZE(opSizeInBits, lenId);
206         } else {
207                 PKA_GET_REG_SIZE(opSizeInBits, lenId+1);
208         }
209 
210         RegSizeWords = PKA_WORD_SIZE_IN_32BIT_WORDS*((opSizeInBits+CC_PKA_WORD_SIZE_IN_BITS-1)/CC_PKA_WORD_SIZE_IN_BITS);
211 
212         /*************************************************/
213         /*      check input parameters                   */
214         /*************************************************/
215 
216         if (Opcode  > PKA_MAX_OPCODE) {
217                 Error =  PKA_ILLEGAL_OPCODE_ERROR;
218                 goto End;
219         }
220 
221         if (lenId >= LEN_ID_MAX) {
222                 Error = PKA_ILLEGAL_OPERAND_LEN_ERROR;
223                 goto End;
224         }
225 
226         if (isAImmed   > 1 ||
227             isBImmed   > 1 ||
228             ResDiscard > 1) {
229                 Error = PKA_ILLEGAL_OPERAND_TYPE_ERROR;
230                 goto End;
231         }
232 
233         if ((OpA >  31)      ||
234             (OpB >  31)      ||
235             (Res >  31)      ||
236             (Tag >  31)) {
237                 Error = PKA_ILLEGAL_OPERAND_ERROR;
238                 goto End;
239         }
240 
241         /* for ModInv and Div operation check, that modulus or divider are not 0 */
242         if (Opcode == PKA_OPCODE_ID_MODINV || Opcode == PKA_OPCODE_ID_DIVISION) {
243                 int8_t OpT;  /* number of register to test its Value = 0 */
244 
245                 /* Set OpT: 0 - for ModInv, OpB - for Div */
246                 if (Opcode == PKA_OPCODE_ID_MODINV) {
247                         Error = PKA_MODULUS_IS_NULL_ERROR;
248                         OpT = 0;
249                 } else {
250                         Error = PKA_DIVIDER_IS_NULL_ERROR;
251                         OpT = OpB;
252                 }
253 
254                 /* Create full opcode word for add immediate 0 operation */
255                 FullOpCode = PKA_SET_FULL_OPCODE(PKA_OPCODE_ID_ADD, lenId,0/*isAImmed*/,OpT/*N*/,1,0/*imm 0*/,1/*ResDiscard*/,0/*dumm*/,Tag);
256 
257                 /* write full opcode into PKA OPCODE register */
258                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL,OPCODE), FullOpCode);
259 
260                 /* test zero bit of STATUS register */
261                 PKA_GET_STATUS_ALU_OUT_ZERO(status);
262                 if (status == 1)
263                         goto End;
264                 else
265                         Error = CC_OK;
266         }
267 
268         /* for ModInv operation check, that OpB is odd, else return Error (can't calculate,
269            the user must use other function) */
270         if (Opcode == PKA_OPCODE_ID_MODINV) {
271                 /* Create full opcode word for Test bit 0 operation */
272                 FullOpCode = PKA_SET_FULL_OPCODE(PKA_OPCODE_ID_AND, lenId, 0/*isAImmed*/, 0/*N*/, 1, 1/*imm 1*/, 1/*ResDiscard*/, 0/*dumm*/, Tag);
273 
274                 /* write full opcode into PKA OPCODE register */
275                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET (CRY_KERNEL, OPCODE), FullOpCode);
276 
277                 /* test zero bit of STATUS register */
278                 PKA_GET_STATUS_ALU_OUT_ZERO(status);
279 
280                 if (status == 1) {
281                         Error = PKA_MOD_EVEN_USE_OTHER_FUNC_ERROR;
282                         goto End;
283                 }
284         }
285 
286 
287         /*************************************************/
288         /*      main PKI operation of this function      */
289         /*************************************************/
290 
291         FullOpCode = PKA_SET_FULL_OPCODE(Opcode, lenId, isAImmed, OpA, isBImmed, OpB, ResDiscard, Res, Tag);
292         PKA_WAIT_ON_PKA_PIPE_READY();
293         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET (CRY_KERNEL, OPCODE), FullOpCode);
294 
295 
296         /*************************************************/
297         /* finishing operations for different cases      */
298         /*************************************************/
299         if (Opcode == PKA_OPCODE_ID_DIVISION) {
300                 /* for Div operation check, that OpB != 0, else return Error */
301                 PKA_GET_STATUS_DIV_BY_ZERO(status);
302                 if (status == 1) {
303                         Error = PKA_DIVIDER_IS_NULL_ERROR;
304                         goto End;
305                 }
306         }
307 
308         /* wait for PKA done bit */
309         PKA_WAIT_ON_PKA_DONE();
310 
311         /* if operation Tag = Print, then copy result into tempRes buffer */
312         if (1/*Tag == PKA_TAG_DebugPtint*/ &&
313             ResDiscard == 0 && Opcode != PKA_OPCODE_ID_TERMINATE && Opcode != PKA_OPCODE_ID_SEPINT) {
314                 CC_PalMemSetZero(tempRes, sizeof(tempRes));
315                 PkaCopyDataFromPkaReg(tempRes/*dst_ptr*/, RegSizeWords, Res/*srcReg*/);
316 
317                 if (Opcode == PKA_OPCODE_ID_DIVISION || Opcode == PKA_OPCODE_ID_MODINV) {
318                         if (Opcode == PKA_OPCODE_ID_DIVISION)
319                                 OpPrint = OpA;
320                         else
321                                 OpPrint = OpB;
322 
323                         PkaCopyDataFromPkaReg(tempRes1/*dst_ptr*/, RegSizeWords, OpPrint/*srcReg*/);
324                 }
325         }
326 
327         End:
328 
329         return Error;
330 
331 }
332 
333 #endif /* #if PKA_EXEC_OP_DEBUG */
334 
335