1 /***************************************************************************//**
2 * \file cy_crypto_core_ecc.h
3 * \version 2.40
4 *
5 * \brief
6 *  This file provides Elliptic Curve (EC) Scalar Multiplication using (X,Y)-only,
7 *  Co-Z arithmetic in the Crypto driver.
8 *
9 ********************************************************************************
10 * Copyright 2016-2020 Cypress Semiconductor Corporation
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 *    http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25 
26 #include "cy_device.h"
27 
28 #if defined (CY_IP_MXCRYPTO)
29 
30 #include "cy_crypto_core_ecc_nist_p.h"
31 
32 #if defined(__cplusplus)
33 extern "C" {
34 #endif
35 
36 #include "cy_crypto_core_vu.h"
37 
38 /*******************************************************************************
39 * Elliptic Curve (EC) Scalar Multiplication using (X,Y)-only, Co-Z arithmetic
40 *
41 * Theoretic and algorithmic references:
42 * Algorithms and Co-Z arithmetic theory: 'Fast and Regular Algorithms for Scalar
43 * Multiplication over Elliptic Curves', Matthieu Rivain NIST P-curves
44 * (parameters and curve-specific modular reduction):
45 * 'RECOMMENDED ELLIPTIC CURVES FOR FEDERAL GOVERNMENT USE', NIST, 1999
46 *
47 * Useful resources:
48 * Large number calculator and converter:
49 * - http://www.mobilefish.com/services/big_number/big_number.php
50 * - https://www.mobilefish.com/services/big_number_equation/big_number_equation.php
51 *
52 * - ECC curves and test vectors: http://point-at-infinity.org/ecc/nisttv
53 *
54 * Valid values for scalar multiplier, 2 < d < (order-1)
55 *
56 *******************************************************************************/
57 
58 
59 /***************************************************************
60 *                   Global Variables
61 ***************************************************************/
62 static cy_en_crypto_ecc_curve_id_t eccMode;
63 
64 static cy_en_crypto_ecc_red_mul_algs_t mul_red_alg_select = CY_CRYPTO_NIST_P_BARRETT_RED_ALG;
65 
66 /***************************************************************
67 * Collection of multiplication reduction algorithms
68 * Method 1: (Crypto_EC_CS_MUL_Red_Pxxx): curve specific
69 *           reduction as proposed by NIST
70 * Method 2: (Crypto_EC_SM_MUL_Red_Pxxx): curve specific
71 *           reduction based on Mersenne prime reduction approach
72 * Method 3: generic Barrett reduction
73 ***************************************************************/
74 static void Cy_Crypto_Core_EC_CS_MUL_Red_P192(CRYPTO_Type *base, uint32_t z, uint32_t x);
75 static void Cy_Crypto_Core_EC_CS_MUL_Red_P224(CRYPTO_Type *base, uint32_t z, uint32_t x);
76 static void Cy_Crypto_Core_EC_CS_MUL_Red_P256(CRYPTO_Type *base, uint32_t z, uint32_t x);
77 static void Cy_Crypto_Core_EC_CS_MUL_Red_P384(CRYPTO_Type *base, uint32_t z, uint32_t x);
78 static void Cy_Crypto_Core_EC_CS_MUL_Red_P521(CRYPTO_Type *base, uint32_t z, uint32_t x);
79 static void Cy_Crypto_Core_EC_SM_MUL_Red_P192(CRYPTO_Type *base, uint32_t z, uint32_t x);
80 static void Cy_Crypto_Core_EC_SM_MUL_Red_P224(CRYPTO_Type *base, uint32_t z, uint32_t x);
81 static void Cy_Crypto_Core_EC_SM_MUL_Red_P256(CRYPTO_Type *base, uint32_t z, uint32_t x);
82 static void Cy_Crypto_Core_EC_SM_MUL_Red_P384(CRYPTO_Type *base, uint32_t z, uint32_t x);
83 static void Cy_Crypto_Core_EC_SM_MUL_Red_P521(CRYPTO_Type *base, uint32_t z, uint32_t x);
84 
85 static void Cy_Crypto_Core_EC_CS_MulRed(CRYPTO_Type *base, uint32_t z, uint32_t x, uint32_t size);
86 static void Cy_Crypto_Core_EC_SM_MulRed(CRYPTO_Type *base, uint32_t z, uint32_t x, uint32_t size);
87 static void Cy_Crypto_Core_EC_MulRed(CRYPTO_Type *base, uint32_t z, uint32_t x, uint32_t size);
88 
89 
90 /***************************************************************
91 *    Curve-specific multiplication reduction algorithms
92 ***************************************************************/
93 
94 
95 /*******************************************************************************
96 * Function Name: Cy_Crypto_Core_EC_CS_MUL_Red_P192
97 ****************************************************************************//**
98 *
99 * Curve-specific multiplication modular reduction for P192.
100 * 0 <= a, b < P192
101 * a5..a0 * b5..b0 % P192 = t11..t0 % P192
102 * P192 = 2^192-2^64-1
103 * t11..t0 % 2^192-2^64-1
104 * t11..t6 * 2^192 + t5..t0 % 2^192-2^64-1
105 * t11..t6 * 2^192-2^64-1 + t11..t6 * 2^64 + t11..t6 + t5..t0 % 2^192-2^64-1
106 * t11..t6 * 2^64 + t11..t6 + t5..t0 % 2^192-2^64-1
107 * t11..t10 * 2^192 + t9..t6 * 2^64 + t11..t6 + t5..t0 % 2^192-2^64-1
108 * t11..t10 * 2^192-2^64-1 + t11..t10 * 2^64 + t11..t10 + t9..t6 * 2^64 + t11..t6 + t5..t0 % 2^192-2^64-1
109 * t11..t10 * 2^64 + t11..t10 + t9..t6 * 2^64 + t11..t6 + t5..t0 % 2^192-2^64-1
110 *
111 * \param base
112 * The pointer to a Crypto instance.
113 *
114 * \param z
115 * Product = a*b [2*192 bits].
116 *
117 * \param x
118 * Result = x mod P = a*b mod P [192 bits].
119 *
120 *******************************************************************************/
Cy_Crypto_Core_EC_CS_MUL_Red_P192(CRYPTO_Type * base,uint32_t z,uint32_t x)121 static void Cy_Crypto_Core_EC_CS_MUL_Red_P192(CRYPTO_Type *base, uint32_t z, uint32_t x)
122 {
123    uint32_t sh   = 0u;
124    uint32_t t1   = 2u;     /* 128 */
125    uint32_t t2   = 3u;     /* 192 */
126    uint32_t my_z = 4u;
127    uint32_t my_x = 5u;
128 
129    CY_CRYPTO_VU_PUSH_REG (base);
130 
131    CY_CRYPTO_VU_LD_REG (base, my_z, z);
132    CY_CRYPTO_VU_LD_REG (base, my_x, x);
133 
134    CY_CRYPTO_VU_ALLOC_MEM (base, t1, 128u);
135    CY_CRYPTO_VU_ALLOC_MEM (base, t2, 192u);
136 
137    CY_CRYPTO_VU_SET_REG (base, sh, 192u, 1u);
138    CY_CRYPTO_VU_LSR (base, my_z, my_x, sh);     /* t11..t6 */
139 
140    CY_CRYPTO_VU_SET_REG (base, sh, 128u, 1u);
141    CY_CRYPTO_VU_LSR (base, t1, my_z, sh);       /* t11..t10 */
142    CY_CRYPTO_VU_SET_REG (base, sh, 64u, 1u);
143    CY_CRYPTO_VU_LSL (base, t2, my_z, sh);       /* t9..t6 * 2^64 */
144 
145 
146    CY_CRYPTO_VU_ADD (base, my_z, my_z, my_x);   /* t11..t6 + t5..t0 */
147    CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);  /* C = (z >= VR_P) */
148    CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);
149 
150    CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);     /* t9..t6 * 2^64 + t11..t6 + t5..t0 */
151    CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);  /* C = (z >= VR_P) */
152    CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);
153 
154    CY_CRYPTO_VU_LSL (base, t2, t1, sh);         /* t11..t10 * 2^64 */
155    CY_CRYPTO_VU_OR (base, t1, t1, t2);          /* t11..t10 * 2^64 + t11..t10 */
156 
157    CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);     /* t11..t10 * 2^64 + t11..t10 + t9..t6 * 2^64 + t11..t6 + t5..t0 */
158    CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);  /* C = (z >= VR_P) */
159    CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);
160 
161    CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t1) | CY_CRYPTO_VU_REG_BIT(t2));
162    CY_CRYPTO_VU_POP_REG (base);
163 }
164 
165 
166 /*******************************************************************************
167 * Function Name: Cy_Crypto_Core_EC_CS_MUL_Red_P224
168 ****************************************************************************//**
169 *
170 * Curve-specific multiplication modular reduction for P224.
171 * 0 <= a, b < P224
172 * a6..a0 * b6..b0 % P224 = t13..t0 % P224
173 * P224 = 2^224 - 2^96 - 1
174 * t6..t0 + t10..t7*2^96 + t13..t11*2^96 - t13..t7 - t13..t11 % 2^224 - 2^96 - 1
175 * t13..t11*2^96 + t6..t0 - t13..t7 - t13..t11 + t10..t7*2^96 % 2^224 - 2^96 - 1
176 *
177 * \param base
178 * The pointer to a Crypto instance.
179 *
180 * \param z
181 * Result = x mod P = a*b mod P [224 bits].
182 *
183 * \param x
184 * Product = a*b [2*224 bits].
185 *
186 *******************************************************************************/
Cy_Crypto_Core_EC_CS_MUL_Red_P224(CRYPTO_Type * base,uint32_t z,uint32_t x)187 static void Cy_Crypto_Core_EC_CS_MUL_Red_P224(CRYPTO_Type *base, uint32_t z, uint32_t x)
188 {
189    uint32_t sh   = 0u;
190    uint32_t t1   = 1u;     /* 224 */
191    uint32_t t2   = 2u;     /* 224 */
192    uint32_t t3   = 3u;     /* 224 */
193    uint32_t my_z = 4u;
194    uint32_t my_x = 5u;
195 
196    CY_CRYPTO_VU_PUSH_REG (base);
197 
198    CY_CRYPTO_VU_LD_REG (base, my_z, z);
199    CY_CRYPTO_VU_LD_REG (base, my_x, x);
200 
201    CY_CRYPTO_VU_ALLOC_MEM (base, t1, CY_CRYPTO_ECC_P224_SIZE);  /* 224 */
202    CY_CRYPTO_VU_ALLOC_MEM (base, t2, CY_CRYPTO_ECC_P224_SIZE);  /* 224 */
203    CY_CRYPTO_VU_ALLOC_MEM (base, t3, CY_CRYPTO_ECC_P224_SIZE);  /* 224 */
204 
205    CY_CRYPTO_VU_SET_REG (base, sh, CY_CRYPTO_ECC_P224_SIZE, 1u); /* sh   = 224 */
206    CY_CRYPTO_VU_LSR (base, my_z, my_x, sh); /* z = t13..t7 */
207 
208    CY_CRYPTO_VU_SET_REG (base, sh, 128u, 1u);
209    CY_CRYPTO_VU_LSR (base, t1, my_z, sh);   /* t1 = t13..t11 */
210 
211    CY_CRYPTO_VU_SET_REG (base, sh, 96u, 1u);
212    CY_CRYPTO_VU_LSL (base, t2, t1, sh);     /* t2 = t13..t11*2^96 */
213 
214    CY_CRYPTO_VU_SET_REG (base, sh, 96u, 1u);
215    CY_CRYPTO_VU_LSL (base, t3, my_z, sh);   /* t3 = t10..t7*2^96 */
216 
217    CY_CRYPTO_VU_ADD (base, t2, t2, my_x);   /* t2 = t13..t11*2^96 + t6..t0 */
218    CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, t2, VR_P);    /* C    = (t2 >= VR_P) */
219    CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, t2, t2, VR_P);    /* t2 = t2 - p, if C==1 (Carry is set) */
220 
221    CY_CRYPTO_VU_SUB (base, t2, t2, my_z);   /* t2 = (t13..t11*2^96 + t6..t0) - t13..t7 */
222    CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, t2, t2, VR_P);    /* t2 = t2 + p, if C==0 (Carry is clear) */
223 
224    CY_CRYPTO_VU_SUB (base, t2, t2, t1);     /* t2 = (t13..t11*2^96 + t6..t0 - t13..t7) - t13..t11 */
225    CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, t2, t2, VR_P);    /* t2 = t2 + p, if C==0 (Carry is clear) */
226 
227    CY_CRYPTO_VU_ADD (base, my_z, t2, t3);   /* z = (t13..t11*2^96 + t6..t0 - t13..t7 - t13..t11) + t10..t7*2^96 */
228    CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);  /* C    = (z >= VR_P) */
229    CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);    /* z = z - p, if C==1 (Carry is set) */
230 
231    CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t1) | CY_CRYPTO_VU_REG_BIT(t2) | CY_CRYPTO_VU_REG_BIT(t3));
232 
233    CY_CRYPTO_VU_POP_REG (base);
234 }
235 
236 
237 /*******************************************************************************
238 * Function Name: Cy_Crypto_Core_EC_CS_MUL_Red_P256
239 ****************************************************************************//**
240 *
241 * Curve-specific multiplication modular reduction for P256.
242 * 0 <= a, b < P256
243 * a7..a0 * b7..b0 % P256 = t15..t0 % P256
244 * P224 = 2^256 - 2^224 + 2^192 + 2^96 - 1
245 * t7..t0 + 2*t15..t11*2^96 + 2*t15..t12*2^96 + (t15..t14*2^192 + t10..t8)
246 * + (t8*2^224 + t13*2^192 + t15..t9) - (t10*2^224 + t8*2^192 + t13..t11)
247 * - (t11*2^224 + t9*2^192 + t15..t12) - (t12*2^224 + t10..t8*2^96 + t15..t13)
248 * - (t13*2^224 + t11..t9*2^96 + t15..t14) % 2^256 - 2^224 + 2^192 + 2^96 - 1
249 *
250 * \param base
251 * The pointer to a Crypto instance.
252 *
253 * \param z
254 * Result = x mod P = a*b mod P [256 bits].
255 *
256 * \param x
257 * Product = a*b [2*256 bits].
258 *
259 *******************************************************************************/
Cy_Crypto_Core_EC_CS_MUL_Red_P256(CRYPTO_Type * base,uint32_t z,uint32_t x)260 static void Cy_Crypto_Core_EC_CS_MUL_Red_P256(CRYPTO_Type *base, uint32_t z, uint32_t x)
261 {
262     uint32_t sh     = 0u;   /* Variable values */
263     uint32_t sh32   = 1u;
264     uint32_t sh96   = 2u;
265     uint32_t sh192  = 3u;
266     uint32_t sh224  = 4u;
267     uint32_t t0     = 5u;   /* 256 */
268     uint32_t t1     = 6u;   /* 256 */
269     uint32_t t2     = 7u;   /* 256 */
270     uint32_t t3     = 8u;   /* 32 */
271     uint32_t t4     = 9u;   /* 96 */
272     uint32_t my_z   = 10u;
273     uint32_t my_x   = 11u;
274 
275     CY_CRYPTO_VU_PUSH_REG (base);
276 
277     CY_CRYPTO_VU_LD_REG (base, my_z, z);
278     CY_CRYPTO_VU_LD_REG (base, my_x, x);
279 
280     CY_CRYPTO_VU_ALLOC_MEM (base, t0, CY_CRYPTO_ECC_P256_SIZE); /* 256 */
281     CY_CRYPTO_VU_ALLOC_MEM (base, t1, CY_CRYPTO_ECC_P256_SIZE); /* 256 */
282     CY_CRYPTO_VU_ALLOC_MEM (base, t2, CY_CRYPTO_ECC_P256_SIZE); /* 256 */
283     CY_CRYPTO_VU_ALLOC_MEM (base, t3, 32u);      /* 32 */
284     CY_CRYPTO_VU_ALLOC_MEM (base, t4, 96u);      /* 96 */
285 
286     CY_CRYPTO_VU_SET_REG (base, sh, CY_CRYPTO_ECC_P256_SIZE, 1u);    /* sh = 256 */
287     CY_CRYPTO_VU_SET_REG (base, sh32, 32u, 1u);   /* sh = 32 */
288     CY_CRYPTO_VU_SET_REG (base, sh96, 96u, 1u);   /* sh = 96 */
289     CY_CRYPTO_VU_SET_REG (base, sh192, 192u, 1u); /* sh = 192 */
290     CY_CRYPTO_VU_SET_REG (base, sh224, 224u, 1u); /* sh = 224 */
291 
292     CY_CRYPTO_VU_LSR (base, t0, my_x, sh);      /* t0 = t15..t8 */
293     CY_CRYPTO_VU_LSR (base, my_z, t0, sh96);    /* z = t15..t11 */
294     CY_CRYPTO_VU_LSR (base, t1, my_z, sh32);    /* t1 = t15..t12 */
295     CY_CRYPTO_VU_LSR (base, t3, my_z, sh32);    /* t3 = t12 */
296 
297     /* 2*S1 -- 2*t15..t11*2^96 */
298     CY_CRYPTO_VU_LSL (base, my_z, my_z, sh96);  /* z = t15..t11*2^96 */
299     CY_CRYPTO_VU_ADD (base, my_z, my_z, my_z);  /* z = 2*t15..t11*2^96 */
300     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
301     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
302 
303     /* D3 (a) -- t12*2^224 */
304     CY_CRYPTO_VU_LSL (base, t2, t3, sh224);     /* t2 = t12*2^224 */
305     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t12*2^224 */
306     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
307 
308     /* 2*S2 -- 2*t15..t12*2^96 */
309     CY_CRYPTO_VU_LSL (base, t2, t1, sh96);      /* t2 = t15..t12*2^96 */
310 
311     CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);    /* z = z + t15..t12*2^96 */
312     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
313     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
314 
315     CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);    /* z = z + 2*t15..t12*2^96 */
316     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
317     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
318 
319     /* D4 (c) -- t15..t14 */
320     CY_CRYPTO_VU_LSR (base, t2, t0, sh192);     /* t2 = t15..t14 */
321     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t15..t14 */
322     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
323 
324     /* S3 (a) -- t15..t14*2^192 */
325     CY_CRYPTO_VU_LSL (base, t2, t2, sh192);     /* t2 = t15..t14*2^192 */
326     CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);    /* z = z + t15..t14*2^192 */
327     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
328     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
329 
330     /* D2 (c) -- t15..t12 */
331     CY_CRYPTO_VU_SUB (base, my_z, my_z, t1);    /* z = z - t15..t12 */
332     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
333 
334     /* S4 (b) -- t13*2^192 */
335     CY_CRYPTO_VU_LSR (base, t3, t1, sh32);      /* t3 = t13 */
336     CY_CRYPTO_VU_LSL (base, t2, t3, sh192);     /* t2 = t13*2^192 */
337     CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);    /* z = z + t13*2^192 */
338     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
339     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
340 
341     /* D4 (a) -- t13*2^224 */
342     CY_CRYPTO_VU_LSL (base, t2, t2, sh32);      /* t2 = t13*2^224 */
343     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t13*2^224 */
344     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
345 
346     /* D3 (c) -- t15..t13 */
347     CY_CRYPTO_VU_LSR (base, t1, t1, sh32);      /* t1 = t15..t13 */
348     CY_CRYPTO_VU_SUB (base, my_z, my_z, t1);    /* z = z - t15..t13 */
349     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
350 
351     /* S4 (c) -- t15..t13*2^96 */
352     CY_CRYPTO_VU_LSL (base, t2, t1, sh96);      /* t2 = t15..t13*2^96 */
353     CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);    /* z = z + t15..t13*2^96 */
354     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
355     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
356 
357     /* D2 (a) -- t11*2^224 */
358     CY_CRYPTO_VU_LSR (base, t3, t0, sh96);      /* t3 = t11 */
359     CY_CRYPTO_VU_LSL (base, t2, t3, sh224);     /* t2 = t11*2^224 */
360     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t11*2^224 */
361     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
362 
363     /* D2 (b) -- t9*2^192 */
364     CY_CRYPTO_VU_LSR (base, t3, t0, sh32);      /* t3 = t9 */
365     CY_CRYPTO_VU_LSL (base, t2, t3, sh192);     /* t2 = t9*2^192 */
366     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t9*2^192 */
367     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
368 
369     /* D1 (c) -- t13..t11 */
370     CY_CRYPTO_VU_LSR (base, t4, t0, sh96);      /* t4 = t13..t11 */
371     CY_CRYPTO_VU_SUB (base, my_z, my_z, t4);    /* z = z - t13..t11 */
372     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
373 
374     /* S4 (d) -- t11..t9 */
375     CY_CRYPTO_VU_LSR (base, t4, t0, sh32);      /* t4 = t11..t9 */
376     CY_CRYPTO_VU_ADD (base, my_z, my_z, t4);    /* z = z + t11..t9 */
377     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
378     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
379 
380     /* D1 (a) -- t10*2^224 */
381     CY_CRYPTO_VU_LSR (base, t3, t4, sh32);      /* t3 = t10 */
382     CY_CRYPTO_VU_LSL (base, t2, t3, sh224);     /* t2 = t10*2^224 */
383     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t10*2^224 */
384     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
385 
386 
387     /* D4 (b) -- t11..t9*2^96 */
388     CY_CRYPTO_VU_LSL (base, t2, t4, sh96);      /* t2 = t11..t9*2^96 */
389     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t11..t9*2^96 */
390     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
391 
392     CY_CRYPTO_VU_SET_REG (base, sh, 0u, 1u);      /* sh = 0; */
393 
394     /* S3 (b) -- t10..t8 */
395     CY_CRYPTO_VU_LSR (base, t4, t0, sh);        /* t4 = t10..t8 */
396     CY_CRYPTO_VU_ADD (base, my_z, my_z, t4);    /* z = z + t10..t8 */
397     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
398     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
399 
400     /* D3 (b) -- t10..t8*2^96 */
401     CY_CRYPTO_VU_LSL (base, t2, t4, sh96);      /* t4 = t10..t8*2^96 */
402     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t10..t8*2^96 */
403     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
404 
405     /* S4 (a) -- t8*2^224 */
406     CY_CRYPTO_VU_LSL (base, t2, t0, sh224);     /* t2 = t8*2^224 */
407     CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);    /* z = z + t8*2^224 */
408     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
409     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
410 
411     /* D1 (b) -- t8*2^192 */
412     CY_CRYPTO_VU_LSR (base, t2, t2, sh32);      /* t2 = t8*2^192 */
413     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t8*2^192 */
414     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
415 
416     /* T -- t7..t0 */
417     CY_CRYPTO_VU_LSR (base, t2, my_x, sh);      /* t2 = t8*2^192 */
418     CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);    /* z = z + t7..t0 */
419     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
420     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
421 
422     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t0) | CY_CRYPTO_VU_REG_BIT(t1) |
423                                  CY_CRYPTO_VU_REG_BIT(t2) | CY_CRYPTO_VU_REG_BIT(t3) | CY_CRYPTO_VU_REG_BIT(t4));
424     CY_CRYPTO_VU_POP_REG (base);
425 }
426 
427 
428 /*******************************************************************************
429 * Function Name: Cy_Crypto_Core_EC_CS_MUL_Red_P384
430 ****************************************************************************//**
431 *
432 * Curve-specific multiplication modular reduction for P384.
433 * 0 <= a, b < P384
434 * a11..a0 * b11..b0 % P384 = t23..t0 % P384
435 * P384 = 2^384 - 2^128 - 2*96 + 2*32 - 1
436 * t11..t0 + 2*t23..t21*2^128 + t23..t12 + (t20..t12*2^96 + t23..t21)
437 * + (t19..t12*2^128 + t20*2^96 +t23*2^32) + t23..t20*2^128 + (t23..t21*2^96 + t20)
438 * - (t22..t12*2^32 + t23) - t23..t20*2^32 - (t23*2^128 + t23*2^96) % P384
439 *
440 * \param base
441 * The pointer to a Crypto instance.
442 *
443 * \param z
444 * Result = x mod P = a*b mod P [384 bits]
445 *
446 * \param x
447 * Product = a*b [2*384 bits]
448 *
449 *******************************************************************************/
Cy_Crypto_Core_EC_CS_MUL_Red_P384(CRYPTO_Type * base,uint32_t z,uint32_t x)450 static void Cy_Crypto_Core_EC_CS_MUL_Red_P384(CRYPTO_Type *base, uint32_t z, uint32_t x)
451 {
452     uint32_t sh32   = 0u;
453     uint32_t sh64   = 1u;
454     uint32_t sh96   = 2u;
455     uint32_t sh128  = 3u;
456     uint32_t sh256  = 4u;
457     uint32_t sh384  = 5u;
458     uint32_t t0     = 6u;   /* 384 */
459     uint32_t t1     = 7u;   /* 384 */
460     uint32_t t2     = 8u;   /*  32 */
461     uint32_t my_z   = 9u;
462     uint32_t my_x   = 10u;
463 
464     CY_CRYPTO_VU_PUSH_REG (base);
465 
466     CY_CRYPTO_VU_LD_REG (base, my_z, z);
467     CY_CRYPTO_VU_LD_REG (base, my_x, x);
468 
469     CY_CRYPTO_VU_ALLOC_MEM (base, t0, CY_CRYPTO_ECC_P384_SIZE); /* 384 */
470     CY_CRYPTO_VU_ALLOC_MEM (base, t1, CY_CRYPTO_ECC_P384_SIZE); /* 384 */
471     CY_CRYPTO_VU_ALLOC_MEM (base, t2, 32u);  /* 32 */
472 
473     CY_CRYPTO_VU_SET_REG (base, sh32, 32u, 1u);   /* sh32  = 32 */
474     CY_CRYPTO_VU_SET_REG (base, sh64, 64u, 1u);   /* sh64  = 64 */
475     CY_CRYPTO_VU_SET_REG (base, sh96, 96u, 1u);   /* sh96  = 96 */
476     CY_CRYPTO_VU_SET_REG (base, sh128, 128u, 1u); /* sh128 = 128 */
477     CY_CRYPTO_VU_SET_REG (base, sh256, 256u, 1u); /* sh256 = 256 */
478     CY_CRYPTO_VU_SET_REG (base, sh384, CY_CRYPTO_ECC_P384_SIZE, 1u);         /* sh384 = 384 */
479 
480     CY_CRYPTO_VU_LSR (base, t0, my_x, sh384);   /* t0 = t23..t12 */
481 
482     /* T + S2 -- t11..t0 + t23..t12 */
483     CY_CRYPTO_VU_ADD (base, my_z, t0, my_x);    /* z = t23..t12 + t11..t0 */
484     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
485     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
486 
487     /* S6 (b) -- t_20 */
488     CY_CRYPTO_VU_LSR (base, t2, t0, sh256);     /* t2 = t20 */
489     CY_CRYPTO_VU_ADD (base, my_z, my_z, t2);    /* z = z + t20 */
490     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
491     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
492 
493     /* S4 (b) -- t20*2^96 */
494     CY_CRYPTO_VU_LSL (base, t1, t2, sh96);      /* t1 = t20*2^96 */
495     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t20*2^96 */
496     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
497     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
498 
499     /* S5 -- t23..t20*2^128 */
500     CY_CRYPTO_VU_LSR (base, t1, t0, sh256);     /* t1 = t23..t20 */
501     CY_CRYPTO_VU_LSL (base, t1, t1, sh128);     /* t1 = t23..t20*2^128 */
502     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t23..t20*2^128 */
503     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
504     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
505 
506     /* D2 -- t23..t20*2^32 */
507     CY_CRYPTO_VU_LSR (base, t1, t1, sh96);      /* t1 = t23..t20*2^32 */
508     CY_CRYPTO_VU_SUB (base, my_z, my_z, t1);    /* z = z - t23..t20*2^32 */
509     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
510 
511     /* S3 (b) -- t23..t21 */
512     CY_CRYPTO_VU_LSR (base, t1, t1, sh64);      /* t1 = t23..t21 */
513     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t23..t21 */
514     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
515     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
516 
517     /* D1 (b) -- t23 */
518     CY_CRYPTO_VU_LSR (base, t2, t1, sh64);      /* t2 = t23 */
519     CY_CRYPTO_VU_SUB (base, my_z, my_z, t2);    /* z = z - t23 */
520     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
521 
522     /* S6 (a) -- t23..t21*2^96 */
523     CY_CRYPTO_VU_LSL (base, t1, t1, sh96);      /* t1 = t23..t21*2^96 */
524     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t23..t21*2^96 */
525     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
526     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
527 
528     /* 2*S1 -- 2*t23..t21*2^128 */
529     CY_CRYPTO_VU_LSL (base, t1, t1, sh32);      /* t1 = t23..t21*2^128 */
530     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t23..t21*2^128 */
531     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
532     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
533     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t20..t12*2^128 */
534     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
535     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
536 
537     /* S4 (c) -- t23*2^32 */
538     CY_CRYPTO_VU_LSL (base, t1, t2, sh32);      /* t1 = t23*2^32 */
539     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t23*2^32 */
540     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
541     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
542 
543     /* D3 (b) -- t23*2^96 */
544     CY_CRYPTO_VU_LSL (base, t1, t1, sh64);      /* t1 = t23*2^96 */
545     CY_CRYPTO_VU_SUB (base, my_z, my_z, t1);    /* z = z - t23*2^96 */
546     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
547 
548     /* D3 (a) -- t23*2^128 */
549     CY_CRYPTO_VU_LSL (base, t1, t1, sh32);      /* t1 = t23*2^128 */
550     CY_CRYPTO_VU_SUB (base, my_z, my_z, t1);    /* z = z - t23*2^128 */
551     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
552 
553     /* D1 (a) -- t22..t12*2^32 */
554     CY_CRYPTO_VU_LSL (base, t1, t0, sh32);      /* t1 = t22..t12*2^32 */
555     CY_CRYPTO_VU_SUB (base, my_z, my_z, t1);    /* z = z - t22..t12*2^32 */
556     CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, my_z, my_z, VR_P);   /* z = z + p, if C==0 (Carry is clear) */
557 
558     /* S3 (a) -- t20..t12*2^96 */
559     CY_CRYPTO_VU_LSL (base, t1, t1, sh64);      /* t1 = t20..t12*2^96 */
560     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t20..t12*2^96 */
561     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
562     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
563 
564     /* S4 (a) -- t19..t12*2^128 */
565     CY_CRYPTO_VU_LSL (base, t1, t1, sh32);      /* t1 = t19..t12*2^128 */
566     CY_CRYPTO_VU_ADD (base, my_z, my_z, t1);    /* z = z + t19..t12*2^128 */
567     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (z >= VR_P) */
568     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* z = z - p, if C==1 (Carry is set) */
569 
570     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t0) | CY_CRYPTO_VU_REG_BIT(t1) | CY_CRYPTO_VU_REG_BIT(t2));
571     CY_CRYPTO_VU_POP_REG (base);
572 }
573 
574 
575 /*******************************************************************************
576 * Function Name: Cy_Crypto_Core_EC_CS_MUL_Red_P521
577 ****************************************************************************//**
578 *
579 * Curve-specific multiplication modular reduction for P521.
580 * 0 <= a, b < P521
581 * P521 = 2^521 - 1
582 * a*b = T = T1*2^521 + T0
583 * T1 = t1041..t521
584 * T0 = t520..t0
585 * T mod p521 = T0 + T1 mod P521
586 *
587 * \param base
588 * The pointer to a Crypto instance.
589 *
590 * \param z
591 * Result = x mod P = a*b mod P [521 bits]
592 *
593 * \param x
594 * Product = a*b [2*521 bits]
595 *
596 *******************************************************************************/
Cy_Crypto_Core_EC_CS_MUL_Red_P521(CRYPTO_Type * base,uint32_t z,uint32_t x)597 static void Cy_Crypto_Core_EC_CS_MUL_Red_P521(CRYPTO_Type *base, uint32_t z, uint32_t x)
598 {
599     uint32_t sh521   = 0u;
600     uint32_t t0      = 1u;
601     uint32_t my_z    = 2u;
602     uint32_t my_x    = 3u;
603 
604     CY_CRYPTO_VU_PUSH_REG (base);
605 
606     CY_CRYPTO_VU_LD_REG (base, my_z, z);
607     CY_CRYPTO_VU_LD_REG (base, my_x, x);
608 
609     CY_CRYPTO_VU_ALLOC_MEM (base, t0, CY_CRYPTO_ECC_P521_SIZE); /* 521 */
610 
611     CY_CRYPTO_VU_SET_REG (base, sh521, 521u, 1u);                 /* sh521  = 521 */
612 
613     CY_CRYPTO_VU_LSR (base, my_z, my_x, sh521);                 /* z = T1 */
614 
615     CY_CRYPTO_VU_ADD (base, my_z, my_z, my_x);                  /* z = T1 + T0 */
616 
617     /* T0 + T1 mod p */
618     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (t2 >= VR_P) */
619     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* t2 = t2 - p, if C==1 (Carry is set) */
620 
621     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t0));
622 
623     CY_CRYPTO_VU_POP_REG (base);
624 }
625 
626 
627 /*******************************************************************************
628 * Function Name: Cy_Crypto_Core_EC_CS_MulRed
629 ****************************************************************************//**
630 *
631 * \param base
632 * The pointer to a Crypto instance.
633 *
634 * \param z
635 * Result.
636 *
637 * \param x
638 * Product.
639 *
640 * \param size
641 * Size.
642 *
643 *******************************************************************************/
Cy_Crypto_Core_EC_CS_MulRed(CRYPTO_Type * base,uint32_t z,uint32_t x,uint32_t size)644 static void Cy_Crypto_Core_EC_CS_MulRed(CRYPTO_Type *base, uint32_t z, uint32_t x, uint32_t size)
645 {
646     (void)size; /* Suppress warning */
647 
648     switch (eccMode)
649     {
650         case CY_CRYPTO_ECC_ECP_SECP192R1:
651             Cy_Crypto_Core_EC_CS_MUL_Red_P192(base, z, x);
652             break;
653         case CY_CRYPTO_ECC_ECP_SECP224R1:
654             Cy_Crypto_Core_EC_CS_MUL_Red_P224(base, z, x);
655             break;
656         case CY_CRYPTO_ECC_ECP_SECP256R1:
657             Cy_Crypto_Core_EC_CS_MUL_Red_P256(base, z, x);
658             break;
659         case CY_CRYPTO_ECC_ECP_SECP384R1:
660             Cy_Crypto_Core_EC_CS_MUL_Red_P384(base, z, x);
661             break;
662         case CY_CRYPTO_ECC_ECP_SECP521R1:
663             Cy_Crypto_Core_EC_CS_MUL_Red_P521(base, z, x);
664             break;
665         default:
666         /* Unsupported Eliptic Curve ID */
667             break;
668     }
669 }
670 
671 
672 /**********************************************************************
673 *  Shift-multiply, curve-specific multiplication reduction algorithms
674 **********************************************************************/
675 
676 
677 /*******************************************************************************
678 * Function Name: Cy_Crypto_Core_EC_CS_MUL_Red_P224
679 ****************************************************************************//**
680 *
681 * Shift-multiply multiplication modular reduction for P192.
682 * a[CURVE_SIZE-1:0] * b[CURVE_SIZE-1:0] mod p[CURVE_SIZE-1:0]
683 *
684 * \param base
685 * The pointer to a Crypto instance.
686 *
687 * \param z
688 * Result = x mod P = a*b mod P [192 bits].
689 *
690 * \param x
691 * Product = a*b [2*192 bits].
692 *
693 *******************************************************************************/
Cy_Crypto_Core_EC_SM_MUL_Red_P192(CRYPTO_Type * base,uint32_t z,uint32_t x)694 static void Cy_Crypto_Core_EC_SM_MUL_Red_P192(CRYPTO_Type *base, uint32_t z, uint32_t x)
695 {
696    /* Setup */
697    uint32_t partial  = 0u;
698    uint32_t hi       = 1u;
699    uint32_t sh64     = 2u;
700    uint32_t sh192    = 3u;
701    uint32_t my_z     = 4u;
702    uint32_t my_x     = 5u;
703 
704    CY_CRYPTO_VU_PUSH_REG (base);
705 
706    CY_CRYPTO_VU_LD_REG (base, my_z, z);
707    CY_CRYPTO_VU_LD_REG (base, my_x, x);
708 
709    CY_CRYPTO_VU_ALLOC_MEM (base, partial, CY_CRYPTO_ECC_P192_SIZE + 65u);
710    CY_CRYPTO_VU_ALLOC_MEM (base, hi, CY_CRYPTO_ECC_P192_SIZE + 64u);
711 
712    CY_CRYPTO_VU_SET_REG (base, sh64, 64u, 1u);
713    CY_CRYPTO_VU_SET_REG (base, sh192, 192u, 1u);
714 
715    /* Step 2: 1st round of shift-multiply
716     * (Separate hi and lo (LSR hi>>CURVE_SIZE), multiply hi (LSL hi and add 1) and add shifted hi to lo)
717     * hi * (2^{64} + 1) + lo
718     */
719    CY_CRYPTO_VU_LSR (base, hi, my_x, sh192);    /* hi = prod >> CURVE_SIZE = prod[383:192] */
720    CY_CRYPTO_VU_MOV (base, my_z, my_x);         /* z == lo = prod[191:0] */
721 
722    CY_CRYPTO_VU_ADD (base, partial, hi, my_z);  /* partial = (hi*1) + lo */
723 
724    CY_CRYPTO_VU_LSL (base, hi, hi, sh64);       /* hi = hi << 64 = hi*2^{64} */
725 
726    CY_CRYPTO_VU_ADD (base, partial, partial, hi);   /* partial = hi*(2^{64}+1) + lo */
727 
728    /* Step 3: 2nd round of shift-multiply */
729    CY_CRYPTO_VU_LSR (base, hi, partial, sh192); /* hi = partial >> CURVE_SIZE = partial[383:192] */
730 
731    CY_CRYPTO_VU_ADD (base, my_z, hi, partial);  /* z = (hi*1) + lo (Note: partial == lo, since it will be cut to CURVE_SIZE since z = CURVE_SIZE) */
732 
733    CY_CRYPTO_VU_LSL (base, hi, hi, sh64);       /* hi = hi << 64 = hi*2^{64} */
734 
735    CY_CRYPTO_VU_ADD (base, my_z, my_z, hi);     /* z = hi*(2^{64}+1) + lo */
736 
737    /* Step 4: Final reduction (compare to P-192 and reduce if necessary, based on CARRY flag) */
738    CY_CRYPTO_VU_CMP_SUB (base, my_z, VR_P);     /* C = (z >= VR_P) */
739    CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);
740 
741    CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(partial) | CY_CRYPTO_VU_REG_BIT(hi));
742    CY_CRYPTO_VU_POP_REG (base);
743 }
744 
745 
746 /*******************************************************************************
747 * Function Name: Cy_Crypto_Core_EC_SM_MUL_Red_P224
748 ****************************************************************************//**
749 *
750 * Curve-specific multiplication modular reduction for P224.
751 *  0 <= a, b < P224
752 *
753 * \param base
754 * The pointer to a Crypto instance.
755 *
756 * \param z
757 * Result = x mod P = a*b mod P [224 bits].
758 *
759 * \param x
760 * Product = a*b [2*224 bits].
761 *
762 *******************************************************************************/
Cy_Crypto_Core_EC_SM_MUL_Red_P224(CRYPTO_Type * base,uint32_t z,uint32_t x)763 static void Cy_Crypto_Core_EC_SM_MUL_Red_P224(CRYPTO_Type *base, uint32_t z, uint32_t x)
764 {
765 
766     /* Setup */
767     uint32_t partial = 0u;
768     uint32_t hi      = 1u;
769     uint32_t sh96    = 2u;
770     uint32_t sh224   = 3u;
771     uint32_t my_z    = 4u;
772     uint32_t my_x    = 5u;
773 
774     CY_CRYPTO_VU_PUSH_REG (base);
775 
776     CY_CRYPTO_VU_LD_REG (base, my_z, z);
777     CY_CRYPTO_VU_LD_REG (base, my_x, x);
778 
779     CY_CRYPTO_VU_ALLOC_MEM (base, partial, CY_CRYPTO_ECC_P224_SIZE + 97u);
780     CY_CRYPTO_VU_ALLOC_MEM (base, hi, CY_CRYPTO_ECC_P224_SIZE + 96u);
781 
782     CY_CRYPTO_VU_SET_REG (base, sh96, 96u, 1u);
783     CY_CRYPTO_VU_SET_REG (base, sh224, 224u, 1u);
784 
785     /* Step 2: 1st round of shift-multiply
786      * (Separate hi and lo (LSR hi>>CURVE_SIZE), multiply hi (LSL hi<<96 and subtract 1) and add shifted hi to lo)
787      * hi * (2^{96} + 1) + lo
788      */
789     CY_CRYPTO_VU_LSR (base, hi, my_x, sh224);       /* hi = prod >> CURVE_SIZE = prod[447:224] */
790     CY_CRYPTO_VU_MOV (base, my_z, my_x);            /* z == lo = prod[223:0] */
791 
792     CY_CRYPTO_VU_SUB (base, partial, my_z, hi);     /* partial = lo - (hi*1) */
793 
794     CY_CRYPTO_VU_LSL (base, hi, hi, sh96);          /* hi = hi << 96 = hi*2^{96} */
795 
796     CY_CRYPTO_VU_ADD (base, partial, partial, hi);  /* partial = hi*(2^{96}-1) + lo */
797 
798     /* Step 3: 2nd round of shift-multiply */
799     CY_CRYPTO_VU_LSR (base, hi, partial, sh224);    /* hi = partial>>CURVE_SIZE = partial[447:224] */
800 
801     CY_CRYPTO_VU_SUB (base, my_z, partial, hi);     /* z = lo - (hi*1) (Note: partial == lo, since it will be cut to CURVE_SIZE since z = CURVE_SIZE) */
802 
803     CY_CRYPTO_VU_LSL (base, hi, hi, sh96);          /* hi = hi<<96 = hi*2^{96} */
804 
805     CY_CRYPTO_VU_ADD (base, my_z, my_z, hi);        /* z = hi*(2^{96}-1) + lo */
806 
807     /* Step 4: Final reduction (compare to P-224 and reduce if necessary, based on CARRY flag) */
808     CY_CRYPTO_VU_CMP_SUB (base, my_z, VR_P);        /* C = (z >= VR_P) */
809     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);
810 
811     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(partial) | CY_CRYPTO_VU_REG_BIT(hi));
812     CY_CRYPTO_VU_POP_REG (base);
813 }
814 
815 
816 /*******************************************************************************
817 * Function Name: Cy_Crypto_Core_EC_SM_MUL_Red_P256
818 ****************************************************************************//**
819 *
820 * Shift-multiply modular reduction algorithm.
821 * a*b mod p
822 * 0 <= a, b < P256
823 *
824 * \param base
825 * The pointer to a Crypto instance.
826 *
827 * \param z
828 * Result.
829 *
830 * \param x
831 * Product.
832 *
833 *******************************************************************************/
Cy_Crypto_Core_EC_SM_MUL_Red_P256(CRYPTO_Type * base,uint32_t z,uint32_t x)834 static void Cy_Crypto_Core_EC_SM_MUL_Red_P256(CRYPTO_Type *base, uint32_t z, uint32_t x)
835 {
836     /* Pre-computed coefficient for shift-multiply modular reduction for P256 */
837     const uint8_t P256_ShMul_COEFF[] = {
838         0x01u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
839         0x00u, 0x00u, 0x00u, 0x00u, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
840         0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
841         0xFEu, 0xFFu, 0xFFu, 0xFFu
842     };
843 
844     /* Setup */
845     uint32_t partial = 0u;
846     uint32_t hi      = 1u;
847     uint32_t sh256   = 2u;
848     uint32_t my_z    = 3u;
849     uint32_t my_x    = 4u;
850     uint32_t coeff   = 5u;
851 
852     CY_CRYPTO_VU_PUSH_REG (base);
853 
854     CY_CRYPTO_VU_LD_REG (base, my_z, z);
855     CY_CRYPTO_VU_LD_REG (base, my_x, x);
856 
857     CY_CRYPTO_VU_ALLOC_MEM (base, coeff, 224u);
858     CY_CRYPTO_VU_ALLOC_MEM (base, partial, CY_CRYPTO_ECC_P256_SIZE + 224u);
859     CY_CRYPTO_VU_ALLOC_MEM (base, hi, CY_CRYPTO_ECC_P256_SIZE);
860 
861     CY_CRYPTO_VU_SET_REG (base, sh256, 256u, 1u);
862 
863     Cy_Crypto_Core_Vu_SetMemValue (base, coeff, P256_ShMul_COEFF, 224u);
864 
865     /* Step 2: 1st round of shift-multiply
866      * (Separate hi and lo (LSR hi>>CURVE_SIZE), multiply hi*c and add hi*coeff + lo)
867      * hi*coeff + lo
868      */
869     CY_CRYPTO_VU_LSR (base, hi, my_x, sh256);           /* hi = prod >> CURVE_SIZE = prod[511:256] */
870     CY_CRYPTO_VU_MOV (base, my_z, my_x);                /* z == lo = prod[255:0] */
871 
872     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
873 
874     CY_CRYPTO_VU_ADD (base, partial, partial, my_z);    /* partial = hi*coeff + lo */
875 
876     /* Step 3: 2nd round of shift-multiply */
877     CY_CRYPTO_VU_LSR (base, hi, partial, sh256);        /* hi = partial>>CURVE_SIZE = partial[511:256] */
878     CY_CRYPTO_VU_MOV (base, my_z, partial);             /* z == lo = partial[255:0] */
879     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
880     CY_CRYPTO_VU_ADD (base, partial, partial, my_z);    /* z = hi*coeff + lo */
881 
882     /* Step 4: 3rd round of shift-multiply */
883     CY_CRYPTO_VU_LSR (base, hi, partial, sh256);        /* hi = partial>>CURVE_SIZE = partial[511:256] */
884     CY_CRYPTO_VU_MOV (base, my_z, partial);             /* z == lo = partial[255:0] */
885 
886     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
887     CY_CRYPTO_VU_ADD (base, partial, partial, my_z);    /* z = hi*coeff + lo */
888 
889     /* Step 5: 4th round of shift-multiply */
890     CY_CRYPTO_VU_LSR (base, hi, partial, sh256);        /* hi = partial>>CURVE_SIZE = partial[511:256] */
891     CY_CRYPTO_VU_MOV (base, my_z, partial);             /* z == lo = partial[255:0] */
892 
893     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
894     CY_CRYPTO_VU_ADD (base, partial, partial, my_z);    /* z = hi*coeff + lo */
895 
896     /* Step 6: 5th round of shift-multiply */
897     CY_CRYPTO_VU_LSR (base, hi, partial, sh256);        /* hi = partial>>CURVE_SIZE = partial[511:256] */
898     CY_CRYPTO_VU_MOV (base, my_z, partial);             /* z == lo = partial[255:0] */
899 
900     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
901     CY_CRYPTO_VU_ADD (base, partial, partial, my_z);    /* z = hi*coeff + lo */
902 
903     /* Step 7: 6th round of shift-multiply */
904     CY_CRYPTO_VU_LSR (base, hi, partial, sh256);        /* hi = partial>>CURVE_SIZE = partial[511:256] */
905     CY_CRYPTO_VU_MOV (base, my_z, partial);             /* z == lo = partial[255:0] */
906 
907     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
908     CY_CRYPTO_VU_ADD (base, partial, partial, my_z);    /* z = hi*coeff + lo */
909 
910     /* Step 8: 7th round of shift-multiply */
911     CY_CRYPTO_VU_LSR (base, hi, partial, sh256);        /* hi = partial>>CURVE_SIZE = partial[511:256] */
912     CY_CRYPTO_VU_MOV (base, my_z, partial);             /* z == lo = partial[255:0] */
913 
914     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
915     CY_CRYPTO_VU_ADD (base, partial, partial, my_z);    /* z = hi*coeff + lo */
916 
917     /* Step 9: 8th round of shift-multiply */
918     CY_CRYPTO_VU_LSR (base, hi, partial, sh256);        /* hi = partial>>CURVE_SIZE = partial[511:256] */
919     CY_CRYPTO_VU_MOV (base, my_z, partial);             /* z == lo = partial[255:0] */
920 
921     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
922     CY_CRYPTO_VU_ADD (base, my_z, partial, my_z);       /* z = hi*coeff + lo */
923 
924     /* Step 11: Final reduction (compare to P-256 and reduce if necessary, based on CARRY flag) */
925     CY_CRYPTO_VU_CMP_SUB (base, my_z, VR_P);            /* C = (z >= VR_P) */
926     CY_CRYPTO_VU_COND_SUB(base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);
927 
928     CY_CRYPTO_VU_FREE_MEM(base, CY_CRYPTO_VU_REG_BIT(partial) | CY_CRYPTO_VU_REG_BIT(hi) | CY_CRYPTO_VU_REG_BIT(coeff));
929     CY_CRYPTO_VU_POP_REG(base);
930 }
931 
932 
933 /*******************************************************************************
934 * Function Name: Cy_Crypto_Core_EC_SM_MUL_Red_P384
935 ****************************************************************************//**
936 *
937 * Shift-multiply modular reduction algorithm.
938 * a*b mod p
939 * 0 <= a, b < P384
940 *
941 * \param base
942 * The pointer to a Crypto instance.
943 *
944 * \param z
945 * Result.
946 *
947 * \param x
948 * Product.
949 *
950 *******************************************************************************/
Cy_Crypto_Core_EC_SM_MUL_Red_P384(CRYPTO_Type * base,uint32_t z,uint32_t x)951 static void Cy_Crypto_Core_EC_SM_MUL_Red_P384(CRYPTO_Type *base, uint32_t z, uint32_t x)
952 {
953     /* Pre-computed coefficient for shift-multiply modular reduction for P384 */
954     const uint8_t P384_ShMul_COEFF[] = {
955         0x01u, 0x00u, 0x00u, 0x00u, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
956         0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u,
957         0x01u
958     };
959 
960     /* Setup */
961     uint32_t partial = 0u;
962     uint32_t hi      = 1u;
963     uint32_t sh96    = 2u;
964     uint32_t sh384   = 3u;
965     uint32_t my_z    = 4u;
966     uint32_t my_x    = 5u;
967     uint32_t coeff   = 6u;
968 
969     CY_CRYPTO_VU_PUSH_REG (base);
970 
971     CY_CRYPTO_VU_LD_REG (base, my_z, z);
972     CY_CRYPTO_VU_LD_REG (base, my_x, x);
973 
974     CY_CRYPTO_VU_ALLOC_MEM (base, partial, CY_CRYPTO_ECC_P384_SIZE + 129u);
975     CY_CRYPTO_VU_ALLOC_MEM (base, hi, CY_CRYPTO_ECC_P384_SIZE + 96u);
976     CY_CRYPTO_VU_ALLOC_MEM (base, coeff, 129u);
977 
978     CY_CRYPTO_VU_SET_REG (base, sh96, 96u, 1u);
979     CY_CRYPTO_VU_SET_REG (base, sh384, 384u, 1u);
980 
981     Cy_Crypto_Core_Vu_SetMemValue (base, coeff, P384_ShMul_COEFF, 129u);
982 
983     /* Step 2: 1st round of shift-multiply
984     * (Separate hi and lo (LSR hi>>CURVE_SIZE), multiply hi*c and add hi*coeff + lo)
985     * hi*coeff + lo
986     */
987     CY_CRYPTO_VU_LSR (base, hi, my_x, sh384);           /* hi = prod >> CURVE_SIZE = prod[767:384] */
988     CY_CRYPTO_VU_MOV (base, my_z, my_x);                /* z == lo = prod[383:0] */
989 
990     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
991     CY_CRYPTO_VU_ADD (base, partial, partial, my_z);    /* partial = hi*coeff + lo */
992 
993     /* Step 3: 2nd round of shift-multiply */
994     CY_CRYPTO_VU_LSR (base, hi, partial, sh384);        /* hi = partial>>CURVE_SIZE = partial[767:384] */
995     CY_CRYPTO_VU_MOV (base, my_z, partial);             /* z == lo = partial[383:0] */
996 
997     CY_CRYPTO_VU_UMUL (base, partial, hi, coeff);       /* partial = hi*coeff */
998     CY_CRYPTO_VU_ADD (base, my_z, partial, my_z);       /* z = hi*coeff + lo */
999 
1000     /* Step 4: Final reduction (compare to P-384 and reduce if necessary, based on CARRY flag) */
1001     CY_CRYPTO_VU_CMP_SUB  (base, my_z, VR_P);           /* C = (z >= VR_P) */
1002     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);
1003 
1004     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(partial) | CY_CRYPTO_VU_REG_BIT(hi) | CY_CRYPTO_VU_REG_BIT(coeff));
1005     CY_CRYPTO_VU_POP_REG (base);
1006 }
1007 
1008 
1009 /*******************************************************************************
1010 * Function Name: Cy_Crypto_Core_EC_SM_MUL_Red_P521
1011 ****************************************************************************//**
1012 *
1013 * Curve-specific multiplication modular reduction for P521; equivalent to shift-multiply method for P521.
1014 * 0 <= a, b < P521
1015 * P521 = 2^521 - 1
1016 * a*b = T = T1*2^521 + T0
1017 * T1 = t1041..t521
1018 * T0 = t520..t0
1019 * T mod p521 = T0 + T1 mod P521
1020 *
1021 * \param base
1022 * The pointer to a Crypto instance.
1023 *
1024 * \param z
1025 * Result = x mod P = a*b mod P [521 bits].
1026 *
1027 * \param x
1028 * Product = a*b [2*521 bits].
1029 *
1030 *******************************************************************************/
Cy_Crypto_Core_EC_SM_MUL_Red_P521(CRYPTO_Type * base,uint32_t z,uint32_t x)1031 static void Cy_Crypto_Core_EC_SM_MUL_Red_P521(CRYPTO_Type *base, uint32_t z, uint32_t x)
1032 {
1033     uint32_t sh521   = 0u;
1034     uint32_t t0      = 1u;
1035     uint32_t my_z    = 2u;
1036     uint32_t my_x    = 3u;
1037 
1038     CY_CRYPTO_VU_PUSH_REG (base);
1039 
1040     CY_CRYPTO_VU_LD_REG (base, my_z, z);
1041     CY_CRYPTO_VU_LD_REG (base, my_x, x);
1042 
1043     CY_CRYPTO_VU_ALLOC_MEM (base, t0, CY_CRYPTO_ECC_P521_SIZE);     /* 521 */
1044 
1045     CY_CRYPTO_VU_SET_REG (base, sh521, 521u, 1u);       /* sh521  = 521 */
1046 
1047     CY_CRYPTO_VU_LSR (base, my_z, my_x, sh521);         /* z = T1 */
1048 
1049     CY_CRYPTO_VU_ADD (base, my_z, my_z, my_x);          /* z = T1 + T0 */
1050 
1051     /* T0 + T1 mod p */
1052     CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, my_z, VR_P);     /* C = (t2 >= VR_P) */
1053     CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, my_z, my_z, VR_P);   /* t2 = t2 - p, if C==1 (Carry is set) */
1054 
1055     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t0));
1056     CY_CRYPTO_VU_POP_REG (base);
1057 
1058 }
1059 
1060 
1061 /*******************************************************************************
1062 * Function Name: Cy_Crypto_Core_EC_SM_MulRed
1063 ****************************************************************************//**
1064 *
1065 *
1066 *
1067 * \param base
1068 * The pointer to a Crypto instance.
1069 *
1070 * \param z
1071 * Result.
1072 *
1073 * \param x
1074 * Product.
1075 *
1076 * \param size
1077 * Size.
1078 *
1079 *******************************************************************************/
Cy_Crypto_Core_EC_SM_MulRed(CRYPTO_Type * base,uint32_t z,uint32_t x,uint32_t size)1080 static void Cy_Crypto_Core_EC_SM_MulRed(CRYPTO_Type *base, uint32_t z, uint32_t x, uint32_t size)
1081 {
1082     (void)size; /* Suppress warning */
1083 
1084     switch (eccMode) {
1085         case CY_CRYPTO_ECC_ECP_SECP192R1:
1086             Cy_Crypto_Core_EC_SM_MUL_Red_P192(base, z, x);
1087             break;
1088         case CY_CRYPTO_ECC_ECP_SECP224R1:
1089             Cy_Crypto_Core_EC_SM_MUL_Red_P224(base, z, x);
1090             break;
1091         case CY_CRYPTO_ECC_ECP_SECP256R1:
1092             Cy_Crypto_Core_EC_SM_MUL_Red_P256(base, z, x);
1093             break;
1094         case CY_CRYPTO_ECC_ECP_SECP384R1:
1095             Cy_Crypto_Core_EC_SM_MUL_Red_P384(base, z, x);
1096             break;
1097         case CY_CRYPTO_ECC_ECP_SECP521R1:
1098             Cy_Crypto_Core_EC_SM_MUL_Red_P521(base, z, x);
1099             break;
1100         default:
1101         /* Unsupported Eliptic Curve ID */
1102             break;
1103     }
1104 }
1105 
1106 
1107 /***************************************************************
1108 *           Generic Barrett modular reduction
1109 ***************************************************************/
1110 
1111 
1112 /*******************************************************************************
1113 * Function Name: Cy_Crypto_Core_EC_Bar_MulRed
1114 ****************************************************************************//**
1115 *
1116 * Curve-specific multiplication modular reduction for P224.
1117 * t[b-1:0] = z_double >> size
1118 * t = t * VR_BARRETT
1119 * t = t + ((z_double >> size) << size)  - for leading '1' Barrett bit.
1120 * t = t >> size
1121 * t = t * mod                           - r2 (not reduced)
1122 * u = z_double - t                      - r = r1 - r2 (not reduced)
1123 *
1124 * u = IF (u >= mod) u = u - mod         - reduce r using mod
1125 * u = IF (u >= mod) u = u - mod
1126 *
1127 * z = a_double % mod
1128 *
1129 * Leaf function.
1130 *
1131 * \param base
1132 * The pointer to a Crypto instance.
1133 *
1134 * \param z
1135 * Register index for Barrett reduced value.
1136 *
1137 * \param x
1138 * Register index for non reduced value.
1139 *
1140 * \param size
1141 * Bit size.
1142 *
1143 *******************************************************************************/
Cy_Crypto_Core_EC_Bar_MulRed(CRYPTO_Type * base,uint32_t z,uint32_t x,uint32_t size)1144 void Cy_Crypto_Core_EC_Bar_MulRed(CRYPTO_Type *base,
1145     uint32_t z,
1146     uint32_t x,
1147     uint32_t size)
1148 {
1149 
1150     uint32_t sh          = 0u;
1151     uint32_t t1          = 1u;
1152     uint32_t t1_plus2    = 1u;
1153     uint32_t t2_plus2    = 0u;
1154     uint32_t t_double    = 2u;
1155     uint32_t z_double    = 3u;
1156     uint32_t my_z        = 4u;
1157 
1158     CY_CRYPTO_VU_PUSH_REG (base);
1159 
1160     CY_CRYPTO_VU_LD_REG (base, my_z, z);
1161     CY_CRYPTO_VU_LD_REG (base, z_double, x);
1162 
1163     CY_CRYPTO_VU_ALLOC_MEM (base, t_double, 2u * size);
1164     CY_CRYPTO_VU_ALLOC_MEM (base, t1, size);
1165 
1166     CY_CRYPTO_VU_SET_REG (base, sh, size, 1u);              /* sh = k (k \equiv size) */
1167     CY_CRYPTO_VU_LSR (base, my_z, z_double, sh);            /* a/b^{k} (q1*b) */
1168 
1169     CY_CRYPTO_VU_UMUL (base, t_double, my_z, VR_BARRETT);   /* a/b^{k}*VR_BARRETT (q2*b) */
1170     CY_CRYPTO_VU_LSR (base, t1, t_double, sh);              /* q2*b/b^{k} = q2/b^{k-1} */
1171 
1172     CY_CRYPTO_VU_UMUL (base, t_double, t1, VR_P);
1173 
1174     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t1));
1175 
1176     CY_CRYPTO_VU_ALLOC_MEM (base, t1_plus2, size + 2u);
1177     CY_CRYPTO_VU_ALLOC_MEM (base, t2_plus2, size + 2u);
1178 
1179     CY_CRYPTO_VU_SUB (base, t2_plus2, z_double, t_double);
1180 
1181     CY_CRYPTO_VU_SUB (base, t1_plus2, t2_plus2, VR_P);
1182     CY_CRYPTO_VU_COND_SWAP_REG (base, CY_CRYPTO_VU_COND_CC, t1_plus2, t2_plus2);
1183 
1184     CY_CRYPTO_VU_SUB (base, t2_plus2, t1_plus2, VR_P);
1185     CY_CRYPTO_VU_COND_MOV (base, CY_CRYPTO_VU_COND_CC, my_z, t1_plus2);
1186     CY_CRYPTO_VU_COND_MOV (base, CY_CRYPTO_VU_COND_CS, my_z, t2_plus2);
1187 
1188     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t2_plus2) |
1189                                  CY_CRYPTO_VU_REG_BIT(t1_plus2) |
1190                                  CY_CRYPTO_VU_REG_BIT(t_double));
1191     CY_CRYPTO_VU_POP_REG (base);
1192 }
1193 
1194 
1195 /***************************************************************
1196 *       Multiplication reduction algorithm select
1197 ***************************************************************/
1198 
1199 
1200 /*******************************************************************************
1201 * Function Name: Cy_Crypto_Core_EC_MulRed
1202 ****************************************************************************//**
1203 *
1204 * \param base
1205 * The pointer to a Crypto instance.
1206 *
1207 * \param z
1208 * Result = x mod P = a*b mod P [224 bits].
1209 *
1210 * \param x
1211 * Product = a*b [2*224 bits].
1212 *
1213 * \param size
1214 * Bit size.
1215 *
1216 *******************************************************************************/
Cy_Crypto_Core_EC_MulRed(CRYPTO_Type * base,uint32_t z,uint32_t x,uint32_t size)1217 static void Cy_Crypto_Core_EC_MulRed(CRYPTO_Type *base, uint32_t z, uint32_t x, uint32_t size)
1218 {
1219     switch (mul_red_alg_select)
1220     {
1221         case CY_CRYPTO_NIST_P_CURVE_SPECIFIC_RED_ALG:
1222                 /* Curve-specific multiplication reduction algorithms */
1223                 Cy_Crypto_Core_EC_CS_MulRed(base, z, x, size);
1224             break;
1225         case CY_CRYPTO_NIST_P_SHIFT_MUL_RED_ALG:
1226                 /* Shift-multiply, curve-specific multiplication reduction algorithms */
1227                 Cy_Crypto_Core_EC_SM_MulRed(base, z, x, size);
1228             break;
1229         default:
1230                 /* Generic Barrett modular reduction */
1231                 Cy_Crypto_Core_EC_Bar_MulRed(base, z, x, size);
1232             break;
1233     }
1234 }
1235 
1236 
1237 /*******************************************************************************
1238 * Function Name: Cy_Crypto_Core_EC_MulMod
1239 ****************************************************************************//**
1240 *
1241 * Modular multiplication in GF(VR_P).
1242 * Leaf function.
1243 *
1244 * \param base
1245 * The pointer to a Crypto instance.
1246 *
1247 * \param z
1248 * Result = a * b % mod. Register index for product value.
1249 *
1250 * \param a
1251 * Register index for multiplicand value.
1252 *
1253 * \param b
1254 * Register index for multiplier value.
1255 *
1256 * \param size
1257 * Bit size.
1258 *
1259 *******************************************************************************/
Cy_Crypto_Core_EC_MulMod(CRYPTO_Type * base,uint32_t z,uint32_t a,uint32_t b,uint32_t size)1260 void Cy_Crypto_Core_EC_MulMod( CRYPTO_Type *base,
1261     uint32_t z,
1262     uint32_t a,
1263     uint32_t b,
1264     uint32_t size)
1265 {
1266     uint32_t ab_double       = 0u;
1267     uint32_t my_z            = 1u;
1268     uint32_t my_a            = 2u;
1269     uint32_t my_b            = 3u;
1270 
1271     CY_CRYPTO_VU_PUSH_REG (base);
1272 
1273     CY_CRYPTO_VU_LD_REG(base, my_z, z);
1274     CY_CRYPTO_VU_LD_REG(base, my_a, a);
1275     CY_CRYPTO_VU_LD_REG(base, my_b, b);
1276 
1277     CY_CRYPTO_VU_ALLOC_MEM (base, ab_double, 2u * size);
1278 
1279     CY_CRYPTO_VU_UMUL (base, ab_double, my_a, my_b);
1280     Cy_Crypto_Core_Vu_WaitForComplete(base);
1281 
1282     /* Modular Reduction: Barrett reduction or curve-specific or shift-multiply */
1283     Cy_Crypto_Core_EC_MulRed(base, my_z, ab_double, size);
1284 
1285     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(ab_double));
1286 
1287     CY_CRYPTO_VU_POP_REG (base);
1288 }
1289 
1290 
1291 /*******************************************************************************
1292 * Function Name: Cy_Crypto_Core_EC_AddMod
1293 ****************************************************************************//**
1294 *
1295 * Modular addition in GF(VR_P).
1296 *
1297 * \param base
1298 * The pointer to a Crypto instance.
1299 *
1300 * \param z
1301 * Result = a + b % mod. Register index for sum value
1302 *
1303 * \param a
1304 * Register index for augend a value.
1305 *
1306 * \param b
1307 * Register index for addend b value.
1308 *
1309 *******************************************************************************/
Cy_Crypto_Core_EC_AddMod(CRYPTO_Type * base,uint32_t z,uint32_t a,uint32_t b)1310 void Cy_Crypto_Core_EC_AddMod( CRYPTO_Type *base, uint32_t z, uint32_t a, uint32_t b)
1311 {
1312    CY_CRYPTO_VU_ADD (base, z, a, b);                                /* C = (sum >= 2^n) */
1313    CY_CRYPTO_VU_COND_CMP_SUB (base, CY_CRYPTO_VU_COND_CC, z, VR_P); /* C = (sum >= mod) */
1314    CY_CRYPTO_VU_COND_SUB (base, CY_CRYPTO_VU_COND_CS, z, z, VR_P);
1315 }
1316 
1317 
1318 /*******************************************************************************
1319 * Function Name: Cy_Crypto_Core_EC_SubMod
1320 ****************************************************************************//**
1321 *
1322 * Modular subtraction in GF(VR_P).
1323 *
1324 * \param base
1325 * The pointer to a Crypto instance.
1326 *
1327 * \param z
1328 * Result = a - b % mod. Register index for difference value.
1329 *
1330 * \param a
1331 * Register index for minuend a value.
1332 *
1333 * \param b
1334 * RRegister index for subtrahend b value.
1335 *
1336 *******************************************************************************/
Cy_Crypto_Core_EC_SubMod(CRYPTO_Type * base,uint32_t z,uint32_t a,uint32_t b)1337 void Cy_Crypto_Core_EC_SubMod( CRYPTO_Type *base, uint32_t z, uint32_t a, uint32_t b)
1338 {
1339    CY_CRYPTO_VU_SUB (base, z, a, b);       /* C = (a >= b) */
1340    CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_CC, z, z, VR_P);
1341 }
1342 
1343 
1344 /*******************************************************************************
1345 * Function Name: Cy_Crypto_Core_EC_HalfMod
1346 ****************************************************************************//**
1347 *
1348 * Modular halving in GF(VR_P).
1349 * Leaf function.
1350 *
1351 * \param base
1352 * The pointer to a Crypto instance.
1353 *
1354 * \param z
1355 * Result = a / 2 % mod.Register index for result value.
1356 *
1357 * \param a
1358 * Register index for value to be halved.
1359 *
1360 *******************************************************************************/
Cy_Crypto_Core_EC_HalfMod(CRYPTO_Type * base,uint32_t z,uint32_t a)1361 void Cy_Crypto_Core_EC_HalfMod( CRYPTO_Type *base, uint32_t z, uint32_t a)
1362 {
1363    CY_CRYPTO_VU_TST (base, a);
1364    CY_CRYPTO_VU_COND_ADD (base, CY_CRYPTO_VU_COND_ODD, a, a, VR_P);
1365    CY_CRYPTO_VU_LSR1_WITH_CARRY (base, z, a);
1366 }
1367 
1368 
1369 /*******************************************************************************
1370 * Function Name: Cy_Crypto_Core_EC_SquareMod
1371 ****************************************************************************//**
1372 *
1373 * Modular squaring in GF(VR_P).
1374 *
1375 * \param base
1376 * The pointer to a Crypto instance.
1377 *
1378 * \param z
1379 * Result = a * a % mod. Register index for product value.
1380 *
1381 * \param a
1382 * Register index for multiplicand and multiplier value.
1383 *
1384 * \param size
1385 * Bit size.
1386 *
1387 *******************************************************************************/
Cy_Crypto_Core_EC_SquareMod(CRYPTO_Type * base,uint32_t z,uint32_t a,uint32_t size)1388 void Cy_Crypto_Core_EC_SquareMod( CRYPTO_Type *base,
1389     uint32_t z,
1390     uint32_t a,
1391     uint32_t size)
1392 {
1393     Cy_Crypto_Core_EC_MulMod( base, z, a, a, size);
1394 }
1395 
1396 
1397 /*******************************************************************************
1398 * Function Name: Cy_Crypto_Core_EC_DivMod
1399 ****************************************************************************//**
1400 *
1401 * Modular division in GF(VR_P).
1402 * This algorithm works when "dividend" and "divisor" are relatively prime,
1403 * Reference: "From Euclid's GCD to Montgomery Multiplication to the Great Divide",
1404 * S.C. Schantz
1405 *
1406 * \param base
1407 * The pointer to a Crypto instance.
1408 *
1409 * \param z
1410 * Result = a / b % mod. Register index for quotient value.
1411 *
1412 * \param a
1413 * Register index for dividend value.
1414 *
1415 * \param b
1416 * Register index for divisor value.
1417 *
1418 * \param size
1419 * Bit size.
1420 *
1421 *******************************************************************************/
Cy_Crypto_Core_EC_DivMod(CRYPTO_Type * base,uint32_t z,uint32_t a,uint32_t b,uint32_t size)1422 void Cy_Crypto_Core_EC_DivMod( CRYPTO_Type *base,
1423     uint32_t z,
1424     uint32_t a,
1425     uint32_t b,
1426     uint32_t size)
1427 {
1428     uint32_t my_dividend = 7u;
1429     uint32_t my_divisor  = 8u;
1430     uint32_t my_a        = 9u;
1431     uint32_t my_b        = 10u;
1432     uint32_t my_u        = 11u;
1433     uint32_t my_v        = 12u;
1434 
1435     uint32_t zero;
1436     uint32_t carry;
1437     uint32_t a_even;
1438     uint32_t b_even;
1439 
1440     uint32_t status0;
1441     uint32_t status1;
1442     uint32_t status2;
1443 
1444     CY_CRYPTO_VU_PUSH_REG (base);
1445 
1446     CY_CRYPTO_VU_LD_REG(base, my_dividend, a);
1447     CY_CRYPTO_VU_LD_REG(base, my_divisor, b);
1448     CY_CRYPTO_VU_LD_REG(base, my_u, z);
1449 
1450     CY_CRYPTO_VU_ALLOC_MEM (base, my_a, size);
1451     CY_CRYPTO_VU_ALLOC_MEM (base, my_b, size);
1452     CY_CRYPTO_VU_ALLOC_MEM (base, my_v, size);
1453 
1454     CY_CRYPTO_VU_MOV (base, my_a, my_divisor);
1455     CY_CRYPTO_VU_MOV (base, my_b, VR_P);
1456     CY_CRYPTO_VU_MOV (base, my_u, my_dividend);
1457 
1458     CY_CRYPTO_VU_SET_TO_ZERO (base, my_v);
1459 
1460     while (true)
1461     {
1462         CY_CRYPTO_VU_CMP_SUB (base, my_a, my_b);
1463         status0 = Cy_Crypto_Core_Vu_StatusRead(base);
1464 
1465         CY_CRYPTO_VU_TST (base, my_a);
1466         status1 = Cy_Crypto_Core_Vu_StatusRead(base);
1467 
1468         CY_CRYPTO_VU_TST (base, my_b);
1469         status2 = Cy_Crypto_Core_Vu_StatusRead(base);
1470 
1471         zero    = status0 & CY_CRYPTO_VU_STATUS_ZERO_BIT;  /* a == b */
1472         carry   = status0 & CY_CRYPTO_VU_STATUS_CARRY_BIT; /* a >= b */
1473         a_even  = status1 & CY_CRYPTO_VU_STATUS_EVEN_BIT;
1474         b_even  = status2 & CY_CRYPTO_VU_STATUS_EVEN_BIT;
1475 
1476         if (0u != zero)
1477         {
1478             break;
1479         }
1480 
1481         if (0u != a_even)
1482         {
1483             CY_CRYPTO_VU_LSR1 (base, my_a, my_a);
1484             Cy_Crypto_Core_EC_HalfMod( base, my_u, my_u);
1485         }
1486         else if (0u != b_even)
1487         {
1488             CY_CRYPTO_VU_LSR1 (base, my_b, my_b);
1489             Cy_Crypto_Core_EC_HalfMod( base, my_v, my_v);
1490         }
1491         else if (0u != carry)
1492         { /* (a >= b) */
1493             CY_CRYPTO_VU_SUB  (base, my_a, my_a, my_b);
1494             CY_CRYPTO_VU_LSR1 (base, my_a, my_a);
1495 
1496             Cy_Crypto_Core_EC_SubMod(  base, my_u, my_u, my_v);
1497             Cy_Crypto_Core_EC_HalfMod( base, my_u, my_u);
1498         }
1499         else
1500         {
1501             CY_CRYPTO_VU_SUB  (base, my_b, my_b, my_a);
1502             CY_CRYPTO_VU_LSR1 (base, my_b, my_b);
1503 
1504             Cy_Crypto_Core_EC_SubMod(  base, my_v, my_v, my_u);
1505             Cy_Crypto_Core_EC_HalfMod( base, my_v, my_v);
1506         }
1507     }
1508 
1509     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(my_a) | CY_CRYPTO_VU_REG_BIT(my_b) | CY_CRYPTO_VU_REG_BIT(my_v));
1510 
1511     CY_CRYPTO_VU_POP_REG (base);
1512 }
1513 
1514 
1515 /*******************************************************************************
1516 * Function Name: Cy_Crypto_Core_JacobianTransform
1517 ****************************************************************************//**
1518 *
1519 * Transformation from affine coordinates to Jacobian projective coordinates in GF(VR_P).
1520 *
1521 * \param base
1522 * The pointer to a Crypto instance.
1523 *
1524 * \param s_x
1525 * Register index for affine X coordinate and Jacobian projective X coordinate.
1526 *
1527 * \param s_y
1528 * Register index for affine Y coordinate and Jacobian projective Y coordinate.
1529 *
1530 * \param s_z
1531 * Register index for Jacobian projective Z coordinate.
1532 *
1533 *******************************************************************************/
Cy_Crypto_Core_JacobianTransform(CRYPTO_Type * base,uint32_t s_x,uint32_t s_y,uint32_t s_z)1534 void Cy_Crypto_Core_JacobianTransform(CRYPTO_Type *base, uint32_t s_x, uint32_t s_y, uint32_t s_z)
1535 {
1536     (void)s_x; /* Suppress warning */
1537     (void)s_y; /* Suppress warning */
1538     CY_CRYPTO_VU_SET_TO_ONE (base, s_z);
1539 }
1540 
1541 
1542 /*******************************************************************************
1543 * Function Name: Cy_Crypto_Core_JacobianInvTransform
1544 ****************************************************************************//**
1545 *
1546 * Transformation from Jacobian projective coordinates to affine coordinates in GF(VR_P).
1547 * (s_x, s_y, s_z) -> (p_x, p_y), where p_x = s_x/s_z^2, p_y = s_y/s_z^3
1548 *
1549 * \param base
1550 * The pointer to a Crypto instance.
1551 *
1552 * \param s_x
1553 * Register index for affine X coordinate and Jacobian projective X coordinate.
1554 *
1555 * \param s_y
1556 * Register index for affine Y coordinate and Jacobian projective Y coordinate.
1557 *
1558 * \param s_z
1559 * Register index for Jacobian projective Z coordinate.
1560 *
1561 * \param size
1562 * Bit size.
1563 *
1564 *******************************************************************************/
Cy_Crypto_Core_JacobianInvTransform(CRYPTO_Type * base,uint32_t s_x,uint32_t s_y,uint32_t s_z,uint32_t size)1565 void Cy_Crypto_Core_JacobianInvTransform(CRYPTO_Type *base, uint32_t s_x, uint32_t s_y, uint32_t s_z, uint32_t size)
1566 {
1567 
1568     uint32_t t1     = 7u;
1569     uint32_t t2     = 8u;
1570     uint32_t t3     = 9u;
1571     uint32_t my_s_x = 10u;
1572     uint32_t my_s_y = 11u;
1573     uint32_t my_s_z = 12u;
1574 
1575     CY_CRYPTO_VU_PUSH_REG (base);
1576 
1577     CY_CRYPTO_VU_LD_REG(base, my_s_x, s_x);
1578     CY_CRYPTO_VU_LD_REG(base, my_s_y, s_y);
1579     CY_CRYPTO_VU_LD_REG(base, my_s_z, s_z);
1580 
1581     CY_CRYPTO_VU_ALLOC_MEM (base, t1, size);
1582     CY_CRYPTO_VU_ALLOC_MEM (base, t2, size);
1583     CY_CRYPTO_VU_ALLOC_MEM (base, t3, size);
1584 
1585     CY_CRYPTO_VU_SET_TO_ONE (base, t1);                     /* t1 = 1 */
1586     Cy_Crypto_Core_EC_DivMod( base, t2, t1, my_s_z, size);  /* t2 = 1/Z */
1587 
1588     Cy_Crypto_Core_EC_SquareMod( base, t1, t2, size);       /* t1 = 1/Z^2 */
1589     Cy_Crypto_Core_EC_MulMod( base, my_s_x, my_s_x, t1, size);  /* my_s_x = X/Z^2 */
1590 
1591     Cy_Crypto_Core_EC_MulMod( base, t3, my_s_y, t1, size);  /* t3 = Y/Z^2 */
1592     Cy_Crypto_Core_EC_MulMod( base, my_s_y, t3, t2, size);  /* my_s_y = Y/Z^3 */
1593 
1594     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t1) | CY_CRYPTO_VU_REG_BIT(t2) | CY_CRYPTO_VU_REG_BIT(t3));
1595 
1596     CY_CRYPTO_VU_POP_REG (base);
1597 }
1598 
1599 
1600 /*******************************************************************************
1601 * Function Name: Cy_Crypto_Core_JacobianEcAdd
1602 ****************************************************************************//**
1603 *
1604 * Elliptic curve point addition on mixed Jacobian projective (s) / affine (t) coordinates in GF(VR_P).
1605 * Reference: "fast and regular algorithms for scalar multiplication over elliptic curves", M. Rivain.
1606 * Upper case register variables refer to Jacobian projective coordinate values.
1607 * Lower case register variables refer to affine coordinate values.
1608 *
1609 * \param base
1610 * The pointer to a Crypto instance.
1611 *
1612 * \param s_x
1613 * Register index for Jacobian projective X coordinate.
1614 *
1615 * \param s_y
1616 * Register index for Jacobian projective Y coordinate.
1617 *
1618 * \param s_z
1619 * Register index for Jacobian projective Z coordinate.
1620 *
1621 * \param t_x
1622 * Register index for affine X coordinate.
1623 *
1624 * \param t_y
1625 * Register index for affine Y coordinate.
1626 *
1627 * \param size
1628 * Bit size.
1629 *
1630 *******************************************************************************/
Cy_Crypto_Core_JacobianEcAdd(CRYPTO_Type * base,uint32_t s_x,uint32_t s_y,uint32_t s_z,uint32_t t_x,uint32_t t_y,uint32_t size)1631 void Cy_Crypto_Core_JacobianEcAdd(CRYPTO_Type *base,
1632     uint32_t s_x,
1633     uint32_t s_y,
1634     uint32_t s_z,
1635     uint32_t t_x,
1636     uint32_t t_y,
1637     uint32_t size
1638 )
1639 {
1640 
1641     uint32_t t6     = 4u;
1642     uint32_t t7     = 5u;
1643     uint32_t t8     = 6u;
1644     uint32_t t9     = 7u;
1645     uint32_t my_s_x = 8u;
1646     uint32_t my_s_y = 9u;
1647     uint32_t my_s_z = 10u;
1648     uint32_t my_t_x = 11u;
1649     uint32_t my_t_y = 12u;
1650 
1651     CY_CRYPTO_VU_PUSH_REG (base);
1652 
1653     CY_CRYPTO_VU_LD_REG(base, my_s_x, s_x);
1654     CY_CRYPTO_VU_LD_REG(base, my_s_y, s_y);
1655     CY_CRYPTO_VU_LD_REG(base, my_s_z, s_z);
1656     CY_CRYPTO_VU_LD_REG(base, my_t_x, t_x);
1657     CY_CRYPTO_VU_LD_REG(base, my_t_y, t_y);
1658 
1659     CY_CRYPTO_VU_ALLOC_MEM (base, t6, size);
1660     CY_CRYPTO_VU_ALLOC_MEM (base, t7, size);
1661     CY_CRYPTO_VU_ALLOC_MEM (base, t8, size);
1662     CY_CRYPTO_VU_ALLOC_MEM (base, t9, size);
1663 
1664     Cy_Crypto_Core_EC_SquareMod( base, t6, my_s_z, size);       /* t6 = ZZ */
1665     Cy_Crypto_Core_EC_MulMod( base, t8, my_t_x, t6, size);      /* t8 = xZZ = B */
1666     Cy_Crypto_Core_EC_MulMod( base, t7, my_t_y, my_s_z, size);  /* t7 = yZ */
1667     Cy_Crypto_Core_EC_SubMod( base, my_s_x, my_s_x, t8);        /* my_s_x = X - B = E */
1668 
1669     Cy_Crypto_Core_EC_MulMod( base, my_s_z, my_s_x, my_s_z, size);  /* my_s_z = E*Z = Z3 */
1670     Cy_Crypto_Core_EC_MulMod( base, t9, t7, t6, size);          /* t9 = yZZZ = D */
1671     Cy_Crypto_Core_EC_SubMod( base, my_s_y, my_s_y, t9);        /* my_s_y = Y - D = F */
1672     Cy_Crypto_Core_EC_SquareMod( base, t6, my_s_x, size);       /* t6 = EE */
1673 
1674     Cy_Crypto_Core_EC_MulMod( base, t7, t8, t6, size);          /* t7 = B*EE */
1675     Cy_Crypto_Core_EC_MulMod( base, t8, t6, my_s_x, size);      /* t8 = EEE */
1676     Cy_Crypto_Core_EC_MulMod( base, t6, t9, t8, size);          /* t6 = D*EEE */
1677     Cy_Crypto_Core_EC_SquareMod( base, my_s_x, my_s_y, size);   /* my_s_x = FF */
1678     Cy_Crypto_Core_EC_SubMod( base, my_s_x, my_s_x, t8);        /* my_s_x = FF - EEE */
1679     Cy_Crypto_Core_EC_AddMod( base, t9, t7, t7);                /* t9 = 2*B*EE */
1680     Cy_Crypto_Core_EC_SubMod( base, my_s_x, my_s_x, t9);        /* my_s_x = FF - EEE - 2*B*EE = X3 */
1681     Cy_Crypto_Core_EC_SubMod( base, t7, t7, my_s_x);            /* t7 = B*EE - X3 */
1682     Cy_Crypto_Core_EC_MulMod( base, my_s_y, my_s_y, t7, size);  /* my_s_y = F*(B*EE - X3) */
1683     Cy_Crypto_Core_EC_SubMod( base, my_s_y, my_s_y, t6);        /* my_s_y = F*(3*B*EE - FF + EEE) - D*EEE = Y3 */
1684 
1685     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t6) | CY_CRYPTO_VU_REG_BIT(t7) |
1686                                  CY_CRYPTO_VU_REG_BIT(t8) | CY_CRYPTO_VU_REG_BIT(t9));
1687 
1688     CY_CRYPTO_VU_POP_REG (base);
1689 }
1690 
1691 
1692 /*******************************************************************************
1693 * Function Name: Cy_Crypto_Core_JacobianEcDouble
1694 ****************************************************************************//**
1695 *
1696 * Elliptic curve point doubling on Jacobian projective coordinates in GF(VR_P).
1697 *
1698 * \param base
1699 * The pointer to a Crypto instance.
1700 *
1701 * \param s_x
1702 * Register index for Jacobian projective X coordinate.
1703 *
1704 * \param s_y
1705 * Register index for Jacobian projective Y coordinate.
1706 *
1707 * \param s_z
1708 * Register index for Jacobian projective Z coordinate.
1709 *
1710 * \param size
1711 * Bit size.
1712 *
1713 *******************************************************************************/
Cy_Crypto_Core_JacobianEcDouble(CRYPTO_Type * base,uint32_t s_x,uint32_t s_y,uint32_t s_z,uint32_t size)1714 void Cy_Crypto_Core_JacobianEcDouble(CRYPTO_Type *base,
1715     uint32_t s_x,
1716     uint32_t s_y,
1717     uint32_t s_z,
1718     uint32_t size
1719 )
1720 /* 4M + 4S + 10A */
1721 {
1722     uint32_t t1     = 1u;
1723     uint32_t t2     = 2u;
1724     uint32_t t3     = 3u;
1725     uint32_t t4     = 4u;
1726     uint32_t my_s_x = 5u;
1727     uint32_t my_s_y = 6u;
1728     uint32_t my_s_z = 7u;
1729 
1730     CY_CRYPTO_VU_PUSH_REG (base);
1731 
1732     CY_CRYPTO_VU_LD_REG(base, my_s_x, s_x);
1733     CY_CRYPTO_VU_LD_REG(base, my_s_y, s_y);
1734     CY_CRYPTO_VU_LD_REG(base, my_s_z, s_z);
1735 
1736     CY_CRYPTO_VU_ALLOC_MEM (base, t1, size);
1737     CY_CRYPTO_VU_ALLOC_MEM (base, t2, size);
1738     CY_CRYPTO_VU_ALLOC_MEM (base, t3, size);
1739     CY_CRYPTO_VU_ALLOC_MEM (base, t4, size);
1740 
1741     Cy_Crypto_Core_EC_SquareMod( base, t4, my_s_y, size);       /* t4 = Y^2 */
1742     Cy_Crypto_Core_EC_SquareMod( base, t3, my_s_z, size);       /* t3 = Z^2 */
1743     Cy_Crypto_Core_EC_MulMod( base, my_s_z, my_s_y, my_s_z, size);  /* my_s_z = Y*Z */
1744 
1745     Cy_Crypto_Core_EC_MulMod( base, my_s_y, my_s_x, t4, size);  /* my_s_y = X*Y^2 = A */
1746     Cy_Crypto_Core_EC_AddMod( base, my_s_x, my_s_x, t3);        /* my_s_x = X + Z^2 */
1747     Cy_Crypto_Core_EC_AddMod( base, t3, t3, t3);                /* t3 = 2*Z^2 */
1748     Cy_Crypto_Core_EC_SubMod( base, t3, my_s_x, t3);            /* t3 = (X + Z^2) - 2*Z^2 = X - Z^2 */
1749     Cy_Crypto_Core_EC_MulMod( base, t1, my_s_x, t3, size);      /* t1 = (X + Z^2) * (X - Z^2) = X^2 - Z^4 */
1750 
1751     Cy_Crypto_Core_EC_AddMod( base, t3, t1, t1);                /* t3 = 2*(X^2 - Z^4) */
1752     Cy_Crypto_Core_EC_AddMod( base, t1, t1, t3);                /* t1 = 3*(X^2 - Z^4) */
1753     Cy_Crypto_Core_EC_HalfMod( base, t1, t1);                   /* t1 = 3/2*(X^2 - Z^4) = B */
1754     Cy_Crypto_Core_EC_SquareMod( base, t3, t1, size);           /* t3 = 9/4*(X^2 - Z^4) = B^2 */
1755 
1756     Cy_Crypto_Core_EC_SubMod( base, t3, t3, my_s_y);            /* t3 = B^2 - A */
1757     Cy_Crypto_Core_EC_SubMod( base, my_s_x, t3, my_s_y);        /* my_s_x =  B^2 - 2*A */
1758     Cy_Crypto_Core_EC_SubMod( base, my_s_y, my_s_y, my_s_x);    /* my_s_y = A - (B^2 - 2*A) = 3*A - B^2 */
1759     Cy_Crypto_Core_EC_MulMod( base, t2, t1, my_s_y, size);      /* t2 = B*(3*A - B^2) */
1760 
1761     Cy_Crypto_Core_EC_SquareMod( base, t1, t4, size);           /* t1 = Y^4 */
1762     Cy_Crypto_Core_EC_SubMod( base, my_s_y, t2, t1);            /* my_s_y = B*(3*A - B^2) - Y^4 */
1763 
1764     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(t1) | CY_CRYPTO_VU_REG_BIT(t2) |
1765                                  CY_CRYPTO_VU_REG_BIT(t3) | CY_CRYPTO_VU_REG_BIT(t4));
1766     CY_CRYPTO_VU_POP_REG (base);
1767 }
1768 
1769 
1770 /*******************************************************************************
1771 * Function Name: Cy_Crypto_Core_JacobianEcScalarMul
1772 ****************************************************************************//**
1773 *
1774 * Elliptic curve point multiplication on Jacobian projective coordinates in GF(VR_P).
1775 *
1776 * \param base
1777 * The pointer to a Crypto instance.
1778 *
1779 * \param s_x
1780 * Register index for affine X coordinate.
1781 *
1782 * \param s_y
1783 * Register index for affine Y coordinate.
1784 *
1785 * \param d
1786 * Register index for multiplication/exponentiation value.
1787 *
1788 * \param size
1789 * Bit size.
1790 *
1791 *******************************************************************************/
Cy_Crypto_Core_JacobianEcScalarMul(CRYPTO_Type * base,uint32_t s_x,uint32_t s_y,uint32_t d,uint32_t size)1792 void Cy_Crypto_Core_JacobianEcScalarMul(CRYPTO_Type *base, uint32_t s_x, uint32_t s_y, uint32_t d, uint32_t size)
1793 {
1794     uint32_t i;
1795     uint32_t status;
1796     uint32_t carry;
1797     uint16_t clsame;
1798 
1799     uint32_t clr     = 5u;
1800     uint32_t t       = 6u;
1801     uint32_t my_s_x  = 7u;
1802     uint32_t my_s_y  = 8u;
1803     uint32_t my_s_z  = 9u;
1804     uint32_t my_t_x  = 10u;
1805     uint32_t my_t_y  = 11u;
1806     uint32_t my_d    = 12u;
1807 
1808     CY_CRYPTO_VU_PUSH_REG (base);
1809 
1810     CY_CRYPTO_VU_LD_REG(base, my_s_x, s_x);
1811     CY_CRYPTO_VU_LD_REG(base, my_s_y, s_y);
1812     CY_CRYPTO_VU_LD_REG(base, my_d, d);
1813 
1814     CY_CRYPTO_VU_ALLOC_MEM (base, clr, size);
1815     CY_CRYPTO_VU_ALLOC_MEM (base, t, size);
1816     CY_CRYPTO_VU_ALLOC_MEM (base, my_s_z, size);
1817     CY_CRYPTO_VU_ALLOC_MEM (base, my_t_x, size);
1818     CY_CRYPTO_VU_ALLOC_MEM (base, my_t_y, size);
1819 
1820     /* my_t_x has the same initial value of my_s_x, but does not point to the
1821     * same address in memory as my_s_x, i.e. different value after point doubling
1822     * my_t_x and my_t_y do not change from (original Jacobian projective coordinates of)
1823     * original base point
1824     */
1825     CY_CRYPTO_VU_MOV (base, my_t_x, my_s_x);
1826     CY_CRYPTO_VU_MOV (base, my_t_y, my_s_y);
1827 
1828     /* Affine-to-Jacobian Transform. */
1829     CY_CRYPTO_VU_SET_TO_ONE (base, my_s_z);
1830 
1831     /* EC scalar multiplication (irregular) */
1832     /* Operation. */
1833     CY_CRYPTO_VU_SET_TO_ZERO (base, clr);
1834     CY_CRYPTO_VU_CLSAME (base, t, my_d, clr);
1835 
1836     CY_CRYPTO_VU_LSL (base, my_d, my_d, t); /* Get rid of leading '0's */
1837 
1838     clsame = Cy_Crypto_Core_Vu_RegDataPtrRead (base, t);
1839 
1840     CY_CRYPTO_VU_LSL1 (base, my_d, my_d); /* Get rid of leading '1' */
1841 
1842     /* Binary left-to-right algorithm
1843     * Perform point addition and point doubling to implement scalar multiplication
1844     * Scan the bits of the scalar from left to right; perform point doubling for each bit,
1845     * and perform point addition when the bit is set.
1846     * Carry set if current bit is equal to 1 (hence, perform point addition - point
1847     * doubling is always performed)
1848     */
1849     for (i = 0u; i < (size - clsame - 1u); i++)
1850     {
1851         /* Carry set if current bit is equal to 1 (hence, perform point addition - point
1852         * doubling is always performed)
1853         */
1854         CY_CRYPTO_VU_LSL1 (base, my_d, my_d);
1855         status = Cy_Crypto_Core_Vu_StatusRead(base);
1856 
1857         carry = status & CY_CRYPTO_VU_STATUS_CARRY_BIT;
1858 
1859         Cy_Crypto_Core_JacobianEcDouble (base, my_s_x, my_s_y, my_s_z, size);
1860 
1861         if (carry != 0U)
1862         {
1863             Cy_Crypto_Core_JacobianEcAdd (base, my_s_x, my_s_y, my_s_z, my_t_x, my_t_y, size);
1864         }
1865     }
1866 
1867     /* Inverse transform */
1868     Cy_Crypto_Core_JacobianInvTransform(base, my_s_x, my_s_y, my_s_z, size);
1869 
1870     CY_CRYPTO_VU_FREE_MEM (base, CY_CRYPTO_VU_REG_BIT(my_s_z) |
1871                                  CY_CRYPTO_VU_REG_BIT(my_t_x) | CY_CRYPTO_VU_REG_BIT(my_t_y) |
1872                                  CY_CRYPTO_VU_REG_BIT(clr)    | CY_CRYPTO_VU_REG_BIT(t));
1873 
1874     CY_CRYPTO_VU_POP_REG (base);
1875 }
1876 
1877 /***************************************************************
1878 *                   Test methods
1879 ***************************************************************/
1880 
1881 
1882 /*******************************************************************************
1883 * Function Name: Cy_Crypto_Core_EC_NistP_SetMode
1884 ****************************************************************************//**
1885 *
1886 * Enable some curve specific features.
1887 *
1888 * \param bitsize
1889 * bitsize of the used NIST P curve.
1890 *
1891 *******************************************************************************/
Cy_Crypto_Core_EC_NistP_SetMode(uint32_t bitsize)1892 void Cy_Crypto_Core_EC_NistP_SetMode(uint32_t bitsize)
1893 {
1894     switch (bitsize)
1895     {
1896         case CY_CRYPTO_ECC_P192_SIZE:
1897             eccMode = CY_CRYPTO_ECC_ECP_SECP192R1;
1898             break;
1899         case CY_CRYPTO_ECC_P224_SIZE:
1900             eccMode = CY_CRYPTO_ECC_ECP_SECP224R1;
1901             break;
1902         case CY_CRYPTO_ECC_P256_SIZE:
1903             eccMode = CY_CRYPTO_ECC_ECP_SECP256R1;
1904             break;
1905         case CY_CRYPTO_ECC_P384_SIZE:
1906             eccMode = CY_CRYPTO_ECC_ECP_SECP384R1;
1907             break;
1908         case CY_CRYPTO_ECC_P521_SIZE:
1909             eccMode = CY_CRYPTO_ECC_ECP_SECP521R1;
1910             break;
1911         default:
1912             eccMode = CY_CRYPTO_ECC_ECP_NONE;
1913             break;
1914     }
1915 }
1916 
1917 
1918 /*******************************************************************************
1919 * Function Name: Cy_Crypto_Core_EC_NistP_SetRedAlg
1920 ****************************************************************************//**
1921 *
1922 * Select which reduction algorithm has to be used.
1923 *
1924 * \param alg
1925 * one of {CURVE_SPECIFIC_RED_ALG, SHIFT_MUL_RED_ALG, BARRETT_RED_ALG}.
1926 * See cy_en_crypto_ecc_red_mul_algs_t.
1927 *
1928 *******************************************************************************/
Cy_Crypto_Core_EC_NistP_SetRedAlg(cy_en_crypto_ecc_red_mul_algs_t alg)1929 void Cy_Crypto_Core_EC_NistP_SetRedAlg(cy_en_crypto_ecc_red_mul_algs_t alg)
1930 {
1931     mul_red_alg_select = alg;
1932 }
1933 
1934 
1935 /*******************************************************************************
1936 * Function Name: Cy_Crypto_Core_EC_NistP_PointMul
1937 ****************************************************************************//**
1938 *
1939 * Elliptic curve point multiplication in GF(p).
1940 *
1941 * \param base
1942 * The pointer to a Crypto instance.
1943 *
1944 * \param p_x
1945 * Register index for affine X coordinate of base point.
1946 *
1947 * \param p_y
1948 * Register index for affine Y coordinate of base point.
1949 *
1950 * \param p_d
1951 * Register index for multiplication value.
1952 *
1953 * \param p_order
1954 * Register index for order value..
1955 *
1956 * \param bitsize
1957 * Bit size of the used curve.
1958 *
1959 *******************************************************************************/
Cy_Crypto_Core_EC_NistP_PointMul(CRYPTO_Type * base,uint32_t p_x,uint32_t p_y,uint32_t p_d,uint32_t p_order,uint32_t bitsize)1960 void Cy_Crypto_Core_EC_NistP_PointMul(CRYPTO_Type *base, uint32_t p_x, uint32_t p_y, uint32_t p_d, uint32_t p_order, uint32_t bitsize)
1961 {
1962     (void)p_order; /* Suppress warning */
1963     Cy_Crypto_Core_JacobianEcScalarMul (base, p_x, p_y, p_d, bitsize);
1964     Cy_Crypto_Core_Vu_WaitForComplete(base);
1965 }
1966 
1967 
1968 /*******************************************************************************
1969 * Function Name: Cy_Crypto_Core_EC_NistP_PointMultiplication
1970 ****************************************************************************//**
1971 *
1972 * Elliptic curve point multiplication in GF(p).
1973 *
1974 * \param base
1975 * The pointer to a Crypto instance.
1976 *
1977 * \param curveID
1978 * See \ref cy_en_crypto_ecc_curve_id_t.
1979 *
1980 * \param ecpGX
1981 * Register index for affine X coordinate of base point.
1982 *
1983 * \param ecpGY
1984 * Register index for affine Y coordinate of base point.
1985 *
1986 * \param ecpD
1987 * Register index for multiplication value.
1988 *
1989 * \param ecpQX
1990 * Register index for affine X coordinate of result point.
1991 *
1992 * \param ecpQY
1993 * Register index for affine Y coordinate of result point.
1994 *
1995 * \return status code. See \ref cy_en_crypto_status_t.
1996 *
1997 *******************************************************************************/
Cy_Crypto_Core_EC_NistP_PointMultiplication(CRYPTO_Type * base,cy_en_crypto_ecc_curve_id_t curveID,const uint8_t * ecpGX,const uint8_t * ecpGY,const uint8_t * ecpD,uint8_t * ecpQX,uint8_t * ecpQY)1998 cy_en_crypto_status_t Cy_Crypto_Core_EC_NistP_PointMultiplication(CRYPTO_Type *base,
1999     cy_en_crypto_ecc_curve_id_t curveID,
2000     const uint8_t *ecpGX,
2001     const uint8_t *ecpGY,
2002     const uint8_t *ecpD,
2003     uint8_t *ecpQX,
2004     uint8_t *ecpQY)
2005 {
2006     /* N.b. If using test vectors from "http://point-at-infinity.org/ecc/nisttv",
2007      * the 'k' values on the website are in decimal form, while the (x,y) result
2008      * coordinates are in hexadecimal form
2009      * Input format for 'd' scalar multiplier in this test is in hexadecimal form.
2010      * Hence, convert k_{dec} to d_{hex} for comparison of test values
2011      */
2012 
2013     /* Setup additional registers */
2014     uint32_t VR_ORDER = 9u;
2015 
2016     const uint8_t *p_polynomial = NULL;
2017     const uint8_t *p_barrett = NULL;
2018 
2019     cy_stc_crypto_ecc_dp_type *eccDp = Cy_Crypto_Core_ECC_GetCurveParams(curveID);
2020 
2021     cy_en_crypto_status_t myStatus = CY_CRYPTO_NOT_SUPPORTED;
2022 
2023     if (eccDp != NULL)
2024     {
2025         /* Setup curve specific parameters depending on mode */
2026         uint32_t bitsize;
2027 
2028         p_polynomial = eccDp->prime;
2029         p_barrett    = eccDp->barrett_p;
2030         bitsize      = eccDp->size;
2031 
2032         /* use Barrett reduction algorithm for operations modulo n (order of the base point) */
2033         Cy_Crypto_Core_EC_NistP_SetRedAlg(eccDp->algo);
2034         Cy_Crypto_Core_EC_NistP_SetMode(eccDp->size);
2035 
2036         myStatus = CY_CRYPTO_BAD_PARAMS;
2037 
2038         if ((NULL != ecpGX) && (NULL != ecpGY) && (NULL != ecpD) && (NULL != ecpQX) && (NULL != ecpQY))
2039         {
2040             /* Public parameters and characteristics of elliptic curve */
2041             CY_CRYPTO_VU_ALLOC_MEM (base, VR_D, bitsize);        /* Scalar factor */
2042             CY_CRYPTO_VU_ALLOC_MEM (base, VR_S_X, bitsize);
2043             CY_CRYPTO_VU_ALLOC_MEM (base, VR_S_Y, bitsize);
2044             CY_CRYPTO_VU_ALLOC_MEM (base, VR_P, bitsize);
2045             CY_CRYPTO_VU_ALLOC_MEM (base, VR_BARRETT, bitsize + 1u);
2046             CY_CRYPTO_VU_ALLOC_MEM (base, VR_ORDER, bitsize);
2047 
2048             Cy_Crypto_Core_Vu_SetMemValue (base, VR_P, p_polynomial, bitsize);
2049 
2050             /* Preparation (either use precalculated or calculated). */
2051             Cy_Crypto_Core_Vu_SetMemValue (base, VR_BARRETT, p_barrett, bitsize + 1u);
2052 
2053             Cy_Crypto_Core_Vu_SetMemValue (base, VR_S_X, ecpGX, bitsize);
2054             Cy_Crypto_Core_Vu_SetMemValue (base, VR_S_Y, ecpGY, bitsize);
2055             Cy_Crypto_Core_Vu_SetMemValue (base, VR_D, ecpD, bitsize);
2056 
2057             /* ECC calculation: d * G mod p */
2058             Cy_Crypto_Core_EC_NistP_PointMul(base, VR_S_X, VR_S_Y, VR_D, VR_ORDER, bitsize);
2059 
2060             /* Get result P = (X,Y) = d.G from EC scalar multiplication */
2061             Cy_Crypto_Core_Vu_GetMemValue (base, ecpQX, VR_S_X, bitsize);
2062             Cy_Crypto_Core_Vu_GetMemValue (base, ecpQY, VR_S_Y, bitsize);
2063 
2064             /* Free memory */
2065             CY_CRYPTO_VU_FREE_MEM (base,
2066                                     CY_CRYPTO_VU_REG_BIT(VR_ORDER) |
2067                                     CY_CRYPTO_VU_REG_BIT(VR_BARRETT) |
2068                                     CY_CRYPTO_VU_REG_BIT(VR_P) |
2069                                     CY_CRYPTO_VU_REG_BIT(VR_S_Y) |
2070                                     CY_CRYPTO_VU_REG_BIT(VR_S_X) |
2071                                     CY_CRYPTO_VU_REG_BIT(VR_D));
2072 
2073             myStatus = CY_CRYPTO_SUCCESS;
2074         }
2075     }
2076 
2077     return myStatus;
2078 }
2079 
2080 #if defined(__cplusplus)
2081 }
2082 #endif
2083 
2084 #endif /* CY_IP_MXCRYPTO */
2085 
2086 
2087 /* [] END OF FILE */
2088