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