1 /***************************************************************************//**
2 * \file cy_crypto_core_ecc_ecdsa.c
3 * \version 2.120
4 *
5 * \brief
6 * This file provides constant and parameters for the API for the ECC ECDSA
7 * in the Crypto driver.
8 *
9 ********************************************************************************
10 * \copyright
11 * Copyright (c) (2020-2022), Cypress Semiconductor Corporation (an Infineon company) or
12 * an affiliate of Cypress Semiconductor Corporation.
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27
28 #include "cy_device.h"
29
30 #if defined (CY_IP_MXCRYPTO)
31
32 #include "cy_crypto_core_ecc.h"
33
34 #if defined(__cplusplus)
35 extern "C" {
36 #endif
37
38 #if defined(CY_CRYPTO_CFG_ECDSA_C)
39
40 #include "cy_crypto_core_ecc_nist_p.h"
41 #include "cy_crypto_core_mem.h"
42 #include "cy_crypto_core_vu.h"
43
44 #if defined(CY_CRYPTO_CFG_ECDSA_SIGN_C)
45 /*******************************************************************************
46 * Function Name: Cy_Crypto_Core_ECC_SignHash
47 ****************************************************************************//**
48 *
49 * Sign a message digest.
50 *
51 * For CAT1C & CAT1D devices when D-Cache is enabled parameters hash, sign, messageKey and key( k, x&y of pubkey) must align and end in 32 byte boundary.
52 *
53 * \param base
54 * The pointer to a Crypto instance.
55 *
56 * \param hash
57 * The message digest to sign. Provided as is in data buffer.
58 *
59 * \param hashlen
60 * The length of the digest in bytes.
61 *
62 * \param sig
63 * [out] The destination for the signature, 'r' followed by 's'.
64 *
65 * \param key
66 * Key used for signature generation. See \ref cy_stc_crypto_ecc_key.
67 *
68 * \param messageKey
69 * Message key.
70 *
71 * \return status code. See \ref cy_en_crypto_status_t.
72 *
73 *******************************************************************************/
Cy_Crypto_Core_ECC_SignHash(CRYPTO_Type * base,const uint8_t * hash,uint32_t hashlen,uint8_t * sig,const cy_stc_crypto_ecc_key * key,const uint8_t * messageKey)74 cy_en_crypto_status_t Cy_Crypto_Core_ECC_SignHash(CRYPTO_Type *base, const uint8_t *hash, uint32_t hashlen, uint8_t *sig,
75 const cy_stc_crypto_ecc_key *key, const uint8_t *messageKey)
76 {
77 cy_en_crypto_status_t tmpResult = CY_CRYPTO_BAD_PARAMS;
78
79 cy_stc_crypto_ecc_key ephKey;
80
81 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
82 CY_ALIGN(__SCB_DCACHE_LINE_SIZE) static uint8_t myKGX[CY_CRYPTO_ECC_MAX_BYTE_SIZE];
83 CY_ALIGN(__SCB_DCACHE_LINE_SIZE) static uint8_t myKGY[CY_CRYPTO_ECC_MAX_BYTE_SIZE];
84 #else
85 uint8_t myKGX[CY_CRYPTO_ECC_MAX_BYTE_SIZE];
86 uint8_t myKGY[CY_CRYPTO_ECC_MAX_BYTE_SIZE];
87 #endif
88
89 uint8_t *sigPtrRemap;
90 uint8_t *hashPtrRemap;
91 uint8_t *keyKRemap;
92 uint8_t *messageKeyPtrRemap;
93
94
95 const cy_stc_crypto_ecc_dp_type *eccDp;
96 uint32_t mallocMask = 0U;
97
98
99 /* NULL parameters checking */
100 if ((hash != NULL) && (0u != hashlen) && (sig != NULL) && (key != NULL) && (messageKey != NULL))
101 {
102 tmpResult = CY_CRYPTO_NOT_SUPPORTED;
103
104 hashPtrRemap = (uint8_t *)CY_REMAP_ADDRESS_FOR_CRYPTO(hash);
105 sigPtrRemap = (uint8_t *)CY_REMAP_ADDRESS_FOR_CRYPTO(sig);
106 messageKeyPtrRemap = (uint8_t *)CY_REMAP_ADDRESS_FOR_CRYPTO(messageKey);
107 keyKRemap = (uint8_t *)CY_REMAP_ADDRESS_FOR_CRYPTO(key->k);
108
109 eccDp = Cy_Crypto_Core_ECC_GetCurveParams(key->curveID);
110
111 if (eccDp != NULL)
112 {
113 uint32_t bitsize = eccDp->size;
114 uint32_t bytesize = CY_CRYPTO_BYTE_SIZE_OF_BITS(eccDp->size);
115 uint32_t datasize = hashlen;
116
117 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
118 /* Flush the cache */
119 SCB_CleanDCache_by_Addr((volatile void *)hash,(int32_t)hashlen);
120 SCB_CleanDCache_by_Addr((volatile void *)key->k, (int32_t)bytesize);
121 SCB_CleanDCache_by_Addr((volatile void *)messageKey,(int32_t)bytesize);
122 #endif
123
124 /* make ephemeral key pair */
125 ephKey.pubkey.x = CY_REMAP_ADDRESS_FOR_CRYPTO(myKGX);
126 ephKey.pubkey.y = CY_REMAP_ADDRESS_FOR_CRYPTO(myKGY);
127
128 tmpResult = Cy_Crypto_Core_ECC_MakePublicKey(base, key->curveID, messageKeyPtrRemap, &ephKey);
129
130 if (CY_CRYPTO_SUCCESS == tmpResult)
131 {
132 uint32_t dividend = 0U; /* for whatever reason Crypto_EC_DivMod only works if dividend is in register 0 */
133 uint32_t p_temp = 8U;
134 uint32_t p_r = 9U;
135 uint32_t p_s = 10U;
136 uint32_t p_d = 11U;
137 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
138 /* Flush the cache */
139 SCB_CleanDCache_by_Addr((volatile void *)ephKey.pubkey.x,(int32_t)bytesize);
140 SCB_CleanDCache_by_Addr((volatile void *)ephKey.pubkey.y, (int32_t)bytesize);
141 #endif
142 /* load values needed for reduction modulo order of the base point */
143 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, VR_P, bitsize);
144 if(CY_CRYPTO_SUCCESS != tmpResult)
145 {
146 return tmpResult;
147 }
148
149 Cy_Crypto_Core_Vu_SetMemValue (base, VR_P, (uint8_t const *)CY_REMAP_ADDRESS_FOR_CRYPTO(eccDp->order), bitsize);
150
151 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, VR_BARRETT, bitsize + 1U);
152 if(CY_CRYPTO_SUCCESS != tmpResult)
153 {
154 return tmpResult;
155 }
156
157 Cy_Crypto_Core_Vu_SetMemValue (base, VR_BARRETT, (uint8_t const*)CY_REMAP_ADDRESS_FOR_CRYPTO(eccDp->barrett_o), bitsize);
158
159 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_r, bitsize);
160 if(CY_CRYPTO_SUCCESS != tmpResult)
161 {
162 return tmpResult;
163 }
164
165 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_s, bitsize);
166 if(CY_CRYPTO_SUCCESS != tmpResult)
167 {
168 return tmpResult;
169 }
170
171 Cy_Crypto_Core_Vu_SetMemValue (base, p_r, (uint8_t *)ephKey.pubkey.x, bitsize);
172
173 mallocMask = CY_CRYPTO_VU_REG_BIT(VR_P) | CY_CRYPTO_VU_REG_BIT(VR_BARRETT) |
174 CY_CRYPTO_VU_REG_BIT(p_r) | CY_CRYPTO_VU_REG_BIT(p_s);
175
176 if (!Cy_Crypto_Core_Vu_IsRegZero(base, p_r))
177 {
178 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_temp, bitsize);
179 if(CY_CRYPTO_SUCCESS != tmpResult)
180 {
181 return tmpResult;
182 }
183
184 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_d, datasize * 8u);
185 if(CY_CRYPTO_SUCCESS != tmpResult)
186 {
187 return tmpResult;
188 }
189
190 /* check that x1 is smaller than the order of the base point */
191 if (!Cy_Crypto_Core_Vu_IsRegLess(base, p_r, VR_P))
192 {
193 /* x1 >= order, needs reduction */
194 CY_CRYPTO_VU_MOV(base, p_temp, p_r);
195 Cy_Crypto_Core_Vu_WaitForComplete(base);
196
197 /* z = x % mod */
198 tmpResult = Cy_Crypto_Core_EC_Bar_MulRed(base, p_r, p_temp, bitsize);
199 if(CY_CRYPTO_SUCCESS != tmpResult)
200 {
201 return tmpResult;
202 }
203
204 /* r = x1 mod n */
205 Cy_Crypto_Core_Vu_GetMemValue (base, sigPtrRemap, p_r, bitsize);
206
207 if (Cy_Crypto_Core_Vu_IsRegZero(base, p_r))
208 {
209 /* R is zero!!! */
210 tmpResult = CY_CRYPTO_HW_ERROR;
211 }
212 }
213 else
214 {
215 /* carry is clear, i. e. x1 < order, r = x1 */
216 Cy_Crypto_Core_Vu_GetMemValue(base, sigPtrRemap, p_r, bitsize);
217 }
218
219 if (CY_CRYPTO_SUCCESS == tmpResult)
220 {
221 /* find s = (e + d*r)/k */
222 /* load signing private key */
223 Cy_Crypto_Core_Vu_SetMemValue (base, p_temp, (uint8_t *)keyKRemap, bitsize);
224
225 /* use Barrett reduction algorithm for operations modulo n (order of the base point) */
226 Cy_Crypto_Core_EC_NistP_SetRedAlg(CY_CRYPTO_NIST_P_BARRETT_RED_ALG);
227
228 /* d*r mod n */
229 tmpResult = Cy_Crypto_Core_EC_MulMod(base, p_s, p_temp, p_r, bitsize); /* z = a * b % mod */
230 if(CY_CRYPTO_SUCCESS != tmpResult)
231 {
232 return tmpResult;
233 }
234 /* load message hash, truncate it if needed. */
235 Cy_Crypto_Core_Vu_SetMemValue (base, p_d, (uint8_t *)hashPtrRemap, datasize * 8u);
236 Cy_Crypto_Core_VU_RegInvertEndianness(base, p_d);
237
238 if ((datasize * 8u) > bitsize)
239 {
240 CY_CRYPTO_VU_SET_REG(base, dividend, (datasize * 8u) - bitsize, 1u);
241 CY_CRYPTO_VU_LSR(base, p_d, p_d, dividend);
242 }
243
244 /* check that the prepared hash value is smaller than the order of base point */
245 if (!Cy_Crypto_Core_Vu_IsRegLess(base, p_d, VR_P))
246 {
247 CY_CRYPTO_VU_MOV(base, p_temp, p_d);
248 Cy_Crypto_Core_Vu_WaitForComplete(base);
249
250 /* z = x % mod */
251 tmpResult = Cy_Crypto_Core_EC_Bar_MulRed(base, p_d, p_temp, bitsize);
252 if(CY_CRYPTO_SUCCESS != tmpResult)
253 {
254 return tmpResult;
255 }
256 }
257
258 /* Use p_r as temporary register */
259 Cy_Crypto_Core_Vu_SetMemValue (base, p_r, messageKeyPtrRemap, bitsize);
260
261 /* e + d*r mod n */
262 Cy_Crypto_Core_EC_AddMod (base, p_s, p_d, p_s); /* z = a + b % mod */
263
264 /* (e + d*r)/k mod n */
265 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, dividend, bitsize);
266 if(CY_CRYPTO_SUCCESS != tmpResult)
267 {
268 return tmpResult;
269 }
270 CY_CRYPTO_VU_MOV(base, dividend, p_s);
271 Cy_Crypto_Core_Vu_WaitForComplete(base);
272
273 /* z = a / b % mod */
274 tmpResult = Cy_Crypto_Core_EC_DivMod(base, p_s, dividend, p_r, bitsize);
275 if(CY_CRYPTO_SUCCESS != tmpResult)
276 {
277 return tmpResult;
278 }
279
280 CY_CRYPTO_VU_FREE_MEM(base, CY_CRYPTO_VU_REG_BIT(dividend));
281
282 if (!Cy_Crypto_Core_Vu_IsRegZero(base, p_s))
283 {
284 /* S is not zero!!! */
285 Cy_Crypto_Core_Vu_GetMemValue (base, &sigPtrRemap[bytesize], p_s, bitsize);
286 }
287 else
288 {
289 tmpResult = CY_CRYPTO_HW_ERROR;
290 }
291 }
292
293 CY_CRYPTO_VU_FREE_MEM(base, CY_CRYPTO_VU_REG_BIT(p_d) | CY_CRYPTO_VU_REG_BIT(p_temp));
294 }
295
296 CY_CRYPTO_VU_FREE_MEM(base, mallocMask);
297 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
298 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to int32_t.');
299 SCB_InvalidateDCache_by_Addr(sig, (int32_t)(bytesize*2U));
300 #endif
301 }
302 }
303 }
304
305 return (tmpResult);
306 }
307 #endif /* defined(CY_CRYPTO_CFG_ECDSA_SIGN_C) */
308
309 #if defined(CY_CRYPTO_CFG_ECDSA_VERIFY_C)
310 /*******************************************************************************
311 * Function Name: Cy_Crypto_Core_ECC_VerifyHash
312 ****************************************************************************//**
313 *
314 * Verify an ECC signature.
315 *
316 * For CAT1C & CAT1D devices when D-Cache is enabled parameters sig, hash and key( x&y of pubkey) must align and end in 32 byte boundary.
317 *
318 * \param base
319 * The pointer to a Crypto instance.
320 *
321 * \param sig
322 * The signature to verify, 'R' followed by 'S'.
323 *
324 * \param hash
325 * The hash (message digest) that was signed.
326 *
327 * \param hashlen
328 * The length of the hash (octets).
329 *
330 * \param stat
331 * Result of signature, 1==valid, 0==invalid.
332 *
333 * \param key
334 * The corresponding public ECC key. See \ref cy_stc_crypto_ecc_key.
335 *
336 * \return status code. See \ref cy_en_crypto_status_t.
337 *
338 *******************************************************************************/
Cy_Crypto_Core_ECC_VerifyHash(CRYPTO_Type * base,const uint8_t * sig,const uint8_t * hash,uint32_t hashlen,uint8_t * stat,const cy_stc_crypto_ecc_key * key)339 cy_en_crypto_status_t Cy_Crypto_Core_ECC_VerifyHash(CRYPTO_Type *base,
340 const uint8_t *sig, const uint8_t *hash, uint32_t hashlen,
341 uint8_t *stat, const cy_stc_crypto_ecc_key *key)
342 {
343 cy_en_crypto_status_t tmpResult = CY_CRYPTO_BAD_PARAMS;
344
345 const cy_stc_crypto_ecc_dp_type *eccDp;
346
347 uint32_t mallocMask = 0U;
348 bool isHashZero = false;
349
350 uint8_t *sigPtrRemap;
351 uint8_t *hashPtrRemap;
352 uint8_t *pubKeyXRemap;
353 uint8_t *pubKeyYRemap;
354
355 /* NULL parameters checking */
356 if ((sig != NULL) && (hash != NULL) && (0u != hashlen) && (stat != NULL) && (key != NULL))
357 {
358 tmpResult = CY_CRYPTO_NOT_SUPPORTED;
359
360 hashPtrRemap = (uint8_t *)CY_REMAP_ADDRESS_FOR_CRYPTO(hash);
361 sigPtrRemap = (uint8_t *)CY_REMAP_ADDRESS_FOR_CRYPTO(sig);
362 pubKeyXRemap = (uint8_t *)CY_REMAP_ADDRESS_FOR_CRYPTO(key->pubkey.x);
363 pubKeyYRemap = (uint8_t *)CY_REMAP_ADDRESS_FOR_CRYPTO(key->pubkey.y);
364
365 eccDp = Cy_Crypto_Core_ECC_GetCurveParams(key->curveID);
366
367 if (eccDp != NULL)
368 {
369 uint32_t bitsize = eccDp->size;
370 uint32_t bytesize = CY_CRYPTO_BYTE_SIZE_OF_BITS(eccDp->size);
371 uint32_t datasize = hashlen;
372
373 uint32_t dividend = 0u; /* for whatever reason Crypto_EC_DivMod only works if dividend is in register 0 */
374 uint32_t p_r = 4U;
375 uint32_t p_s = 5U;
376 uint32_t p_u1 = 6U;
377 uint32_t p_u2 = 7U;
378 uint32_t p_o = 8U;
379 uint32_t p_gx = 9U;
380 uint32_t p_gy = 10U;
381 uint32_t p_qx = 11U;
382 uint32_t p_qy = 12U;
383 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
384 /* Flush the cache */
385 SCB_CleanDCache_by_Addr((volatile void *)hash,(int32_t)hashlen);
386 SCB_CleanDCache_by_Addr((volatile void *)key->pubkey.x, (int32_t)bytesize);
387 SCB_CleanDCache_by_Addr((volatile void *)key->pubkey.y, (int32_t)bytesize);
388 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to int32_t.');
389 SCB_CleanDCache_by_Addr((volatile void *)sig,(int32_t)(2u*bytesize));
390 SCB_CleanDCache_by_Addr((volatile void *)eccDp->order,(int32_t)bytesize);
391 SCB_CleanDCache_by_Addr((volatile void *)eccDp->Gx,(int32_t)bytesize);
392 SCB_CleanDCache_by_Addr((volatile void *)eccDp->Gy,(int32_t)bytesize);
393 SCB_CleanDCache_by_Addr((volatile void *)eccDp->prime,(int32_t)bytesize);
394 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to int32_t.');
395 SCB_CleanDCache_by_Addr((volatile void *)eccDp->barrett_o,(int32_t)(bytesize+1u));
396 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to int32_t.');
397 SCB_CleanDCache_by_Addr((volatile void *)eccDp->barrett_p,(int32_t)(bytesize+1u));
398 #endif
399 /* use Barrett reduction algorithm for operations modulo n (order of the base point) */
400 Cy_Crypto_Core_EC_NistP_SetRedAlg(CY_CRYPTO_NIST_P_BARRETT_RED_ALG);
401 Cy_Crypto_Core_EC_NistP_SetMode(bitsize);
402
403 /*******************************************************************************/
404 /* load values needed for reduction modulo order of the base point */
405 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, VR_P, bitsize);
406 if(CY_CRYPTO_SUCCESS != tmpResult)
407 {
408 return tmpResult;
409 }
410 Cy_Crypto_Core_Vu_SetMemValue (base, VR_P, (uint8_t const *)CY_REMAP_ADDRESS_FOR_CRYPTO(eccDp->order), bitsize);
411
412 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, VR_BARRETT, bitsize + 1U);
413 if(CY_CRYPTO_SUCCESS != tmpResult)
414 {
415 return tmpResult;
416 }
417 Cy_Crypto_Core_Vu_SetMemValue (base, VR_BARRETT, (uint8_t const *)CY_REMAP_ADDRESS_FOR_CRYPTO(eccDp->barrett_o), bitsize + 1U);
418
419 /*******************************************************************************/
420 /* check that R and S are within the valid range, i.e. 0 < R < n and 0 < S < n */
421 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_r, bitsize);
422 if(CY_CRYPTO_SUCCESS != tmpResult)
423 {
424 return tmpResult;
425 }
426
427 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_s, bitsize);
428 if(CY_CRYPTO_SUCCESS != tmpResult)
429 {
430 return tmpResult;
431 }
432
433 Cy_Crypto_Core_Vu_SetMemValue (base, p_r, (uint8_t *)sigPtrRemap, bitsize);
434 Cy_Crypto_Core_Vu_SetMemValue (base, p_s, (uint8_t *)&sigPtrRemap[bytesize], bitsize);
435
436 mallocMask = CY_CRYPTO_VU_REG_BIT(VR_P) | CY_CRYPTO_VU_REG_BIT(VR_BARRETT) |
437 CY_CRYPTO_VU_REG_BIT(p_r) | CY_CRYPTO_VU_REG_BIT(p_s);
438
439 /* Check R and S range */
440 if (Cy_Crypto_Core_Vu_IsRegZero(base, p_r))
441 {
442 /* R is zero!!! */
443 tmpResult = CY_CRYPTO_BAD_PARAMS;
444 }
445 if (!Cy_Crypto_Core_Vu_IsRegLess(base, p_r, VR_P))
446 {
447 /* R is not less than n!!! */
448 tmpResult = CY_CRYPTO_BAD_PARAMS;
449 }
450 if (Cy_Crypto_Core_Vu_IsRegZero(base, p_s))
451 {
452 /* S is zero!!! */
453 tmpResult = CY_CRYPTO_BAD_PARAMS;
454 }
455 if (!Cy_Crypto_Core_Vu_IsRegLess(base, p_s, VR_P))
456 {
457 /* S is not less than n!!! */
458 tmpResult = CY_CRYPTO_BAD_PARAMS;
459 }
460
461 if (CY_CRYPTO_SUCCESS == tmpResult)
462 {
463 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_u1, bitsize);
464 if(CY_CRYPTO_SUCCESS != tmpResult)
465 {
466 return tmpResult;
467 }
468
469 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_u2, bitsize);
470 if(CY_CRYPTO_SUCCESS != tmpResult)
471 {
472 return tmpResult;
473 }
474
475 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_gx, bitsize);
476 if(CY_CRYPTO_SUCCESS != tmpResult)
477 {
478 return tmpResult;
479 }
480
481 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_gy, bitsize);
482 if(CY_CRYPTO_SUCCESS != tmpResult)
483 {
484 return tmpResult;
485 }
486
487 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_qx, bitsize);
488 if(CY_CRYPTO_SUCCESS != tmpResult)
489 {
490 return tmpResult;
491 }
492
493 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_qy, bitsize);
494 if(CY_CRYPTO_SUCCESS != tmpResult)
495 {
496 return tmpResult;
497 }
498
499 mallocMask |= CY_CRYPTO_VU_REG_BIT(dividend) |
500 CY_CRYPTO_VU_REG_BIT(p_u1) | CY_CRYPTO_VU_REG_BIT(p_u2) |
501 CY_CRYPTO_VU_REG_BIT(p_gx) | CY_CRYPTO_VU_REG_BIT(p_gy) |
502 CY_CRYPTO_VU_REG_BIT(p_qx) | CY_CRYPTO_VU_REG_BIT(p_qy);
503
504 /* load message hash, truncate it if needed */
505 CY_CRYPTO_VU_SET_TO_ZERO(base, p_u1);
506
507 /* load message hash, truncate it if needed. */
508 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_o, datasize * 8u);
509 if(CY_CRYPTO_SUCCESS != tmpResult)
510 {
511 return tmpResult;
512 }
513
514 CY_CRYPTO_VU_SET_TO_ZERO(base, p_o);
515 Cy_Crypto_Core_Vu_SetMemValue (base, p_o, (uint8_t *)hashPtrRemap, datasize * 8u);
516 Cy_Crypto_Core_VU_RegInvertEndianness(base, p_o);
517
518 /* Check if message hash is zero */
519 if(Cy_Crypto_Core_Vu_IsRegZero(base, p_o))
520 {
521 isHashZero = true;
522 }
523
524 if ((datasize * 8u) > bitsize)
525 {
526 CY_CRYPTO_VU_SET_REG(base, dividend, (datasize * 8u) - bitsize, 1u);
527 CY_CRYPTO_VU_LSR(base, p_o, p_o, dividend);
528 }
529
530 /* Use p_o as temporary register */
531 CY_CRYPTO_VU_MOV(base, p_u1, p_o);
532
533 CY_CRYPTO_VU_FREE_MEM(base, CY_CRYPTO_VU_REG_BIT(p_o));
534 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, p_o, bitsize);
535 if(CY_CRYPTO_SUCCESS != tmpResult)
536 {
537 return tmpResult;
538 }
539 tmpResult = CY_CRYPTO_VU_ALLOC_MEM (base, dividend, bitsize);
540 if(CY_CRYPTO_SUCCESS != tmpResult)
541 {
542 return tmpResult;
543 }
544 /* check that the prepared hash value is smaller than the order of base point */
545 if (!Cy_Crypto_Core_Vu_IsRegLess(base, p_u1, VR_P))
546 {
547 /* Use p_o as temporary register */
548 CY_CRYPTO_VU_MOV(base, p_o, p_u1);
549 Cy_Crypto_Core_Vu_WaitForComplete(base);
550
551 /* z = x % mod */
552 tmpResult = Cy_Crypto_Core_EC_Bar_MulRed(base, p_u1, p_o, bitsize);
553 if(CY_CRYPTO_SUCCESS != tmpResult)
554 {
555 return tmpResult;
556 }
557 }
558
559 /* w = s^-1 mod n */
560 CY_CRYPTO_VU_SET_TO_ONE(base, dividend);
561 tmpResult = Cy_Crypto_Core_EC_DivMod(base, p_s, dividend, p_s, bitsize);
562 if(CY_CRYPTO_SUCCESS != tmpResult)
563 {
564 return tmpResult;
565 }
566
567 /* u1 = e*w mod n */
568 tmpResult = Cy_Crypto_Core_EC_MulMod(base, p_u1, p_u1, p_s, bitsize);
569 if(CY_CRYPTO_SUCCESS != tmpResult)
570 {
571 return tmpResult;
572 }
573
574 /* u2 = r*w mod n */
575 tmpResult =Cy_Crypto_Core_EC_MulMod(base, p_u2, p_r, p_s, bitsize);
576 if(CY_CRYPTO_SUCCESS != tmpResult)
577 {
578 return tmpResult;
579 }
580
581 /* Initialize point multiplication */
582 Cy_Crypto_Core_EC_NistP_SetRedAlg(eccDp->algo);
583
584 /* load prime, order and Barrett coefficient */
585 Cy_Crypto_Core_Vu_SetMemValue (base, VR_P, (uint8_t const *)CY_REMAP_ADDRESS_FOR_CRYPTO(eccDp->prime), bitsize);
586 Cy_Crypto_Core_Vu_SetMemValue (base, VR_BARRETT, (uint8_t const *)CY_REMAP_ADDRESS_FOR_CRYPTO(eccDp->barrett_p), bitsize + 1U);
587
588 /* load base Point G */
589 Cy_Crypto_Core_Vu_SetMemValue (base, p_gx, (uint8_t const *)CY_REMAP_ADDRESS_FOR_CRYPTO(eccDp->Gx), bitsize);
590 Cy_Crypto_Core_Vu_SetMemValue (base, p_gy, (uint8_t const *)CY_REMAP_ADDRESS_FOR_CRYPTO(eccDp->Gy), bitsize);
591
592 /* load public key Qa */
593 Cy_Crypto_Core_Vu_SetMemValue (base, p_qx, (uint8_t const *)pubKeyXRemap, bitsize);
594 Cy_Crypto_Core_Vu_SetMemValue (base, p_qy, (uint8_t const *)pubKeyYRemap, bitsize);
595
596 /* u1 * G */
597 tmpResult = Cy_Crypto_Core_EC_NistP_PointMul(base, p_gx, p_gy, p_u1, p_o, bitsize);
598 if(CY_CRYPTO_SUCCESS != tmpResult)
599 {
600 return tmpResult;
601 }
602 /* u2 * Qa */
603 tmpResult = Cy_Crypto_Core_EC_NistP_PointMul(base, p_qx, p_qy, p_u2, p_o, bitsize);
604 if(CY_CRYPTO_SUCCESS != tmpResult)
605 {
606 return tmpResult;
607 }
608
609 if(isHashZero)
610 {
611 /* GECC 3.22 */
612 CY_CRYPTO_VU_MOV(base, p_s, p_qx);
613 }
614 else
615 {
616 /* P = u1 * G + u2 * Qa. Only Px is needed */
617 Cy_Crypto_Core_EC_SubMod(base, dividend, p_qy, p_gy); /* (y2-y1) */
618 Cy_Crypto_Core_EC_SubMod(base, p_s, p_qx, p_gx); /* (x2-x1) */
619 tmpResult = Cy_Crypto_Core_EC_DivMod(base, p_s, dividend, p_s, bitsize); /* s = (y2-y1)/(x2-x1) */
620 if(CY_CRYPTO_SUCCESS != tmpResult)
621 {
622 return tmpResult;
623 }
624
625 tmpResult = Cy_Crypto_Core_EC_SquareMod (base, p_s, p_s, bitsize); /* s^2 */
626 if(CY_CRYPTO_SUCCESS != tmpResult)
627 {
628 return tmpResult;
629 }
630 Cy_Crypto_Core_EC_SubMod (base, p_s, p_s, p_gx); /* s^2 - x1 */
631 Cy_Crypto_Core_EC_SubMod (base, p_s, p_s, p_qx); /* s^2 - x1 - x2 which is Px mod n */
632 }
633
634 CY_CRYPTO_VU_FREE_MEM(base, CY_CRYPTO_VU_REG_BIT(p_o));
635
636 if (Cy_Crypto_Core_Vu_IsRegEqual(base, p_s, p_r))
637 {
638 *stat = 1u;
639 }
640 else
641 {
642 *stat = 0u;
643 }
644 }
645
646 CY_CRYPTO_VU_FREE_MEM(base, mallocMask);
647 }
648 }
649
650 return (tmpResult);
651 }
652 #endif /* defined(CY_CRYPTO_CFG_ECDSA_VERIFY_C) */
653
654 #endif /* defined(CY_CRYPTO_CFG_ECDSA_C) */
655
656 #if defined(__cplusplus)
657 }
658 #endif
659
660 #endif /* CY_IP_MXCRYPTO */
661
662
663 /* [] END OF FILE */
664