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