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