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