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