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