1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7
8
9 #include "cc_pal_types.h"
10 #include "cc_pal_mem.h"
11 #include "cc_common_math.h"
12 #include "cc_ecpki_types.h"
13 #include "pka.h"
14 #include "ec_wrst.h"
15 #include "pki.h"
16 #include "pki_modular_arithmetic.h"
17
18 #include "pki_dbg.h"
19 /* virt. pointers to pka regs. (regs. ID-s)*/
20 #include "pka_point_compress_regs_def.h"
21
22
23
24 /*********** PkiCalcJacobiSymbol function **********************/
25 /**
26 * @brief Calculate Jacobi symbol for a and prime b numbers.
27 * Assumed: a, b are a positive numbers.
28 * Note: PKA_REG_A, PKA_REG_B registers are destroed by the function.
29 *
30 * @author reuvenl (10/26/2014)
31 *
32 * @return int32_t jacobi symbol value.
33 */
PkiCalcJacobiSymbol(void)34 int32_t PkiCalcJacobiSymbol(void)
35 {
36 int32_t r, t;
37 uint32_t stat, w, w1;
38
39
40 /* Note: Check GCD - not need because b - prime.
41 Convert a to positive numbers - not need */
42
43 /* case PKA_REG_A = 0 or PKA_REG_A = 1 */
44 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_A, 0, stat); /*if(a==0) r = 0*/
45 if(stat == 1) {
46 r = 0;
47 goto End;
48 }
49
50 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_A, 1, stat); /*if(a==0) r = 0*/
51 if(stat == 1) {
52 r = 1;
53 goto End;
54 }
55
56 r = 1;
57
58 /* Evaluate Jacobi symb. */
59 do {
60 /* 1. Remove 0-LS bits of PKA_REG_A */
61 t = 0;
62 w = 0;
63
64 while(w == 0) {/* remove 0- words */
65 PKA_READ_WORD_FROM_REG(w, 0, PKA_REG_A);
66 if(w == 0) {
67 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_A, PKA_REG_A, 32-1);
68 t += 32;
69 }
70 }
71
72 while((w & 1) == 0){
73 w >>= 1;
74 t += 1;
75 }
76 if((t & 0x1F) != 0) {/* removes 0-bits */
77 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_A, PKA_REG_A, (t & 0x1F) - 1);
78 }
79
80 /* 2. Change sign if b mod 8 == 3 or 5 */
81 PKA_READ_WORD_FROM_REG(w1, 0, PKA_REG_B);
82
83 if(t & 1) {
84 if((w1 & 7) == 3 || (w1 & 7) == 5)
85 r = -r;
86 }
87
88 /* 3. Quadratic reciprocity law */
89 if((w & 3) == 3 && (w1 & 3) == 3){
90 r = -r;
91 }
92
93 PKA_COPY(LEN_ID_N_PKA_REG_BITS, PKA_REG_C, PKA_REG_A);
94 PKA_COPY(LEN_ID_N_PKA_REG_BITS, PKA_REG_A, PKA_REG_B);
95 PKA_DIV(LEN_ID_N_PKA_REG_BITS, PKA_REG_B, PKA_REG_A, PKA_REG_C); /* a = b mod a */
96 PKA_COPY(LEN_ID_N_PKA_REG_BITS, PKA_REG_B, PKA_REG_C); /* b = a prev. */
97
98 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_A, 0, stat);
99
100 } while(stat != 1); /*while a != 0*/
101 End:
102
103 return r;
104
105 } /* End of PkiCalcJacobiSymbol*/
106
107
108 /*********** PkiIsModSquareRootExists function **********************/
109 /**
110 * @brief The function calculates square root modulo prime:
111 * PKA_REG_Y1 = PKA_REG_Y2 ^ 1/2 mod rP if root exists, else returns an error.
112 *
113 * Assuming: 1. The modulus N is a prime.
114 * 2. Y2 is less than modulus.
115 *
116 * @return true if the root exists, or false if not.
117 */
PkiIsModSquareRootExists(void)118 bool PkiIsModSquareRootExists(void)
119 {
120 uint32_t w=0, stat;
121 int32_t s, i;
122 bool rootEx = false;
123 int32_t jcb;
124
125
126 /* if Y^2 = 0, return Y=0 */
127 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y2, 0, stat);
128 if(stat == 1){
129 PKA_CLEAR(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y1); /* Y1=0*/
130 rootEx = true;
131 goto End;
132 }
133
134 /* read w = mod[0]*/
135 PKA_READ_WORD_FROM_REG(w, 0/*i*/, PKA_REG_N);
136
137 /* ----------------------------------------- */
138 /* Case P=3 mod 4, then PKA_REG_Y1 = +- PKA_REG_Y2^(P+1)/4 */
139 /* ----------------------------------------- */
140 if((w & 0x3) == 3) {
141 PKA_ADD_IM(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y1, PKA_REG_N, 1);
142 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_T, PKA_REG_Y1, 2-1);
143 PKA_MOD_EXP(LEN_ID_N_BITS, PKA_REG_Y1, PKA_REG_Y2, PKA_REG_T);
144 goto End;
145 }
146
147 /* ------------------------------------------------ */
148 /* Case P=5 mod 8, then PKA_REG_Y1 calculated by algorithm */
149 /* ------------------------------------------------ */
150 if((w & 0x7) == 5) {
151 PKA_SUB_IM(LEN_ID_N_PKA_REG_BITS, PKA_REG_YT, PKA_REG_N, 1); /* PKA_REG_YT = PKA_REG_N-1*/
152 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_Z, PKA_REG_YT, 2-1);
153 PKA_MOD_EXP(LEN_ID_N_BITS, PKA_REG_T, PKA_REG_Y2, PKA_REG_Z); /* d = PKA_REG_T = PKA_REG_Y2^((PKA_REG_N-1)/4)*/
154 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_T, 1, stat);
155 if(stat == 1) {
156 PKA_ADD_IM(LEN_ID_N_PKA_REG_BITS, PKA_REG_T, PKA_REG_N, 3);
157 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_T, PKA_REG_T, 3-1);
158 PKA_MOD_EXP(LEN_ID_N_BITS, PKA_REG_Y1, PKA_REG_Y2, PKA_REG_T);
159 }
160 else {
161 PKA_COMPARE_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_T, PKA_REG_YT, stat); /* PKA_REG_T =? PKA_REG_N-1*/
162 if(stat == 1) {
163 PKA_SUB_IM(LEN_ID_N_PKA_REG_BITS, PKA_REG_T, PKA_REG_N, 5);
164 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_T, PKA_REG_T, 3-1);
165 PKA_SHL_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_YT, PKA_REG_Y2, 2-1); /* PKA_REG_YT = 4*PKA_REG_Y2 */
166 PKA_MOD_EXP(LEN_ID_N_BITS, PKA_REG_Z, PKA_REG_YT, PKA_REG_T);
167 PKA_SHL_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_YT, PKA_REG_Y2, 1-1); /* PKA_REG_YT = 2*PKA_REG_Y2 */
168 PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_Y1, PKA_REG_Z, PKA_REG_YT); /* PKA_REG_Y1 = 2*PKA_REG_Y2*(4rY2)^((PKA_REG_N-5)/8) */
169 }
170 }
171
172 goto End;
173 }
174
175
176 /* --------------------------------- */
177 /* Case of other modulus structure */
178 /* --------------------------------- */
179
180 /* check if root exist using jacoby symbol */
181 PKA_COPY(LEN_ID_N_PKA_REG_BITS, PKA_REG_A, PKA_REG_Y2);
182 PKA_COPY(LEN_ID_N_PKA_REG_BITS, PKA_REG_B, PKA_REG_N);
183 jcb = PkiCalcJacobiSymbol(/*, PKA_REG_A, PKA_REG_B*/);
184 if(jcb == -1)
185 goto End;
186
187 /* state P-1 as Q * 2^s, where Q is odd */
188 PKA_SUB_IM(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y1, PKA_REG_N, 1); /**/
189 w -= 1;
190 s = 0;
191 while(w == 0) { /*remove 0-words*/
192 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y1, PKA_REG_Y1, 32-1);
193 s += 32;
194 PKA_READ_WORD_FROM_REG(w, 0/*i*/, PKA_REG_Y1);
195 }
196 /* remove 0-bits */
197 i = 0;
198 while((w & 1) == 0){
199 w >>= 1;
200 i++;
201 }
202 s += i;
203 if(i > 0)
204 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y1, PKA_REG_Y1, i-1);
205
206 /* find first non residue number (modulo N) starting from 2 */
207 jcb = 0;
208 PKA_CLEAR(LEN_ID_N_PKA_REG_BITS, PKA_REG_Z);
209 PKA_SET_BIT0(LEN_ID_N_PKA_REG_BITS, PKA_REG_Z, PKA_REG_Z); /* z = 1*/
210 while (jcb != -1) {
211 PKA_ADD_IM(LEN_ID_N_PKA_REG_BITS, PKA_REG_Z, PKA_REG_Z, 1);
212
213 /*set jacoby input values */
214 PKA_COPY(LEN_ID_N_PKA_REG_BITS, PKA_REG_A, PKA_REG_Z);
215 PKA_COPY(LEN_ID_N_PKA_REG_BITS, PKA_REG_B, PKA_REG_N);
216 jcb = PkiCalcJacobiSymbol(/*, PKA_REG_A, PKA_REG_B*/);
217 }
218
219 PKA_MOD_EXP(LEN_ID_N_BITS, PKA_REG_Z, PKA_REG_Z, PKA_REG_Y1); /* */
220 PKA_ADD_IM(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y1, PKA_REG_Y1, 1);
221 PKA_SHR_FILL0(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y1, PKA_REG_Y1, 1-1); /* PKA_REG_Y1 = (PKA_REG_Y1+1)/2 */
222 PKA_MOD_EXP(LEN_ID_N_BITS, PKA_REG_Y1, PKA_REG_Y2, PKA_REG_Y1); /* PKA_REG_Y1 = PKA_REG_Y2^PKA_REG_Y1 */
223 PKA_COPY(LEN_ID_N_PKA_REG_BITS, PKA_REG_YT, PKA_REG_Y2);
224 PKA_MOD_INV(LEN_ID_N_BITS, PKA_REG_T, PKA_REG_YT);
225 for(;;) {
226 PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_YT, PKA_REG_Y1, PKA_REG_Y1); /* PKA_REG_YT = PKA_REG_Y1^2 */
227 PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_YT, PKA_REG_YT, PKA_REG_T); /* PKA_REG_YT = PKA_REG_YT * PKA_REG_Y2^-1 */
228 i = 0;
229 while(1) {
230 /*if(PKA_REG_YT == 1) break;*/
231 PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_YT, 1, stat);
232 if(stat == 1)
233 break;
234 i++;
235 PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_YT,PKA_REG_YT, PKA_REG_YT); /* PKA_REG_YT = PKA_REG_YT^2 */
236 }
237 /* if PKA_REG_Y1^2 * PKA_REG_Y2^-1 == 1 (mod rP), return */
238 if(i == 0) {
239 rootEx = true;
240 goto End;
241 }
242 if(s-i == 1) { /* mul instead pow */
243 PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_Y1, PKA_REG_Y1, PKA_REG_Z);
244 } else {
245 w = 1 << ((s-i-1) & 31);
246 i = (s-i-1) / 32; /*i was free*/
247 PKA_CLEAR(LEN_ID_N_PKA_REG_BITS, PKA_REG_EX);
248 PKA_WRITE_WORD_TO_REG(w, i, PKA_REG_EX);
249 PKA_MOD_EXP(LEN_ID_N_BITS, PKA_REG_YT, PKA_REG_Z, PKA_REG_EX);
250 PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_Y1, PKA_REG_Y1, PKA_REG_YT); /* PKA_REG_Y1 = r * PKA_REG_Z^(2^(s-i-1)) */
251 }
252 }
253 End:
254 /* Check result for PKA_REG_N mod 8 = {3,5} */
255 if((w & 3) == 3 || (w & 7) == 5){
256 PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_T, PKA_REG_Y1, PKA_REG_Y1);
257 PKA_COMPARE_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_T, PKA_REG_Y2, stat);
258 if(stat == 1)
259 rootEx = true;
260 }
261
262 return rootEx;
263 }
264
265