1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Crypto Component */
16 /** */
17 /** Huge Number */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_CRYPTO_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26 #include "stdio.h"
27 #include "nx_crypto_huge_number.h"
28
29 #ifndef NX_CRYPTO_SELF_TEST
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _nx_crypto_huge_number_add_digit PORTABLE C */
35 /* 6.1.7 */
36 /* AUTHOR */
37 /* */
38 /* Timothy Stapko, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* This function calculates addition for huge number and digit. */
43 /* */
44 /* Note: Result is stored in value. */
45 /* */
46 /* INPUT */
47 /* */
48 /* value Huge number number */
49 /* digit Digit value */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* None */
54 /* */
55 /* CALLS */
56 /* */
57 /* _nx_crypto_huge_number_add_digit_unsigned */
58 /* Calculate addition for */
59 /* unsigned huge numbers */
60 /* _nx_crypto_huge_number_subtract_digit_unsigned */
61 /* Calculate subtraction for */
62 /* unsigned huge numbers */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* Application Code */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
73 /* 09-30-2020 Timothy Stapko Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* 06-02-2021 Bhupendra Naphade Modified comment(s), */
76 /* renamed FIPS symbol to */
77 /* self-test, */
78 /* resulting in version 6.1.7 */
79 /* */
80 /**************************************************************************/
_nx_crypto_huge_number_add_digit(NX_CRYPTO_HUGE_NUMBER * value,HN_UBASE digit)81 NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_add_digit(NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE digit)
82 {
83 if (value -> nx_crypto_huge_number_is_negative)
84 {
85 if ((value -> nx_crypto_huge_number_size > 1) ||
86 (value -> nx_crypto_huge_number_data[0] >= digit))
87 {
88
89 /* |value| >= digit */
90 /* value = -(|value| - digit) */
91 _nx_crypto_huge_number_subtract_digit_unsigned(value, digit);
92 }
93 else
94 {
95
96 /* value < digit */
97 /* value = digit - |value| */
98 value -> nx_crypto_huge_number_data[0] = digit - value -> nx_crypto_huge_number_data[0];
99 value -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE;
100 }
101 }
102 else
103 {
104
105 /* value = value + digit */
106 _nx_crypto_huge_number_add_digit_unsigned(value, digit);
107 }
108 }
109
110 /**************************************************************************/
111 /* */
112 /* FUNCTION RELEASE */
113 /* */
114 /* _nx_crypto_huge_number_subtract_digit PORTABLE C */
115 /* 6.1 */
116 /* AUTHOR */
117 /* */
118 /* Timothy Stapko, Microsoft Corporation */
119 /* */
120 /* DESCRIPTION */
121 /* */
122 /* This function calculates subtraction for huge number and digit. */
123 /* */
124 /* Note: Result is stored in value. */
125 /* */
126 /* INPUT */
127 /* */
128 /* value Huge number number */
129 /* digit Digit value */
130 /* */
131 /* OUTPUT */
132 /* */
133 /* None */
134 /* */
135 /* CALLS */
136 /* */
137 /* _nx_crypto_huge_number_add_digit_unsigned */
138 /* Calculate addition for */
139 /* unsigned huge numbers */
140 /* _nx_crypto_huge_number_subtract_digit_unsigned */
141 /* Calculate subtraction for */
142 /* unsigned huge numbers */
143 /* */
144 /* CALLED BY */
145 /* */
146 /* Application Code */
147 /* */
148 /* RELEASE HISTORY */
149 /* */
150 /* DATE NAME DESCRIPTION */
151 /* */
152 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
153 /* 09-30-2020 Timothy Stapko Modified comment(s), */
154 /* resulting in version 6.1 */
155 /* */
156 /**************************************************************************/
_nx_crypto_huge_number_subtract_digit(NX_CRYPTO_HUGE_NUMBER * value,HN_UBASE digit)157 NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_subtract_digit(NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE digit)
158 {
159 if (value -> nx_crypto_huge_number_is_negative)
160 {
161
162 /* value = -(|value| + digit) */
163 _nx_crypto_huge_number_add_digit_unsigned(value, digit);
164 }
165 else
166 {
167 if ((value -> nx_crypto_huge_number_size > 1) ||
168 (value -> nx_crypto_huge_number_data[0] >= digit))
169 {
170
171 /* value >= digit */
172 /* value = value - digit */
173 _nx_crypto_huge_number_subtract_digit_unsigned(value, digit);
174 }
175 else
176 {
177
178 /* value < digit */
179 /* value = -(digit - value) */
180 value -> nx_crypto_huge_number_data[0] = digit - value -> nx_crypto_huge_number_data[0];
181 value -> nx_crypto_huge_number_is_negative = NX_CRYPTO_TRUE;
182 }
183 }
184 }
185
186 /**************************************************************************/
187 /* */
188 /* FUNCTION RELEASE */
189 /* */
190 /* _nx_crypto_huge_number_power_modulus PORTABLE C */
191 /* 6.1.9 */
192 /* AUTHOR */
193 /* */
194 /* Timothy Stapko, Microsoft Corporation */
195 /* */
196 /* DESCRIPTION */
197 /* */
198 /* This function raises a huge number to the power of a second huge */
199 /* number using a third huge number as a modulus. The result is placed */
200 /* in a fourth huge number. */
201 /* */
202 /* NOTE: This function makes use of the Huge Number scratch buffers. */
203 /* Each operand and the result must have the */
204 /* nx_crypto_huge_number_scratch member set to point to a buffer */
205 /* of size equal to the number data buffer and that size stored */
206 /* in the nx_crypto_huge_buffer_size member. */
207 /* */
208 /* INPUT */
209 /* */
210 /* number Number being exponentiated */
211 /* exponent Exponent number */
212 /* modulus Modulus number */
213 /* result Result buffer */
214 /* */
215 /* OUTPUT */
216 /* */
217 /* None */
218 /* */
219 /* CALLS */
220 /* */
221 /* NX_CRYPTO_HUGE_NUMBER_COPY Copy huge number */
222 /* NX_CRYPTO_HUGE_NUMBER_INITIALIZE Initialize the buffer of */
223 /* huge number */
224 /* NX_CRYPTO_HUGE_NUMBER_SET_DIGIT Set value of huge number */
225 /* between 0 and (HN_RADIX - 1)*/
226 /* _nx_crypto_huge_number_multiply Multiply a huge number by */
227 /* a second huge number */
228 /* _nx_crypto_huge_number_modulus Calculate the remainder after */
229 /* dividing a huge number by */
230 /* another huge number */
231 /* _nx_crypto_huge_number_square Compute the square of a value */
232 /* */
233 /* CALLED BY */
234 /* */
235 /* Application Code */
236 /* */
237 /* RELEASE HISTORY */
238 /* */
239 /* DATE NAME DESCRIPTION */
240 /* */
241 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
242 /* 09-30-2020 Timothy Stapko Modified comment(s), */
243 /* resulting in version 6.1 */
244 /* 10-15-2021 Bhupendra Naphade Modified comment(s), */
245 /* resulting in version 6.1.9 */
246 /* */
247 /**************************************************************************/
_nx_crypto_huge_number_power_modulus(NX_CRYPTO_HUGE_NUMBER * number,NX_CRYPTO_HUGE_NUMBER * exponent,NX_CRYPTO_HUGE_NUMBER * modulus,NX_CRYPTO_HUGE_NUMBER * result,HN_UBASE * scratch)248 NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_power_modulus(NX_CRYPTO_HUGE_NUMBER *number,
249 NX_CRYPTO_HUGE_NUMBER *exponent,
250 NX_CRYPTO_HUGE_NUMBER *modulus,
251 NX_CRYPTO_HUGE_NUMBER *result,
252 HN_UBASE *scratch)
253 {
254 UINT index, bit;
255 HN_UBASE cur_block;
256 HN_UBASE *val;
257 UINT exp_size;
258 NX_CRYPTO_HUGE_NUMBER temp;
259
260 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&temp, scratch,
261 number -> nx_crypto_huge_buffer_size);
262
263 /* Clear out the result since we need it to start with a simple value. */
264 NX_CRYPTO_HUGE_NUMBER_SET_DIGIT(result, 1);
265
266 exp_size = exponent -> nx_crypto_huge_number_size;
267 val = exponent -> nx_crypto_huge_number_data;
268 /* Loop through the bits of the exponent. For each bit set, multiply the result by the running square. */
269 for (index = 0; index < exp_size; index++)
270 {
271 /* Current byte in the exponent determines whether we multiply or not. */
272 cur_block = val[index];
273
274 /* Loop over the bits in the current byte to see whether we add or not. */
275 for (bit = 0; bit < HN_SHIFT; ++bit)
276 {
277 /* A non-zero bit means we need to multiply. */
278 if (cur_block & 1)
279 {
280 /* Multiply the result by the running square (number) and put the result in a scratch buffer. */
281 _nx_crypto_huge_number_multiply(result, number, &temp);
282 NX_CRYPTO_HUGE_NUMBER_COPY(result, &temp);
283
284 /* Take the modulus of the product we just calculated. If we didn't do this here the result would quickly grow
285 larger than our buffers (or the universe) could store. Put the result in our result buffer. */
286 _nx_crypto_huge_number_modulus(result, modulus);
287 }
288
289 /* Shift the data to go to the next bit. */
290 cur_block = cur_block >> 1;
291
292 _nx_crypto_huge_number_square(number, &temp);
293 _nx_crypto_huge_number_modulus(&temp, modulus);
294 NX_CRYPTO_HUGE_NUMBER_COPY(number, &temp);
295
296 /* Take the modulus of our squared product and put the result into our number buffer. */
297 }
298 }
299 }
300
301 #endif
302