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