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 
24 /**************************************************************************/
25 /*                                                                        */
26 /*  APPLICATION INTERFACE DEFINITION                       RELEASE        */
27 /*                                                                        */
28 /*    nx_crypto_huge_number.h                             PORTABLE C      */
29 /*                                                           6.1.8        */
30 /*  AUTHOR                                                                */
31 /*                                                                        */
32 /*    Timothy Stapko, Microsoft Corporation                               */
33 /*                                                                        */
34 /*  DESCRIPTION                                                           */
35 /*                                                                        */
36 /*    This file defines the basic Application Interface (API) to the      */
37 /*    NetX Crypto huge number module.                                     */
38 /*                                                                        */
39 /*  RELEASE HISTORY                                                       */
40 /*                                                                        */
41 /*    DATE              NAME                      DESCRIPTION             */
42 /*                                                                        */
43 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
44 /*  09-30-2020     Timothy Stapko           Modified comment(s), and      */
45 /*                                            fixed number initialization,*/
46 /*                                            resulting in version 6.1    */
47 /*  08-02-2021     Timothy Stapko           Modified comment(s), and      */
48 /*                                            used ULONG64_DEFINED macro, */
49 /*                                            resulting in version 6.1.8  */
50 /*                                                                        */
51 /**************************************************************************/
52 
53 #ifndef NX_CRYPTO_HUGE_NUMBER_H
54 #define NX_CRYPTO_HUGE_NUMBER_H
55 
56 /* Determine if a C++ compiler is being used.  If so, ensure that standard
57    C is used to process the API information.  */
58 #ifdef __cplusplus
59 
60 /* Yes, C++ compiler is present.  Use standard C.  */
61 extern   "C" {
62 
63 #endif
64 
65 /* Include the ThreadX and port-specific data type file.  */
66 
67 #include "nx_crypto.h"
68 
69 /* Return values for _nx_crypto_huge_number_compare */
70 #define NX_CRYPTO_HUGE_NUMBER_EQUAL   (0x0)
71 #define NX_CRYPTO_HUGE_NUMBER_LESS    (0x1)
72 #define NX_CRYPTO_HUGE_NUMBER_GREATER (0x2)
73 #define NX_CRYPTO_HUGE_NUMBER_ERROR   (0x3)
74 
75 
76 /* Define the base exponent of 2 for huge number.
77  * Only 16 and 32 are supported. */
78 #ifndef NX_CRYPTO_HUGE_NUMBER_BITS
79 #define NX_CRYPTO_HUGE_NUMBER_BITS    32
80 #endif /* NX_CRYPTO_HUGE_NUMBER_BITS */
81 
82 #if (NX_CRYPTO_HUGE_NUMBER_BITS == 32)
83 #ifndef ULONG64_DEFINED
84 #define ULONG64_DEFINED
85 #define ULONG64                       unsigned long long
86 #define LONG64                        long long
87 #endif
88 #define HN_BASE                       LONG
89 #define HN_BASE2                      LONG64
90 #define HN_UBASE                      ULONG
91 #define HN_UBASE2                     ULONG64
92 #define HN_MASK                       0xFFFFFFFF
93 #define HN_RADIX                      0x100000000
94 #define HN_SHIFT                      (sizeof(HN_BASE) << 3)
95 #define HN_SIZE_ROUND                 (sizeof(HN_BASE) - 1)
96 #define HN_SIZE_SHIFT                 2
97 #define HN_ULONG_TO_UBASE(v)          v
98 #elif (NX_CRYPTO_HUGE_NUMBER_BITS == 16)
99 #define HN_BASE                       SHORT
100 #define HN_BASE2                      LONG
101 #define HN_UBASE                      USHORT
102 #define HN_UBASE2                     ULONG
103 #define HN_MASK                       0xFFFF
104 #define HN_RADIX                      0x10000
105 #define HN_SHIFT                      (sizeof(HN_BASE) << 3)
106 #define HN_SIZE_ROUND                 (sizeof(HN_BASE) - 1)
107 #define HN_SIZE_SHIFT                 1
108 #define HN_ULONG_TO_UBASE(v)          (v) & HN_MASK, (v) >> HN_SHIFT
109 #else
110 #error "NX_CRYPTO_HUGE_NUMBER_BITS supports 16 and 32 only!"
111 #endif
112 
113 
114 /* Huge number structure - contains data pointer and size. */
115 typedef struct NX_CRYPTO_HUGE_NUMBER_STRUCT
116 {
117     /* Stores a pointer to the number data which may be of arbitrary size. */
118     HN_UBASE *nx_crypto_huge_number_data;
119 
120     /* The size of the data stored in the buffer, in number of digit. */
121     UINT nx_crypto_huge_number_size;
122 
123     /* The size of the buffer itself, in number of bytes. */
124     UINT nx_crypto_huge_buffer_size;
125 
126     /* Flag to indicate positive or negative value. */
127     UINT nx_crypto_huge_number_is_negative;
128 } NX_CRYPTO_HUGE_NUMBER;
129 
130 
131 /* Misc macros for huge number. */
132 
133 /* Initialize the buffer of huge number. */
134 #define NX_CRYPTO_HUGE_NUMBER_INITIALIZE(hn, buff, size)     \
135     (hn) -> nx_crypto_huge_number_data = (HN_UBASE *)(buff); \
136     (hn) -> nx_crypto_huge_number_size = 0;                  \
137     (hn) -> nx_crypto_huge_buffer_size = (((size) + HN_SIZE_ROUND) >> HN_SIZE_SHIFT) << HN_SIZE_SHIFT;\
138     (hn) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE;    \
139     (buff) = (buff) + (((size) + HN_SIZE_ROUND) >> HN_SIZE_SHIFT);
140 
141 /* Is it an even huge number? */
142 #define NX_CRYPTO_HUGE_NUMBER_IS_EVEN(hn) \
143     !((hn) -> nx_crypto_huge_number_data[0] & 1)
144 
145 /* Set value of huge number between 0 and (HN_RADIX - 1). */
146 #define NX_CRYPTO_HUGE_NUMBER_SET_DIGIT(hn, val)          \
147     (hn) -> nx_crypto_huge_number_data[0] = (val);        \
148     (hn) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; \
149     (hn) -> nx_crypto_huge_number_size = 1;
150 
151 /* Initialize the buffer of huge number to variable between 0 and (HN_RADIX - 1). */
152 #define NX_CRYPTO_HUGE_NUMBER_INITIALIZE_DIGIT(hn, buff, val) \
153     (hn) -> nx_crypto_huge_number_data = (HN_UBASE *)(buff);  \
154     (hn) -> nx_crypto_huge_buffer_size = sizeof(HN_UBASE);        \
155     NX_CRYPTO_HUGE_NUMBER_SET_DIGIT(hn, val)
156 
157 /* Copy huge number from src to dst. */
158 #define NX_CRYPTO_HUGE_NUMBER_COPY(dst, src)                                                 \
159     (dst) -> nx_crypto_huge_number_size = (src) -> nx_crypto_huge_number_size;               \
160     (dst) -> nx_crypto_huge_number_is_negative = (src) -> nx_crypto_huge_number_is_negative; \
161     NX_CRYPTO_MEMCPY((dst) -> nx_crypto_huge_number_data,                                              \
162            (src) -> nx_crypto_huge_number_data,                                              \
163            (src) -> nx_crypto_huge_number_size << HN_SIZE_SHIFT);
164 
165 
166 /* Function prototypes */
167 
168 VOID _nx_crypto_huge_number_adjust_size(NX_CRYPTO_HUGE_NUMBER *val);
169 UINT _nx_crypto_huge_number_setup(NX_CRYPTO_HUGE_NUMBER *number, const UCHAR *byte_stream, UINT size);
170 UINT _nx_crypto_huge_number_extract(NX_CRYPTO_HUGE_NUMBER *number, UCHAR *byte_stream,
171                                     UINT byte_stream_size, UINT *huge_number_size);
172 UINT _nx_crypto_huge_number_extract_fixed_size(NX_CRYPTO_HUGE_NUMBER *number,
173                                                UCHAR *byte_stream, UINT byte_stream_size);
174 UINT _nx_crypto_huge_number_rbg(UINT bits, UCHAR *result);
175 UINT _nx_crypto_huge_number_compare(NX_CRYPTO_HUGE_NUMBER *left, NX_CRYPTO_HUGE_NUMBER *right);
176 UINT _nx_crypto_huge_number_compare_unsigned(NX_CRYPTO_HUGE_NUMBER *left,
177                                              NX_CRYPTO_HUGE_NUMBER *right);
178 UINT _nx_crypto_huge_number_is_zero(NX_CRYPTO_HUGE_NUMBER *x);
179 VOID _nx_crypto_huge_number_add(NX_CRYPTO_HUGE_NUMBER *left, NX_CRYPTO_HUGE_NUMBER *right);
180 VOID _nx_crypto_huge_number_add_unsigned(NX_CRYPTO_HUGE_NUMBER *left, NX_CRYPTO_HUGE_NUMBER *right);
181 VOID _nx_crypto_huge_number_subtract(NX_CRYPTO_HUGE_NUMBER *left, NX_CRYPTO_HUGE_NUMBER *right);
182 VOID _nx_crypto_huge_number_subtract_unsigned(NX_CRYPTO_HUGE_NUMBER *left,
183                                               NX_CRYPTO_HUGE_NUMBER *right,
184                                               NX_CRYPTO_HUGE_NUMBER *result);
185 VOID _nx_crypto_huge_number_add_digit(NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE digit);
186 VOID _nx_crypto_huge_number_subtract_digit(NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE digit);
187 VOID _nx_crypto_huge_number_add_digit_unsigned(NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE digit);
188 VOID _nx_crypto_huge_number_subtract_digit_unsigned(NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE digit);
189 VOID _nx_crypto_huge_number_multiply(NX_CRYPTO_HUGE_NUMBER *left,
190                                      NX_CRYPTO_HUGE_NUMBER *right,
191                                      NX_CRYPTO_HUGE_NUMBER *result);
192 VOID _nx_crypto_huge_number_multiply_digit(NX_CRYPTO_HUGE_NUMBER *value,
193                                            HN_UBASE digit,
194                                            NX_CRYPTO_HUGE_NUMBER *result);
195 VOID _nx_crypto_huge_number_square(NX_CRYPTO_HUGE_NUMBER *value, NX_CRYPTO_HUGE_NUMBER *result);
196 VOID _nx_crypto_huge_number_modulus(NX_CRYPTO_HUGE_NUMBER *dividend, NX_CRYPTO_HUGE_NUMBER *divisor);
197 VOID _nx_crypto_huge_number_shift_left(NX_CRYPTO_HUGE_NUMBER *x, UINT shift);
198 VOID _nx_crypto_huge_number_shift_right(NX_CRYPTO_HUGE_NUMBER *x, UINT shift);
199 UINT _nx_crypto_huge_number_inverse_modulus_prime(NX_CRYPTO_HUGE_NUMBER *a,
200                                                   NX_CRYPTO_HUGE_NUMBER *p,
201                                                   NX_CRYPTO_HUGE_NUMBER *r,
202                                                   HN_UBASE *scratch);
203 UINT _nx_crypto_huge_number_inverse_modulus(NX_CRYPTO_HUGE_NUMBER *a,
204                                             NX_CRYPTO_HUGE_NUMBER *m,
205                                             NX_CRYPTO_HUGE_NUMBER *r,
206                                             HN_UBASE *scratch);
207 VOID _nx_crypto_huge_number_mont(NX_CRYPTO_HUGE_NUMBER *m, UINT mi,
208                                  NX_CRYPTO_HUGE_NUMBER *x,
209                                  NX_CRYPTO_HUGE_NUMBER *y,
210                                  NX_CRYPTO_HUGE_NUMBER *result);
211 VOID _nx_crypto_huge_number_power_modulus(NX_CRYPTO_HUGE_NUMBER *number,
212                                           NX_CRYPTO_HUGE_NUMBER *exponent,
213                                           NX_CRYPTO_HUGE_NUMBER *modulus,
214                                           NX_CRYPTO_HUGE_NUMBER *result,
215                                           HN_UBASE *scratch);
216 VOID _nx_crypto_huge_number_mont_power_modulus(NX_CRYPTO_HUGE_NUMBER *x,
217                                                NX_CRYPTO_HUGE_NUMBER *e,
218                                                NX_CRYPTO_HUGE_NUMBER *m,
219                                                NX_CRYPTO_HUGE_NUMBER *result,
220                                                HN_UBASE *scratch);
221 VOID _nx_crypto_huge_number_crt_power_modulus(NX_CRYPTO_HUGE_NUMBER *x,
222                                               NX_CRYPTO_HUGE_NUMBER *e,
223                                               NX_CRYPTO_HUGE_NUMBER *p,
224                                               NX_CRYPTO_HUGE_NUMBER *q,
225                                               NX_CRYPTO_HUGE_NUMBER *m,
226                                               NX_CRYPTO_HUGE_NUMBER *result,
227                                               HN_UBASE *scratch);
228 
229 
230 #ifdef __cplusplus
231 }
232 #endif
233 
234 #endif /* NX_CRYPTO_HUGE_NUMBER_H */
235 
236