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