1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #include "cc_pal_mem.h"
7 #include "cc_pal_mutex.h"
8 #include "cc_pal_abort.h"
9 #include "cc_common.h"
10 #include "cc_common_math.h"
11 #include "cc_ecpki_types.h"
12 #include "cc_ecpki_error.h"
13 #include "cc_ecpki_local.h"
14 #include "pka_hw_defs.h"
15 #include "pki.h"
16 #include "pka.h"
17 #include "ec_wrst.h"
18 #include "ec_wrst_error.h"
19 #include "pka_ec_wrst.h"
20 #include "pka_ec_wrst_glob_regs.h"
21 #include "pka_ec_wrst_dsa_verify_regs.h"
22 #include "cc_rnd_local.h"
23
24
25 /* canceling the lint warning:
26 Info 740: Unusual pointer cast
27 (incompatible indirect types) */
28 /*lint --e{740} */
29
30 /* canceling the lint warning:
31 Info 826: Suspicious pointer-to-pointer conversion
32 (area too small) */
33 /*lint --e{826} */
34
35 /* canceling the lint warning:
36 Info 716: while(1) */
37 /*lint --e{716} */
38
39 extern const int8_t regTemps[PKA_MAX_COUNT_OF_PHYS_MEM_REGS];
40
41 /*********** CalcSignature function **********************/
42 /**
43 * @brief Sets data into SRAM and calculates ECDSA Signature.
44 *
45 * @author reuvenl (3/29/2015)
46 *
47 * Note: All data in is given with LE order of words (LS word is left most).
48 * Algorithm - according ANS X9.62 denoted [1].
49 *
50 * @return CC_OK On success, otherwise indicates failure
51 */
CalcSignature(const CCEcpkiDomain_t * pDomain,uint32_t * pSignPrivKey,uint32_t * pMsgRepres,uint32_t * pEphemPrivKey,uint32_t * pEphemPublX,uint32_t * pSignC,uint32_t * pSignD)52 static CCError_t CalcSignature(const CCEcpkiDomain_t *pDomain, /*!< [in] Pointer to EC domain structure. */
53 uint32_t *pSignPrivKey, /*!< [in] Pointer to signer privatekey structure. */
54 uint32_t *pMsgRepres, /*!< [in] The pointer to the message representative buffer.*/
55 uint32_t *pEphemPrivKey, /*!< [in] pointer to private Ephemeral key buff. */
56 uint32_t *pEphemPublX, /*!< [in] Pointer to X-coordinate of Ephemeral public. */
57 uint32_t *pSignC, /*!< [in] Pointer to C-part of the signature (called also R-part). */
58 uint32_t *pSignD) /*!< [in] Pointer to D-part of the signature (called also S-part). */
59 {
60 CCError_t err = CC_OK;
61 uint32_t status;
62 uint32_t ordSizeInWords, modSizeInWords;
63 uint32_t pkaReqRegs = PKA_MAX_COUNT_OF_PHYS_MEM_REGS;
64
65 /* define regs (ECC_REG_N=0, ECC_REG_NP=1) */
66 uint8_t rC = regTemps[2]; /*C (zR) - signC*/
67 uint8_t rM = regTemps[3]; /*message (zF)*/
68 uint8_t rEphK = regTemps[4]; /*ephemer.priv.key*/
69 uint8_t rK = regTemps[5]; /*priv. key (zD)*/
70 uint8_t rKinv = regTemps[6];
71 uint8_t rD = regTemps[7]; /*D (zS)- signD*/
72 uint8_t rT = regTemps[8];
73
74
75 /* set EC modulus and order sizes */
76 ordSizeInWords = CALC_FULL_32BIT_WORDS(pDomain->ordSizeInBits);
77 modSizeInWords = CALC_FULL_32BIT_WORDS(pDomain->modSizeInBits);
78 if ((ordSizeInWords > (CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1)) ||
79 (modSizeInWords > CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS)) {
80 return ECWRST_SCALAR_MULT_INVALID_MOD_ORDER_SIZE_ERROR;
81 }
82
83 /* Init PKA for operations with EC order */
84 err = PkaInitAndMutexLock(pDomain->ordSizeInBits , &pkaReqRegs); // RL Count regs to clean 9!
85 if (err != CC_OK) {
86 return err;
87 }
88
89
90 /* Set data into PKA registers */
91 /* Note: ignore false positive KW warning about explicit offset: *
92 sizes, given in the EC Domain, must be right */
93 PkaCopyDataIntoPkaReg(ECC_REG_N, 1, pDomain->ecR/*src_ptr*/, ordSizeInWords);
94 PkaCopyDataIntoPkaReg(ECC_REG_NP, 1, ((EcWrstDomain_t*)&(pDomain->llfBuff))->ordTag,
95 CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
96 PkaCopyDataIntoPkaReg(rC, 1, pEphemPublX, modSizeInWords);
97 PkaCopyDataIntoPkaReg(rM, 1, pMsgRepres, ordSizeInWords);
98 PkaCopyDataIntoPkaReg(rEphK, 1, pEphemPrivKey, ordSizeInWords);
99 PkaCopyDataIntoPkaReg(rK, 1, pSignPrivKey, ordSizeInWords);
100
101 /* Calculate Signature */
102 /* [1] 7.3. calc. rEphK mod ECC_REG_N and check that it > 0 */
103 PKA_DIV(LEN_ID_MAX_BITS, rT/*not used*/, rEphK, ECC_REG_N);
104 PKA_COMPARE_IM_STATUS(LEN_ID_MAX_BITS, rEphK, 0, status);
105 if(status == 1){
106 err = ECWRST_DSA_SIGN_BAD_EPHEMER_KEY_TRY_AGAIN_ERROR;
107 goto End;
108 }
109
110 /* check rKinv != 0 (ANS X9.62 7.3) */
111 PKA_MOD_INV_W_EXP(rKinv, rEphK, rT/*temp*/); /* RL to inv_fast */
112 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rKinv, 0, status);
113 if(status == 1) {
114 err = ECWRST_DSA_SIGN_BAD_EPHEMER_KEY_TRY_AGAIN_ERROR;
115 goto End;
116 }
117 PKA_MOD_MUL(LEN_ID_N_BITS, rD, rK, rC);
118 PKA_REDUCE(LEN_ID_N_BITS,rM, rM);
119 PKA_MOD_ADD(LEN_ID_N_PKA_REG_BITS, rD, rD, rM);
120 PKA_MOD_MUL(LEN_ID_N_BITS, rD, rD, rKinv);
121 /* check rD != 0 (ANS X9.62 7.3) */
122 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rD, 0, status);
123 if(status == 1) {
124 err = ECWRST_DSA_SIGN_BAD_EPHEMER_KEY_TRY_AGAIN_ERROR;
125 goto End;
126 }
127 /* if status == 0 then copy the signature to the output */
128 if(status == 0) {
129 PkaCopyDataFromPkaReg(pSignC, ordSizeInWords, rC);
130 PkaCopyDataFromPkaReg(pSignD, ordSizeInWords, rD);
131 }
132
133 End:
134 PkaFinishAndMutexUnlock(pkaReqRegs);
135 return err;
136
137 }
138
139
140 /*********** EcWrstDsaTruncateMsg function **********************/
141 /**
142 * @brief Truncates the message to given count of LS bits.
143 *
144 * @author reuvenl (8/19/2014)
145 *
146 * @return no return value.
147 */
EcWrstDsaTruncateMsg(uint32_t * pMsgOut,uint8_t * pMsgIn,uint32_t outSizeBits)148 void EcWrstDsaTruncateMsg(
149 uint32_t *pMsgOut, /*!< [out] Pointer to truncated message output.
150 Output format: bytes, LS byte is left most one. */
151 uint8_t *pMsgIn, /*!< [in] Pointer to input message in bytes. */
152 uint32_t outSizeBits) /*!< [in] Exact size of truncated message in bits. */
153 {
154 uint32_t i, shift;
155 uint32_t outSizeBytes = CALC_FULL_BYTES(outSizeBits);
156 uint32_t outSizeWords = CALC_FULL_32BIT_WORDS(outSizeBits);
157
158 pMsgOut[outSizeWords-1] = 0; /* zeroing high word of output */
159 /* reverse copy only a needed bytes of the message */
160 CC_CommonReverseMemcpy((uint8_t*)pMsgOut, pMsgIn, outSizeBytes);
161
162 /* shift right by redundant bits */
163 shift = (8 - (outSizeBits & 7UL)) & 7UL;
164 if (shift) {
165 for (i = 0; i < CALC_FULL_32BIT_WORDS(outSizeBits) - 1; i++) {
166 pMsgOut[i] = (pMsgOut[i] >> shift) |
167 (pMsgOut[i+1] << (32-shift));
168 }
169 pMsgOut[i] = pMsgOut[i] >> shift;
170 }
171 return;
172 }
173
174
175
176 /*********** EcWrstDsaSign function **********************/
177 /**
178 * @brief Generates aphemeral key, if needed and
179 * calls specific Signature function.
180 *
181 * @author reuvenl (3/29/2015)
182 *
183 * Note: All data in buffers given with LE order of bytes and word and their sizes
184 * must be EC modulus size in words (with leading zeros)
185 *
186 * @return CC_OK On success, otherwise indicates failure
187 */
EcWrstDsaSign(CCRndContext_t * pRndContext,CCEcpkiPrivKey_t * pSignPrivKey,uint32_t * pMsgRepres,uint32_t isEphemerKeyInternal,uint32_t * pEphemKey,uint32_t * pSignC,uint32_t * pSignD,uint32_t * pTempBuff)188 CCError_t EcWrstDsaSign(CCRndContext_t *pRndContext, /*!< [in/out] Pointer to the RND context buffer. */
189 CCEcpkiPrivKey_t *pSignPrivKey, /*!< [in] Pointer to to signer privatekey structure. */
190 uint32_t *pMsgRepres, /*!< [in] The pointer to the message representative buffer.*/
191 uint32_t isEphemerKeyInternal, /*!< [in] boolean indicating internal (=1) or external (=0) ephemeral key. */
192 uint32_t *pEphemKey, /*!< [in] Pointer to to private Ephemeral key buff. */
193 uint32_t *pSignC, /*!< [in] Pointer to C-part of the signature (called also R-part). */
194 uint32_t *pSignD, /*!< [in] Pointer to D-part of the signature (called also S-part). */
195 uint32_t *pTempBuff) /*!< [in] Pointer to temp buffer. the buffer size must be
196 not less than (3*ModulusSizeInWords +
197 CC_PKA_ECPKI_SCALAR_MUL_BUFF_MAX_LENGTH_IN_WORDS)*/
198 {
199 CCError_t err = CC_OK;
200 const CCEcpkiDomain_t *pDomain = &pSignPrivKey->domain;
201 uint32_t ordSizeInBits, ordSizeInWords, modSizeInWords;
202 /* pointers to result EC point coordinates x, y */
203 uint32_t *pEphemPublX, *pEphemPublY, *pEphemKeyBuf, *pMaxVect;
204 uint32_t *funcTmpBuff;
205 uint32_t countTries = 0;
206
207
208 /* set EC domain parameters modulus and EC order sizes */
209 ordSizeInBits = pDomain->ordSizeInBits;
210 ordSizeInWords = CALC_FULL_32BIT_WORDS(ordSizeInBits);
211 modSizeInWords = CALC_FULL_32BIT_WORDS(pDomain->modSizeInBits);
212 if ((ordSizeInWords > (CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1)) ||
213 (modSizeInWords > CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS)) {
214 return ECWRST_SCALAR_MULT_INVALID_MOD_ORDER_SIZE_ERROR;
215 }
216
217
218 pEphemPublX = pTempBuff; //?? use pSignC to save mem
219 pEphemKeyBuf = pEphemPublX + modSizeInWords;
220 pEphemPublY = pEphemKeyBuf + ordSizeInWords;
221 pMaxVect = pEphemPublY + modSizeInWords;
222
223 while (1) {
224 /* Generate random ephemeral key *
225 * Note: Checking, that private ephemer.key 0 < k < EC order *
226 * performed on LLF during scalar multiplication */
227 if(isEphemerKeyInternal) {
228 /* Set bytes MaxVect= EcOrder. */
229 pMaxVect[ordSizeInWords-1] = 0; /*zero MSWord of maxVect*/
230 CC_PalMemCopy(pMaxVect, pDomain->ecR, sizeof(uint32_t)*ordSizeInWords);
231 pEphemKeyBuf[ordSizeInWords-1] = 0; /*zero MSWord*/
232 err = CC_RndGenerateVectorInRange(
233 pRndContext, pDomain->ordSizeInBits, (uint8_t*)pMaxVect/* maxVect*/, (uint8_t*)pEphemKeyBuf);
234 if (err) {
235 goto End;
236 }
237 }
238 /* copy external key if provided */
239 else {
240 /* Note: Checking of range of the ephemeral key *
241 * performed in PkaEcWrstScalarMult */
242 CC_PalMemCopy(pEphemKeyBuf, pEphemKey, sizeof(uint32_t)*ordSizeInWords);
243 }
244
245 /* Calculate ephemeral public key */
246 funcTmpBuff = pMaxVect; /* because pMaxVect not needed yet */
247 err = PkaEcWrstScalarMult(pDomain,
248 pEphemKeyBuf/*scalar*/, ordSizeInWords, /*scalar size*/
249 (uint32_t*)&pDomain->ecGx, (uint32_t*)&pDomain->ecGy, /*in point coordinates*/
250 pEphemPublX/*C*/, pEphemPublY, /*out point coordinates*/
251 funcTmpBuff);
252 if (err) {
253 goto End;
254 }
255
256
257 /* Calculate Signature S */
258 err = CalcSignature(pDomain, pSignPrivKey->PrivKey,
259 pMsgRepres, pEphemKeyBuf, pEphemPublX,
260 pSignC, pSignD);
261
262 /* exit the programm if an error occurs, beside the case of *
263 * returned error message to try a new Ephemeral Key */
264 if(err && (err != ECWRST_DSA_SIGN_BAD_EPHEMER_KEY_TRY_AGAIN_ERROR || !isEphemerKeyInternal)) {
265 goto End;
266 }
267
268 /* if error is OK or count of tries > 100, then end the loop*/
269 if((err == 0) || (countTries > 100)) {
270 goto End;
271 } else {
272 countTries++;
273 }
274 } /* End of while() */
275
276 End:
277 return err;
278 }
279
280
281 /*********** EcWrstDsaVerify function **********************/
282 /**
283 * @brief Verifies the signature.
284 *
285 * @author reuvenl (8/7/2014)
286 *
287 * @return CC_OK On success, otherwise indicates failure
288 */
EcWrstDsaVerify(CCEcpkiPublKey_t * pSignPublKey,uint32_t * pMsgRepres,uint32_t msgRepresSizeWords,uint32_t * pSignC,uint32_t * pSignD)289 CCError_t EcWrstDsaVerify(CCEcpkiPublKey_t *pSignPublKey, /*!< [in] Pointer to signer public key structure. */
290 uint32_t *pMsgRepres, /*!< [in] The pointer to the message representative buffer.*/
291 uint32_t msgRepresSizeWords, /*!< [in] Size of the message representative buffer in words.*/
292 uint32_t *pSignC, /*!< [in] Pointer to C-part of the signature (called also R-part). */
293 uint32_t *pSignD) /*!< [in] Pointer to D-part of the signature (called also S-part). */
294 {
295 CCError_t err = CC_OK;
296 const CCEcpkiDomain_t *domain = &pSignPublKey->domain;
297 EcWrstDomain_t *llfBuff = (EcWrstDomain_t*)&pSignPublKey->domain.llfBuff;
298 int32_t modSizeInBits, modSizeInWords, ordSizeInBits, ordSizeInWords;
299 uint32_t pkaReqRegs = PKA_MAX_COUNT_OF_PHYS_MEM_REGS;
300
301
302 /* set domain parameters */
303 modSizeInBits = domain->modSizeInBits;
304 modSizeInWords = CALC_FULL_32BIT_WORDS(modSizeInBits);
305 ordSizeInBits = domain->ordSizeInBits;
306 ordSizeInWords = CALC_FULL_32BIT_WORDS(ordSizeInBits);
307 if ((ordSizeInWords > (CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1)) ||
308 (modSizeInWords > CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS)) {
309 return ECWRST_SCALAR_MULT_INVALID_MOD_ORDER_SIZE_ERROR;
310 }
311
312 /* Init PKA for modular operations with EC modulus or EC order and *
313 * registers size according to maximal of them */
314 err = PkaInitAndMutexLock(CC_MAX(ordSizeInBits, modSizeInBits), &pkaReqRegs);
315 if (err != CC_OK) {
316 return err;
317 }
318 /* set order and modulus mod sizes */
319 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET (CRY_KERNEL, PKA_L0), ordSizeInBits);
320 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET (CRY_KERNEL, PKA_L2), modSizeInBits);
321
322 /* Set input data into PKA registers */
323 /* EC order and its Barrett tag */
324 PkaCopyDataIntoPkaReg(ECC_REG_N/*dest_reg*/, 1, domain->ecR/*src_ptr*/, ordSizeInWords);
325 PkaCopyDataIntoPkaReg(ECC_REG_NP, 1, llfBuff->ordTag, CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
326 /* signature C, D */
327 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_C, 1, pSignC, ordSizeInWords);
328 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_D, 1, pSignD, ordSizeInWords);
329 /* message representative EC_VERIFY_REG_F */
330 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_F, 1, pMsgRepres, msgRepresSizeWords);
331 /* Load modulus and its Barrett tag */
332 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_TMP_N, 1, domain->ecP, modSizeInWords);
333 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_TMP_NP, 1, llfBuff->modTag, CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
334 /* set pG */
335 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_P_GX, 1, domain->ecGx, modSizeInWords);
336 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_P_GY, 1, domain->ecGy, modSizeInWords);
337 /* set pW */
338 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_P_WX, 1, pSignPublKey->x, modSizeInWords);
339 PkaCopyDataIntoPkaReg(EC_VERIFY_REG_P_WY, 1, pSignPublKey->y, modSizeInWords);
340 PkaCopyDataIntoPkaReg(ECC_REG_EC_A, 1, domain->ecA, modSizeInWords);
341
342 /* Verify */
343 err = PkaEcdsaVerify();
344
345 PkaFinishAndMutexUnlock(pkaReqRegs);
346
347 return err;
348
349 }
350
351