1 /*
2  * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /*
8  * All the includes that are needed for code using this module to
9  * compile correctly should be #included here.
10  */
11 #include "cc_pal_mem.h"
12 #include "cc_pal_types.h"
13 #include "cc_pal_mutex_plat.h"
14 #include "cc_hal_plat.h"
15 #include "cc_common.h"
16 #include "cc_common_math.h"
17 #include "cc_ecpki_error.h"
18 #include "cc_ec_edw_api.h"
19 #include "mbedtls_cc_ec_mont_edw_error.h"
20 
21 #include "pka_hw_defs.h"
22 #include "pka_defs.h"
23 #include "ec_edw_local.h"
24 #include "pka.h"
25 #include "pki.h"
26 #include "pka_error.h"
27 #include "ec_edw.h"
28 #include "pka_ec_edw_glob_regs_def.h"
29 
30 #include "pki_dbg.h"
31 #include "cc_int_general_defs.h"
32 #include "cc_general_defs.h"
33 #include "mbedtls/md.h"
34 
35 /* global data definitions */
36 extern CC_PalMutex CCAsymCryptoMutex;
37 
38 
39 /*********************************************************************/
40 /*!
41 @brief The function performs EC Edwards key pair generation using seed.
42 
43        Libsodium analog: crypto_sign_ed25519_seed_keypair() function
44 
45  @return CCError_t
46 */
EcEdwSeedKeyPair(uint8_t * pPublKey,uint8_t * pSecrKey,const uint8_t * pSeed,const CCEcEdwDomain_t * pEcDomain,uint32_t * pTempBuff)47 CCError_t EcEdwSeedKeyPair(
48                                uint8_t *pPublKey,                    /*!< [out] a pointer to publickey (compressed,
49                                                                            the size = ec modulus size) */
50                                uint8_t *pSecrKey,                    /*!< [out] a pointer to secret key, stated as concatenation
51                                                                           of seed amd public key (the size = 2 * ec modulus size) */
52                                const uint8_t  *pSeed,                /*!< [in] a pointer to the seed (the size = ec order size) */
53                                const CCEcEdwDomain_t *pEcDomain,   /*!< [in] pointer to EC domain (curve). */
54                                uint32_t *pTempBuff)             /*!< [in] pointer to the temp buffer. */
55 {
56         CCError_t err = CC_OK;
57         uint32_t pkaRegsUsed;
58         uint32_t edwSizeWords = pEcDomain->ecModSizeInWords;
59         uint32_t edwSizeBytes = edwSizeWords * sizeof(uint32_t);
60 
61         /* set pointers to temp buffers */
62         uint32_t *pPrivKey32/*az*/ = pTempBuff;
63         uint32_t *pPublKey32/*az*/ = pPrivKey32 + edwSizeWords;
64         uint32_t *pCoordX32/*az*/ = pPublKey32 + edwSizeWords;
65         const mbedtls_md_info_t *md_info=NULL;
66 
67         /* get the hardware semaphore  */
68         err = CC_PalMutexLock(&CCAsymCryptoMutex, CC_INFINITE);
69         if (err != CC_SUCCESS) {
70                 CC_PalAbort("Fail to acquire mutex\n");
71         }
72 
73         /* verify that the device is not in fatal error state before activating the PKA engine */
74         CC_IS_FATAL_ERR_ON(err);
75         if (err == CC_TRUE) {
76                 /* release the hardware semaphore */
77                 if (CC_PalMutexUnlock(&CCAsymCryptoMutex) != CC_SUCCESS) {
78                         CC_PalAbort("Fail to release mutex\n");
79                 }
80                 return PKA_FATAL_ERR_STATE_ERROR;
81         }
82 
83         /* increase CC counter at the beginning of each operation */
84         err = CC_IS_WAKE;
85         if (err != CC_SUCCESS) {
86             CC_PalAbort("Fail to increase PM counter\n");
87         }
88 
89         /* init PKA, mapping and sizes tables */
90         pkaRegsUsed = 30;
91         err = PkaInitPka(pEcDomain->ecModSizeInBits, 0/*edwSizeWords*/,
92                          &pkaRegsUsed/*regs.count*/);
93 
94         if (err != CC_SUCCESS) {
95                 err = CC_ECEDW_INTERNAL_ERROR;
96                 goto End;
97         }
98 
99         /* calculate private key from seed (first half of SignSecrKey) */
100         md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[CC_HASH_SHA512_mode] );
101         if (NULL == md_info) {
102                 err = CC_ECEDW_INTERNAL_ERROR;
103                 goto End;
104         }
105         err = mbedtls_md(md_info,
106                          (uint8_t*)pSeed,
107                          edwSizeBytes,
108                         (unsigned char *)pPrivKey32);
109         if (err != CC_OK) {
110                 goto End;
111         }
112 
113         pPrivKey32[0] &= 0xFFFFFFF8;              // & 248;
114         pPrivKey32[edwSizeWords-1] &=  0x3FFFFFFF;// & 63;
115         pPrivKey32[edwSizeWords-1] |=  0x40000000;// | 64;
116 
117         /* call EC scalar multiplication function */
118         err = EcEdwSpecialScalarMultBase(
119                                 pCoordX32, /*coord.X*/
120                                 pPublKey32,/*coord.Y*/
121                                 pPrivKey32,
122                                 edwSizeWords,
123                                 pEcDomain);
124         if (err)
125                 goto End;
126 
127 
128         /* set high bit of Y */
129         pPublKey32[edwSizeWords-1] |= ((pCoordX32[0] & 1) << 31);
130 
131         /* results output */
132         CC_PalMemCopy(pSecrKey, pSeed, edwSizeBytes);
133         CC_CommonConvertLswMswWordsToLsbMsbBytes(pPublKey, pPublKey32, edwSizeWords);
134         CC_PalMemCopy(pSecrKey + edwSizeBytes, pPublKey, edwSizeBytes);
135 
136 End:
137         CC_PalMemSetZero(pTempBuff, 3*edwSizeBytes);
138         PkaFinishAndMutexUnlock(pkaRegsUsed);
139         return err;
140 }
141 
142 /*********************************************************************/
143 /*!
144  * The function performs input/output parameters for EC Edwards
145  * scalar multiplication.
146  *
147  *         resPoint(Y,_) = k*inPoint(X,Y), where:
148  *         the point is given with LE order of the words.
149  *
150  *         Assuming:
151  *              The PKA HW is turned ON and initialized yet;
152  *
153  * \return CCError_t
154  */
EcEdwScalarMultBase(uint32_t * pResPointX,uint32_t * pResPointY,uint32_t * pScalar,size_t scalarSizeWords,const CCEcEdwDomain_t * pEcDomain)155 CCError_t  EcEdwScalarMultBase(
156                                 uint32_t  *pResPointX,             /*!< [out] a pointer (optional) to result EC point coordinate X. */
157                                 uint32_t  *pResPointY,             /*!< [out] a pointer to result EC point coordinate Y. */
158                                 uint32_t  *pScalar,                /*!< [in]  a pointer to the scalar. */
159                                 size_t     scalarSizeWords,        /*!< [in]  the scalar size in words. */
160                                 const CCEcEdwDomain_t *pEcDomain     /*!< [in]  a pointer to EC domain (curve). */)
161 {
162 
163         /* Definitions */
164 
165         CCError_t err = CC_OK;
166         size_t edwSizeWords = pEcDomain->ecModSizeInWords;
167         size_t scalarSizeInBits;
168 
169 
170         /* Get exact scalar size in bits */
171         scalarSizeInBits = CC_CommonGetWordsCounterEffectiveSizeInBits(pScalar, scalarSizeWords);
172         if (scalarSizeInBits == 0)
173                 return CC_EC_EDW_INVALID_SCALAR_SIZE_ERROR;
174 
175         /* ********************************************* */
176         /*   load needed data to defined pka registers   */
177         /* ********************************************* */
178 
179         /*   pEcDomain modulus and Barr. tag */
180         PkaCopyDataIntoPkaReg(EDW_REG_N, LEN_ID_MAX_BITS, pEcDomain->ecModP, edwSizeWords);
181         PkaCopyDataIntoPkaReg(EDW_REG_NP, LEN_ID_MAX_BITS, pEcDomain->ecModBarrTag,
182                               CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
183 
184         /* set precalculated points data: G,2G,4G  */
185         PkaCopyDataIntoPkaReg(EDW_REG_SG,   LEN_ID_MAX_BITS, pEcDomain->sg,   edwSizeWords);
186         PkaCopyDataIntoPkaReg(EDW_REG_DG,   LEN_ID_MAX_BITS, pEcDomain->dg,   edwSizeWords);
187         PkaCopyDataIntoPkaReg(EDW_REG_PG,   LEN_ID_MAX_BITS, pEcDomain->pg,   edwSizeWords);
188         PkaCopyDataIntoPkaReg(EDW_REG_MPG,  LEN_ID_MAX_BITS, pEcDomain->mpg,  edwSizeWords);
189         PkaCopyDataIntoPkaReg(EDW_REG_SG2,  LEN_ID_MAX_BITS, pEcDomain->sg2,  edwSizeWords);
190         PkaCopyDataIntoPkaReg(EDW_REG_DG2,  LEN_ID_MAX_BITS, pEcDomain->dg2,  edwSizeWords);
191         PkaCopyDataIntoPkaReg(EDW_REG_PG2,  LEN_ID_MAX_BITS, pEcDomain->pg2,  edwSizeWords);
192         PkaCopyDataIntoPkaReg(EDW_REG_MPG2, LEN_ID_MAX_BITS, pEcDomain->mpg2, edwSizeWords);
193         PkaCopyDataIntoPkaReg(EDW_REG_SG4,  LEN_ID_MAX_BITS, pEcDomain->sg4,  edwSizeWords);
194         PkaCopyDataIntoPkaReg(EDW_REG_DG4,  LEN_ID_MAX_BITS, pEcDomain->dg4,  edwSizeWords);
195         PkaCopyDataIntoPkaReg(EDW_REG_PG4,  LEN_ID_MAX_BITS, pEcDomain->pg4,  edwSizeWords);
196         PkaCopyDataIntoPkaReg(EDW_REG_MPG4, LEN_ID_MAX_BITS, pEcDomain->mpg4, edwSizeWords);
197         PkaCopyDataIntoPkaReg(EDW_REG_XG2,  LEN_ID_MAX_BITS, pEcDomain->xg2,  edwSizeWords);
198         PkaCopyDataIntoPkaReg(EDW_REG_YG2,  LEN_ID_MAX_BITS, pEcDomain->yg2,  edwSizeWords);
199         PkaCopyDataIntoPkaReg(EDW_REG_TG2,  LEN_ID_MAX_BITS, pEcDomain->tg2,  edwSizeWords);
200         PkaCopyDataIntoPkaReg(EDW_REG_XG4,  LEN_ID_MAX_BITS, pEcDomain->xg4,  edwSizeWords);
201         PkaCopyDataIntoPkaReg(EDW_REG_YG4,  LEN_ID_MAX_BITS, pEcDomain->yg4,  edwSizeWords);
202         PkaCopyDataIntoPkaReg(EDW_REG_TG4,  LEN_ID_MAX_BITS, pEcDomain->tg4,  edwSizeWords);
203         /* set D2 */
204         PkaCopyDataIntoPkaReg(EDW_REG_D2, LEN_ID_MAX_BITS, pEcDomain->ecAuxValD2, edwSizeWords);
205 
206         /*--------------------------------------------------------------------*
207         * perform EC scalar multiplication:  used PKA registers defined in    *
208         *    "pka_ec_edw_glob_regs_def."h file; input - scalr;                *
209         *     output registers: EC_MONT_REG_YS and EDW_REG_XS                 *
210         *---------------------------------------------------------------------*/
211 
212         /* used common scalarMult function; output regs:  *
213          *       x<-EDW_REG_SG, y<-EDW_REG_DG             */
214         err = PkaEcEdwScalarMultBase(pScalar, scalarSizeInBits);
215         if (err) {
216                 goto End;
217         }
218 
219         /* output result point: x,y */
220         PkaCopyDataFromPkaReg(pResPointX/*dst*/, edwSizeWords, EDW_REG_SG/*srcReg*/);
221         PkaCopyDataFromPkaReg(pResPointY/*dst*/, edwSizeWords, EDW_REG_DG/*srcReg*/);
222 
223         End:
224         return err;
225 }
226 
227 /*********************************************************************/
228 /*!
229  * The function performs input/output parameters for EC Edwards scalar
230  * multiplication for special scalars.
231  *
232  *         resPoint(Y,_) = k*inPoint(X,Y), where:
233  *         the point is given with LE order of the words.
234  *
235  *         Assuming:
236  *              The PKA HW is turned on and initialized yet;
237  *
238  * \return CCError_t
239  */
EcEdwSpecialScalarMultBase(uint32_t * pResPointX,uint32_t * pResPointY,uint32_t * pScalar,size_t scalarSizeWords,const CCEcEdwDomain_t * pEcDomain)240 CCError_t  EcEdwSpecialScalarMultBase(
241                                        uint32_t  *pResPointX,             /*!< [out] a pointer to result EC point coordinate X. */
242                                        uint32_t  *pResPointY,             /*!< [out] a pointer to result EC point coordinate Y. */
243                                        uint32_t  *pScalar,                /*!< [in]  a pointer to the scalar. */
244                                        size_t     scalarSizeWords,         /*!< [in]  the scalar size in words. */
245                                        const CCEcEdwDomain_t *pEcDomain /*!< [in]  a pointer to EC domain (curve). */)
246 {
247 
248         /* Definitions */
249 
250         CCError_t err = CC_OK;
251         size_t   edwSizeWords = pEcDomain->ecModSizeInWords;
252         size_t   scalarSizeBits;
253 
254         /* Get exact scalar size in bits */
255         scalarSizeBits = CC_CommonGetWordsCounterEffectiveSizeInBits(pScalar, scalarSizeWords);
256         if (scalarSizeWords == 0)
257                 return CC_EC_EDW_INVALID_SCALAR_SIZE_ERROR;
258 
259         /* ********************************************* */
260         /*   load needed data to defined pka registers   */
261         /* ********************************************* */
262 
263         /*   pEcDomain modulus and Barr. tag */
264         PkaCopyDataIntoPkaReg(EDW_REG_N, LEN_ID_MAX_BITS, pEcDomain->ecModP, edwSizeWords);
265         PkaCopyDataIntoPkaReg(EDW_REG_NP, LEN_ID_MAX_BITS, pEcDomain->ecModBarrTag,
266                               CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
267 
268         /* set precalculated points data: G,4G...32G,  */
269         PkaCopyDataIntoPkaReg(EDW_REG_SG4, LEN_ID_MAX_BITS, pEcDomain->sg4, edwSizeWords);
270         PkaCopyDataIntoPkaReg(EDW_REG_DG4, LEN_ID_MAX_BITS, pEcDomain->dg4, edwSizeWords);
271         PkaCopyDataIntoPkaReg(EDW_REG_PG4, LEN_ID_MAX_BITS, pEcDomain->pg4, edwSizeWords);
272         PkaCopyDataIntoPkaReg(EDW_REG_MPG4, LEN_ID_MAX_BITS, pEcDomain->mpg4, edwSizeWords);
273         PkaCopyDataIntoPkaReg(EDW_REG_SG8, LEN_ID_MAX_BITS, pEcDomain->sg8, edwSizeWords);
274         PkaCopyDataIntoPkaReg(EDW_REG_DG8, LEN_ID_MAX_BITS, pEcDomain->dg8, edwSizeWords);
275         PkaCopyDataIntoPkaReg(EDW_REG_PG8, LEN_ID_MAX_BITS, pEcDomain->pg8, edwSizeWords);
276         PkaCopyDataIntoPkaReg(EDW_REG_MPG8, LEN_ID_MAX_BITS, pEcDomain->mpg8, edwSizeWords);
277         PkaCopyDataIntoPkaReg(EDW_REG_SG16, LEN_ID_MAX_BITS, pEcDomain->sg16, edwSizeWords);
278         PkaCopyDataIntoPkaReg(EDW_REG_DG16, LEN_ID_MAX_BITS, pEcDomain->dg16, edwSizeWords);
279         PkaCopyDataIntoPkaReg(EDW_REG_PG16, LEN_ID_MAX_BITS, pEcDomain->pg16, edwSizeWords);
280         PkaCopyDataIntoPkaReg(EDW_REG_MPG16, LEN_ID_MAX_BITS, pEcDomain->mpg16, edwSizeWords);
281         /* s = 32G*/
282         PkaCopyDataIntoPkaReg(EDW_REG_XS, LEN_ID_MAX_BITS, pEcDomain->xg32, edwSizeWords);
283         PkaCopyDataIntoPkaReg(EDW_REG_YS, LEN_ID_MAX_BITS, pEcDomain->yg32, edwSizeWords);
284         PkaCopyDataIntoPkaReg(EDW_REG_TS, LEN_ID_MAX_BITS, pEcDomain->tg32, edwSizeWords);
285         PKA_CLEAR(LEN_ID_MAX_BITS, EDW_REG_ZS);
286         PKA_SET_BIT0(LEN_ID_MAX_BITS, EDW_REG_ZS, EDW_REG_ZS);
287         /* set 4N */
288         PKA_ADD(LEN_ID_N_PKA_REG_BITS, EDW_REG_N_4, EDW_REG_N, EDW_REG_N);
289         PKA_ADD(LEN_ID_N_PKA_REG_BITS, EDW_REG_N_4, EDW_REG_N_4, EDW_REG_N_4);
290         /* set D2 */
291         PkaCopyDataIntoPkaReg(EDW_REG_D2, LEN_ID_MAX_BITS, pEcDomain->ecAuxValD2, edwSizeWords);
292 
293         /*--------------------------------------------------------------------*
294         * perform EC scalar multiplication:  used PKA registers defined in    *
295         *    "pka_ec_edw_glob_regs_def."h file; input - scalr;                *
296         *     output registers: EC_MONT_REG_YS and EDW_REG_XS                 *
297         *---------------------------------------------------------------------*/
298         /* use special (more fasted) scalarMult function */
299         err = PkaEcEdwSpecialScalarMultBase(pScalar, scalarSizeBits);
300 
301         if (err) {
302                 goto End;
303         }
304 
305         /* output result point: X,Y */
306         PkaCopyDataFromPkaReg(pResPointX/*dst*/, edwSizeWords, EDW_REG_SG8/*srcReg*/);
307         PkaCopyDataFromPkaReg(pResPointY/*dst*/, edwSizeWords, EDW_REG_DG8/*srcReg*/);
308 
309         End:
310         return err;
311 }
312 
313 
314 /**
315  * The function createss EC Edwards detatched signature on given message
316  *
317  * Implemented algorithm of Bernstein D. etc. sign ed25519 detached.
318  *
319  * @author reuvenl (1/21/2016)
320  *
321  * @return CCError_t
322  */
EcEdwSign(uint8_t * pEdwSign,const uint8_t * pMsg,size_t msgSize,const uint8_t * pSignSecrKey,const CCEcEdwDomain_t * pEcDomain,CCEcEdwTempBuff_t * pEcEdwSignTempBuff)323 CCError_t  EcEdwSign (
324                        uint8_t       *pEdwSign,             /*!< [out] - the pointer to the signature (detatched). */
325                        const uint8_t *pMsg,                 /*!< [in] - the pointer to the message. */
326                        size_t         msgSize,              /*!< [in] - the message size in bytes: it must be less, than
327                                                                  CC_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES. */
328                        const uint8_t *pSignSecrKey,         /*!< [in] - the pointer to the signer secret key, stated as
329                                                                  concatenation of the seed and public key) */
330                        const CCEcEdwDomain_t *pEcDomain,      /*!< [in] pointer to EDW EC domain (curve). */
331                        CCEcEdwTempBuff_t *pEcEdwSignTempBuff)   /*!< [in] pointer to the temp buffer. */
332 {
333 
334         CCError_t err = CC_OK;
335         size_t edwSizeWords = pEcDomain->ecOrdSizeInWords;
336         size_t edwSizeBytes = edwSizeWords * sizeof(uint32_t);
337         size_t hashSizeWords = CC_HASH_SHA512_DIGEST_SIZE_IN_BYTES / sizeof(uint32_t);
338         size_t sizeToHash, msgSize1;
339 
340         /* set pointers to temp buffers */
341         uint32_t *pPrivKey = (uint32_t*)pEcEdwSignTempBuff; /*h1||h2 = hash(seed)*/
342         uint32_t *pEphPriv = pPrivKey + edwSizeWords; /*nonce*/
343         uint32_t *pSign = pEphPriv + edwSizeWords; /*h2 is placed there for hash*/
344         uint32_t *pHash = pSign + 2*edwSizeWords; /*second part of */
345         uint32_t *pIntegrVal/*hram*/ = pHash + CC_HASH_SHA512_DIGEST_SIZE_IN_WORDS;
346 
347         const mbedtls_md_info_t *md_info=NULL;
348         mbedtls_md_context_t *p_hash_ctx = NULL;
349 
350         /*-------------------------------------------------*/
351         /*          Process signature calculation          */
352         /*-------------------------------------------------*/
353 
354         /* 1. Calculate hash512(seed) = pPrivKey||h2 for private key (for h2 temporary used pEphPrivKy buff) */
355         md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[CC_HASH_SHA512_mode] );
356         if (NULL == md_info) {
357                 err = CC_ECEDW_INTERNAL_ERROR;
358                 goto End;
359         }
360         err = mbedtls_md(md_info,
361                          (uint8_t*)pSignSecrKey,
362                          edwSizeBytes,
363                         (unsigned char *)pPrivKey);
364         if (err != CC_OK) {
365                 goto End; // h1 = 32 bytes of hash(seed) ;
366         }
367 
368         /* save privKey = h1 and set bits */
369         ((uint8_t*)pPrivKey)[0]  &= 248;
370         ((uint8_t*)pPrivKey)[edwSizeBytes-1] &= 63;
371         ((uint8_t*)pPrivKey)[edwSizeBytes-1] |= 64;
372 
373         /* 2. Calculate a nonce for ephemeral priv. key:  hash(h2||msg)  */
374         /*---------------------------------------------------------------*/
375         p_hash_ctx = (mbedtls_md_context_t*)(pIntegrVal + 2*edwSizeWords);
376         mbedtls_md_init(p_hash_ctx);
377         err = mbedtls_md_setup(p_hash_ctx, md_info, 0); // 0 = HASH, not HMAC
378         if (err != CC_OK) {
379                 goto End;
380         }
381         err = mbedtls_md_starts(p_hash_ctx);
382         if (err != CC_OK)
383                 goto End;
384 
385         if (msgSize == 0) {
386                 sizeToHash = edwSizeBytes;
387                 msgSize1 = 0;
388         } else {
389                 if (msgSize <= CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES - edwSizeBytes) {
390                         CC_PalMemCopy((uint8_t*)pEphPriv + edwSizeBytes, pMsg, msgSize);
391                         sizeToHash = edwSizeBytes + msgSize;
392                         msgSize1 = 0;
393                 } else {
394                         sizeToHash = CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES;
395                         CC_PalMemCopy((uint8_t*)pEphPriv + edwSizeBytes, pMsg, sizeToHash - edwSizeBytes);
396                         msgSize1 = msgSize - (sizeToHash - edwSizeBytes);
397                 }
398         }
399         err = mbedtls_md_update(p_hash_ctx, (uint8_t*)pEphPriv/*h2*/, sizeToHash);
400         if (err != CC_OK) /*full block, padded by msg*/
401                 goto End;
402 
403         if (msgSize1 > 0) {
404                 err = mbedtls_md_update(p_hash_ctx, (uint8_t*)pMsg+(sizeToHash - edwSizeBytes), msgSize1);
405                 if (err != CC_OK)   /*remaining bytes of the msg*/
406                         goto End;
407         }
408         err = mbedtls_md_finish(p_hash_ctx, (unsigned char *)pEphPriv);
409         if (err != CC_OK)
410                 goto End;
411 
412         mbedtls_md_free(p_hash_ctx);
413         p_hash_ctx = NULL;
414 
415         /*------------------------------------------*/
416         /*        PKA Initialization                */
417         /*------------------------------------------*/
418         /* get and lock the PKA hardware */
419         err = CC_PalMutexLock(&CCAsymCryptoMutex, CC_INFINITE);
420         if (err != CC_SUCCESS) {
421                 CC_PalAbort("Fail to acquire mutex\n");
422         }
423 
424         /* verify that the device is not in fatal error state before activating the PKA engine */
425         CC_IS_FATAL_ERR_ON(err);
426         if (err == CC_TRUE) {
427                 /* release the hardware semaphore */
428                 if (CC_PalMutexUnlock(&CCAsymCryptoMutex) != CC_SUCCESS) {
429                         CC_PalAbort("Fail to release mutex\n");
430                 }
431                 return PKA_FATAL_ERR_STATE_ERROR;
432         }
433 
434         /* increase CC counter at the beginning of each operation */
435         err = CC_IS_WAKE;
436         if (err != CC_SUCCESS) {
437             CC_PalAbort("Fail to increase PM counter\n");
438         }
439 
440         /* init PKA mapping according to 2*EC modulus size  */
441         err = PkaInitPka(2*CC_BITS_IN_32BIT_WORD*edwSizeWords,
442                          0/*regSizeInPkaWords*/, NULL/*pRegsCount*/);
443         if (err != CC_SUCCESS) {
444                 err = CC_ECEDW_INTERNAL_ERROR;
445                 goto End;
446         }
447 
448         /* 3. calculate reduced ephemer. priv. Key */
449         PkaCopyDataIntoPkaReg(EDW_REG_N, LEN_ID_N_PKA_REG_BITS, pEcDomain->ecOrdN, edwSizeWords);
450         PkaCopyDataIntoPkaReg(EDW_REG_EPH_PRIV, LEN_ID_N_PKA_REG_BITS, pEphPriv, hashSizeWords);
451         PKA_DIV(LEN_ID_N_PKA_REG_BITS, EDW_REG_T5/*4*/, EDW_REG_EPH_PRIV/*24*/, EDW_REG_N/*0*/);
452         PkaCopyDataFromPkaReg(pEphPriv/*dst*/, edwSizeWords, EDW_REG_EPH_PRIV/*srcReg*/);
453 
454         /* remapping of PKA registers and sizes for scalar mult. */
455         err = PkaInitPka(pEcDomain->ecModSizeInBits, pEcDomain->ecModSizeInWords, NULL);
456         if (err != CC_SUCCESS) {
457                 err = CC_ECEDW_INTERNAL_ERROR;
458                 goto End;
459         }
460 
461         /* 4. calculate ephemer. public key */
462         err = EcEdwScalarMultBase(
463                                  pSign+edwSizeWords, /*Eph.Publ. X*/
464                                  pSign,              /*Eph.Publ. Y*/
465                                  pEphPriv,           /*Eph.Priv. key*/
466                                  edwSizeWords,       /*scalarSize*/
467                                  pEcDomain);         /*Ec Domain*/
468         if (err) {
469                 goto End;
470         }
471 
472         /* convert eph. public key to compressed: MSBit(Y) = LSBit(X) */
473         pSign[edwSizeWords-1] ^= ((pSign[edwSizeWords] & 1) << 31);
474 
475         /* copy the user public key to the signature second half */
476         CC_PalMemCopy(((uint8_t*)pSign+edwSizeBytes), pSignSecrKey+edwSizeBytes, edwSizeBytes);
477 
478         /* 5. concatenate data for integrity value: EphPublKey || userPublKey || Msg */
479         /*---------------------------------------------------------------------------*/
480 
481         if (msgSize == 0) {
482                 sizeToHash = 2*edwSizeBytes;
483                 msgSize1 = 0;
484         } else {
485                 if (msgSize <= CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES - 2*edwSizeBytes) {
486                         CC_PalMemCopy((uint8_t*)pSign + 2*edwSizeBytes, pMsg, msgSize);
487                         sizeToHash = 2*edwSizeBytes + msgSize;
488                         msgSize1 = 0;
489                 } else {
490                         sizeToHash = CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES;
491                         CC_PalMemCopy((uint8_t*)pSign + 2*edwSizeBytes, pMsg, sizeToHash - 2*edwSizeBytes);
492                         msgSize1 = msgSize - 2*edwSizeBytes;
493                 }
494         }
495 
496         /* 6. calculate hash for integrity value */
497         p_hash_ctx = (mbedtls_md_context_t*)(pIntegrVal + 2*edwSizeWords);
498         mbedtls_md_init(p_hash_ctx);
499         err = mbedtls_md_setup(p_hash_ctx, md_info, 0); // 0 = HASH, not HMAC
500         if (err != CC_OK) {
501                 goto End;
502         }
503         err = mbedtls_md_starts(p_hash_ctx);
504         if (err != CC_OK)
505                 goto End;
506         err = mbedtls_md_update(p_hash_ctx, (uint8_t*)pSign, sizeToHash);
507         if (err != CC_OK)
508                 goto End;
509 
510         if (msgSize1 > 0) {
511                 err = mbedtls_md_update(p_hash_ctx, (uint8_t*)pMsg+2*edwSizeBytes, msgSize1);
512                 if (err != CC_OK)
513                         goto End;
514         }
515         err = mbedtls_md_finish(p_hash_ctx, (unsigned char *)pIntegrVal);
516         if (err != CC_OK)
517                 goto End;
518 
519         /* PKA registers remapping according to 2*EC order size  */
520         err = PkaInitPka(2*CC_BITS_IN_32BIT_WORD*edwSizeWords,
521                          0/*regSizeInPkaWords*/, NULL/*pRegsCount*/);
522         if (err != CC_SUCCESS) {
523                 err = CC_ECEDW_INTERNAL_ERROR;
524                 goto End;
525         }
526 
527         /* 7. set data to PKA registers and reduce integrity value */
528         PkaCopyDataIntoPkaReg(EDW_REG_N, LEN_ID_N_PKA_REG_BITS, pEcDomain->ecOrdN, edwSizeWords);
529         PkaCopyDataIntoPkaReg(EDW_REG_INTEGR, LEN_ID_N_PKA_REG_BITS, pIntegrVal, hashSizeWords);
530         PkaCopyDataIntoPkaReg(EDW_REG_USER_PRIV, LEN_ID_N_PKA_REG_BITS, pPrivKey, edwSizeWords);
531         PkaCopyDataIntoPkaReg(EDW_REG_EPH_PRIV, LEN_ID_N_PKA_REG_BITS, pEphPriv, edwSizeWords);
532         PkaCopyDataIntoPkaReg(EDW_REG_NP, LEN_ID_N_PKA_REG_BITS, pEcDomain->ecOrdBarrTag,
533                               CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
534 
535         PKA_DIV(LEN_ID_N_PKA_REG_BITS, EDW_REG_D2/*temp*/, EDW_REG_INTEGR, EDW_REG_N);
536 
537         /* set sizes for modMul op. according to actual size of the EC order  */
538         PKA_WAIT_ON_PKA_DONE();
539         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_L0), pEcDomain->ecOrdSizeInBits);
540         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, PKA_L0) + 4,
541                                 edwSizeWords*CC_BITS_IN_32BIT_WORD + CC_PKA_WORD_SIZE_IN_BITS);
542 
543 
544         /* 8. calculation of the Edw. specific signature value edwSignVal */
545         /*----------------------------------------------------------------*/
546         PKA_MOD_MUL(LEN_ID_N_BITS, EDW_REG_SIGN/*res*/, EDW_REG_INTEGR, EDW_REG_USER_PRIV);
547         PKA_MOD_ADD(LEN_ID_N_BITS, EDW_REG_SIGN/*res*/, EDW_REG_SIGN, EDW_REG_EPH_PRIV);
548         /* output EdwSignVal from PKA  */
549         PkaCopyDataFromPkaReg(&pSign[edwSizeWords]/*dst*/, edwSizeWords, EDW_REG_SIGN/*srcReg*/);
550         CC_PalMemCopy(pEdwSign, pSign, 2*edwSizeBytes);
551 
552         End:
553         if((md_info!=NULL) && (p_hash_ctx!=NULL)) {
554                 mbedtls_md_free(p_hash_ctx);
555         }
556         CC_PalMemSetZero(pEcEdwSignTempBuff, sizeof(CCEcEdwTempBuff_t));
557         PkaFinishAndMutexUnlock(CC_INFINITE);
558 
559         return err;
560 }
561 
562 /*********************************************************************/
563 /*!
564 @brief The function performs two EC Edwards scalar multiplication and adding
565        of points:  resPoint = scalarA * Point(X,Y) + scalarB * BasePointG.
566 
567        Assuming: - PKA is initialized yet (including setting N and NP in registers);
568                  - Input point may be given in uncompressed form (given both coord. X,Y)
569                    or in compressed form: coordinate Y only and LSBit of X on bit place,
570                    equalled to modulus size in bits (255 for ec25519).
571 
572  @return CCError_t
573 */
EcEdwAddTwoScalarMult(uint32_t * pResPoint,uint32_t * pScalarA,uint32_t * pPointY,uint32_t * pPointX,uint32_t * pScalarB,const CCEcEdwDomain_t * pEcDomain)574 CCError_t EcEdwAddTwoScalarMult(
575                                  uint32_t *pResPoint,        /*!< [out] the pointer to the result point in compressed
576                                                                  form (coordinate Y, the size in bytes = ec modulus size). */
577                                  uint32_t *pScalarA,         /*!< [in] pointer to the scalarA, the size = ec modulus size in bytes). */
578                                  uint32_t *pPointY,          /*!< [in] a pointer to the input point coordinate Y - in uncompressed
579                                                                  form, if given coordinate X, or in compressed form if coordinate
580                                                                  X == NULL (the size of Y in bytes = ec modulus size). */
581                                  uint32_t *pPointX,          /*!< [in, optional] the pointer to input point coordinate X for uncompressed
582                                                                  form of point(the size of Y in bytes = ec modulus size). */
583                                  uint32_t *pScalarB,         /*!< [in] pointer to the scalarB, the size = ec modulus sizein bytes). */
584                                  const CCEcEdwDomain_t *pEcDomain /*!< [in] pointer to EC domain (curve). */)
585 {
586         CCError_t err = CC_OK;
587         size_t edwSizeWords;
588         size_t scalarAsizeBits, scalarBsizeBits;
589         uint32_t isOddX = 0, shift;
590 
591         /* count of bits for MS bit setting of Y coordinate */
592         shift = 31;
593 
594         /* get bit sizes of scalars */
595         edwSizeWords = pEcDomain->ecModSizeInWords;
596         scalarAsizeBits = CC_CommonGetWordsCounterEffectiveSizeInBits( pScalarA, edwSizeWords);
597         scalarBsizeBits = CC_CommonGetWordsCounterEffectiveSizeInBits( pScalarB, edwSizeWords);
598 
599         /*   pEcDomain modulus and Barr. tag and input point X,Y */
600         PkaCopyDataIntoPkaReg(EDW_REG_N, LEN_ID_MAX_BITS, pEcDomain->ecModP, edwSizeWords);
601         PkaCopyDataIntoPkaReg(EDW_REG_NP, LEN_ID_MAX_BITS, pEcDomain->ecModBarrTag,
602                               CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
603         /*--------------------------------------------------------------*/
604         /* decompression of input point, if given in compressed form    */
605         /*--------------------------------------------------------------*/
606         if (pPointX == NULL) {
607                 /* load EC params data into PKA */
608                 PkaCopyDataIntoPkaReg(EDW_REG_D, LEN_ID_MAX_BITS, pEcDomain->ecParamD, edwSizeWords);
609                 PkaCopyDataIntoPkaReg(EDW_REG_Q58, LEN_ID_MAX_BITS, pEcDomain->ecAuxValQ58, edwSizeWords);
610                 PkaCopyDataIntoPkaReg(EDW_REG_SQRTM1, LEN_ID_MAX_BITS, pEcDomain->ecAuxValSqrt_1, edwSizeWords);
611 
612                 /* extract LSBit of X from compressed Y */
613                 isOddX = (pPointY[edwSizeWords-1] >> shift) & 1;
614                 pPointY[edwSizeWords-1] &= ~(1UL << shift); /*clean MSBit in Y-buffer*/
615 
616                 /* load point coord. Y into PKA */
617                 PkaCopyDataIntoPkaReg(EDW_REG_YP, LEN_ID_MAX_BITS, pPointY/*Y*/, edwSizeWords);
618 
619                 /* decompress input Point (in/out registers: EDW_REG_YP - in, EDW_REG_XP - out) */
620                 PkaEcEdwDecompress(EDW_REG_XP, EDW_REG_YP, isOddX);
621 
622         } else {
623                 /* load point coord. X,Y data */
624                 PkaCopyDataIntoPkaReg(EDW_REG_YP, LEN_ID_MAX_BITS, pPointY/*Y*/, edwSizeWords);
625                 PkaCopyDataIntoPkaReg(EDW_REG_XP, LEN_ID_MAX_BITS, pPointX/*Y*/, edwSizeWords);
626         }
627 
628         /* call EC scalar mult. add function with implicitly defined registers:
629            input aff. point P is in registers: (EDW_REG_XP, EDW_REG_YP)
630            output aff. point R is in registers: (EDW_REG_XR, EDW_REG_YR) */
631         err = PkaEcEdwAddTwoScalarMult(
632                                       EDW_REG_XR, EDW_REG_YR,
633                                       EDW_REG_XP, EDW_REG_YP,
634                                       pScalarA, scalarAsizeBits,
635                                       pScalarB, scalarBsizeBits,
636                                       pEcDomain);
637         if (err != CC_OK)
638                 goto End;
639 
640 
641         /* output result point in compressed form Y */
642         PkaCopyDataFromPkaReg(pResPoint/*dst*/, edwSizeWords, EDW_REG_XR/*srcReg*/); /*X*/
643         /* get bit b'0 of XR */
644         PKA_READ_BIT0(LEN_ID_MAX_BITS, EDW_REG_XR, isOddX);
645         PkaCopyDataFromPkaReg(pResPoint/*dst*/, edwSizeWords, EDW_REG_YR/*srcReg*/); /*Y*/
646         /* set MSbit YR =  b'0 XR */
647         if(pPointX == NULL) {
648                 pResPoint[edwSizeWords-1] |= (isOddX << shift);
649         }
650 
651         End:
652         return err;
653 }
654 
655 
656 /**
657  * The function verifies EC Edwards detatched signature on given message
658  *
659  * Implemented algorithm of Bernstein D. etc.
660  *
661  * @author reuvenl (1/21/2016)
662  *
663  * @return CCError_t
664  */
EcEdwSignVerify(const uint8_t * pInSign,const uint8_t * pMsg,size_t msgSize,const uint8_t * pSignPublKey,const CCEcEdwDomain_t * pEcDomain,CCEcEdwTempBuff_t * pEcEdwTempBuff)665 CCError_t  EcEdwSignVerify (
666                         const uint8_t *pInSign,              /*!< [in] - the pointer to input signature. */
667                         const uint8_t *pMsg,                 /*!< [in] - the pointer to the message. */
668                         size_t         msgSize,              /*!< [in] - the message size in bytes: it must not great
669                                                                   than CC_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES. */
670                         const uint8_t *pSignPublKey,         /*!< [in] - the pointer to the signer public key, stated
671                                                                   in compressed form of coordinate Y */
672                         const CCEcEdwDomain_t *pEcDomain,  /*!< [in] pointer to EDW EC domain (curve). */
673                         CCEcEdwTempBuff_t *pEcEdwTempBuff) /*!< [in] pointer to the temp buffer. */
674 {
675 
676         CCError_t err = CC_OK;
677         size_t edwSizeWords = pEcDomain->ecModSizeInWords;
678         size_t edwSizeBytes = edwSizeWords * sizeof(uint32_t);
679         size_t hashSizeWords = CC_HASH_SHA512_DIGEST_SIZE_IN_BYTES / sizeof(uint32_t);
680         uint32_t sizeToHash, msgSize1;
681         /* set pointers to 32-bit aligned buffers */
682         uint32_t *pSign = (uint32_t*)pEcEdwTempBuff;
683         /* next uses the same buff */
684         uint32_t *pIntegrVal = pSign/*hram*/;
685         uint32_t *pPublKeyY = pIntegrVal + edwSizeWords;
686         uint32_t *pEdwSignVal = pPublKeyY + edwSizeWords;
687         uint32_t *pEphPubl = pEdwSignVal + edwSizeWords;
688         uint32_t *pResPoint = pEphPubl + edwSizeWords; /*use previous buff*/
689 
690         const mbedtls_md_info_t *md_info=NULL;
691         mbedtls_md_context_t *p_hash_ctx = (mbedtls_md_context_t*)(pResPoint + 2*edwSizeWords);;
692 
693         /* get and lock the PKA hardware */
694         err = CC_PalMutexLock(&CCAsymCryptoMutex, CC_INFINITE);
695         if (err != CC_SUCCESS) {
696                 CC_PalAbort("Fail to acquire mutex\n");
697         }
698 
699         /* verify that the device is not in fatal error state before activating the PKA engine */
700         CC_IS_FATAL_ERR_ON(err);
701         if (err == CC_TRUE) {
702                 /* release the hardware semaphore */
703                 if (CC_PalMutexUnlock(&CCAsymCryptoMutex) != CC_SUCCESS) {
704                         CC_PalAbort("Fail to release mutex\n");
705                 }
706                 return PKA_FATAL_ERR_STATE_ERROR;
707         }
708 
709         /* increase CC counter at the beginning of each operation */
710         err = CC_IS_WAKE;
711         if (err != CC_SUCCESS) {
712             CC_PalAbort("Fail to increase PM counter\n");
713         }
714 
715         /*-------------------------------------------------*/
716         /*          Process signature verification         */
717         /*-------------------------------------------------*/
718 
719         /* check that EdwSignValue have two MS bits = 0 */
720         if (pInSign[2*edwSizeBytes - 1] >> ((pEcDomain->ecModSizeInBits % CC_BITS_IN_32BIT_WORD) - 2)) {
721                 return CC_EC_EDW_SIGN_VERIFY_FAILED_ERROR;
722         }
723 
724         /* check that publ.key != 0 */
725         if (PkiIsUint8ArrayEqualTo0(pSignPublKey, edwSizeBytes)) {
726 
727                 return CC_EC_EDW_SIGN_VERIFY_FAILED_ERROR;
728         }
729 
730         /* create integrity value on: EphPublKey || userPublKey || Msg */
731         /*-------------------------------------------------------------*/
732 
733         /* copy input EphPublKey||userPublKey to aligned buffer as bytes */
734         CC_PalMemCopy((uint8_t*)pSign, pInSign, edwSizeBytes);
735         CC_PalMemCopy((uint8_t*)pSign + edwSizeBytes, pSignPublKey, edwSizeBytes);
736 
737         if (msgSize == 0) {
738                 sizeToHash = 2*edwSizeBytes;
739                 msgSize1 = 0;
740         } else {
741                 if (msgSize <= CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES - 2*edwSizeBytes) {
742                         CC_PalMemCopy((uint8_t*)pSign + 2*edwSizeBytes, pMsg, msgSize);
743                         sizeToHash = 2*edwSizeBytes + msgSize;
744                         msgSize1 = 0;
745                 } else {
746                         sizeToHash = CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES;
747                         CC_PalMemCopy((uint8_t*)pSign + 2*edwSizeBytes, pMsg, sizeToHash - 2*edwSizeBytes);
748                         msgSize1 = msgSize - (sizeToHash - 2*edwSizeBytes);
749                 }
750         }
751 
752         /*         HASH operations      */
753         /*------------------------------*/
754         md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[CC_HASH_SHA512_mode] );
755         if (NULL == md_info) {
756                 err = CC_EC_EDW_SIGN_VERIFY_FAILED_ERROR;
757                 goto End;
758         }
759         mbedtls_md_init(p_hash_ctx);
760         err = mbedtls_md_setup(p_hash_ctx, md_info, 0); // 0 = HASH, not HMAC
761         if (err != CC_OK) {
762                 goto End;
763         }
764         err = mbedtls_md_starts(p_hash_ctx);
765         if (err != CC_OK)
766                 goto End;
767 
768         err = mbedtls_md_update(p_hash_ctx, (uint8_t*)pSign/*h2*/, sizeToHash);
769         if (err != CC_OK) /*full block, padded by msg*/
770                 goto End;
771 
772         if (msgSize1 > 0) {
773                 err = mbedtls_md_update(p_hash_ctx, (uint8_t*)pMsg+(sizeToHash - 2*edwSizeBytes), msgSize1);
774                 if (err != CC_OK)   /*remaining bytes of the msg*/
775                         goto End;
776         }
777         err = mbedtls_md_finish(p_hash_ctx, (unsigned char *)pSign);
778         if (err != CC_OK)
779                 goto End;
780 
781         /* reduce IntegrVal by EC order, set result into EDW_REG_INTEGR  */
782         /*---------------------------------------------------------------*/
783 
784         /* init PKA mapping and sizes tables according to 2 modulus size */
785         err = PkaInitPka(CC_HASH_SHA512_DIGEST_SIZE_IN_BYTES*CC_BITS_IN_BYTE,
786                          0/*RegSizeInWords*/, NULL);
787         if (err != CC_SUCCESS) {
788                 err = CC_ECEDW_INTERNAL_ERROR;
789                 goto End;
790         }
791 
792         /* load IntegrVal and mod.P into paired register for each parameter */
793         PkaCopyDataIntoPkaReg(EDW_REG_INTEGR, LEN_ID_N_PKA_REG_BITS, pSign/*IntegrVal*/, hashSizeWords);
794         PkaCopyDataIntoPkaReg(EDW_REG_N, LEN_ID_N_PKA_REG_BITS, pEcDomain->ecOrdN, edwSizeWords);
795         /* reduce by order */
796         PKA_DIV(LEN_ID_N_PKA_REG_BITS, EDW_REG_T5/*4 not used*/, EDW_REG_INTEGR/*3*/, EDW_REG_N);
797         /* output reduced EphPrivKey */
798         PkaCopyDataFromPkaReg(pIntegrVal/*dst*/, edwSizeWords, EDW_REG_INTEGR/*srcReg*/);
799 
800         /* init PKA mapping and sizes tables according to EC modulus size */
801         /*----------------------------------------------------------------*/
802         err = PkaInitPka(pEcDomain->ecModSizeInBits, 0/*pEcDomain->ecModSizeInWords*/, NULL);
803         if (err != CC_SUCCESS) {
804                 err = CC_ECEDW_INTERNAL_ERROR;
805                 goto End;
806         }
807 
808         /* set the user publ. key as words and negate it */
809         CC_CommonConvertLsbMsbBytesToLswMswWords(pPublKeyY, pSignPublKey, edwSizeBytes);
810         pPublKeyY[edwSizeWords-1] ^= (1UL << 31);
811 
812         CC_CommonConvertLsbMsbBytesToLswMswWords(pEdwSignVal, &pInSign[edwSizeBytes], edwSizeBytes);
813 
814         /* perform two scalar mult. with adding: ("**" - scalar mult)
815             ResPoint = pIntegrVal**PublKey + EdwSignVal**EcBasePoint */
816         err = EcEdwAddTwoScalarMult(
817                                    pResPoint,
818                                    pIntegrVal/*scalarA*/,
819                                    pPublKeyY, NULL/*pPublKeyX*/,
820                                    pEdwSignVal/*scalarB*/,
821                                    pEcDomain);
822         if (err) {
823                 goto End;
824         }
825 
826         /* specific verification of the Edw. signature  */
827         CC_CommonConvertLsbMsbBytesToLswMswWords(pEphPubl, pInSign, edwSizeBytes);
828 
829         if (!PkiAreBuffersEqual(pResPoint, pEphPubl, edwSizeBytes)) {
830                 err = CC_EC_EDW_SIGN_VERIFY_FAILED_ERROR;
831                 goto End;
832         }
833 
834         End:
835         if(md_info!=NULL){
836                 mbedtls_md_free(p_hash_ctx);
837         }
838 
839         CC_PalMemSetZero(pEcEdwTempBuff, sizeof(CCEcEdwTempBuff_t));
840 
841         PkaFinishAndMutexUnlock(CC_INFINITE);
842 
843         return err;
844 }
845 
846 
847