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