1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
|
/*
* Licensed Materials - Property of IBM
*
* trousers - An open source TCG Software Stack
*
* (C) Copyright International Business Machines Corp. 2006
*
*/
#ifndef BI_OPENSSL_
#define BI_OPENSSL_
#include <openssl/bn.h>
#include <openssl/engine.h>
typedef struct bignum_st bi_t[1];
typedef struct bignum_st *bi_ptr;
extern BN_CTX *context;
INLINE_DECL bi_ptr bi_new(bi_ptr result) {
BN_init( result);
return result;
}
/* create a big integer pointer */
INLINE_DECL bi_ptr bi_new_ptr(void) {
return BN_new();
}
/* free resources allocated to the big integer <i> */
INLINE_DECL void bi_free(const bi_ptr i) {
BN_free( i);
}
/* free resources allocated to the big integer pointer <i> */
INLINE_DECL void bi_free_ptr(const bi_ptr i) {
BN_free( i);
}
/* <result> := result++ */
INLINE_DECL bi_ptr bi_inc(bi_ptr result) {
BN_add_word( result, 1);
return result;
}
/* <result> := result-- */
INLINE_DECL bi_ptr bi_dec(bi_ptr result) {
BN_sub_word( result, 1);
return result;
}
/* return the current number of bits of the number */
INLINE_DECL long bi_length( const bi_ptr res) {
return BN_num_bits( res);
}
/***********************************************************************************
BASIC MATH OPERATION
*************************************************************************************/
/* <result> := - <result> */
INLINE_DECL bi_ptr bi_negate( bi_ptr result) {
BIGNUM *n = result;
n->neg = ( n->neg == 0 ? 1 : 0);
return result;
}
INLINE_DECL bi_ptr bi_mul_si( bi_ptr result, const bi_ptr i, const long n) {
BN_copy( result, i);
BN_mul_word( result, n);
return result;
}
/* <result> := <i> * <n> */
INLINE_DECL bi_ptr bi_mul( bi_ptr result, const bi_ptr i, const bi_ptr n) {
BN_mul( result, i, n, context);
return result;
}
INLINE_DECL bi_ptr bi_add_si( bi_ptr result, const bi_ptr i, const long n) {
BN_copy( result, i);
BN_add_word( result, n);
return result;
}
/* <result> := <i> + <n> */
INLINE_DECL bi_ptr bi_add( bi_ptr result, const bi_ptr i, const bi_ptr n) {
BN_add( result, i, n);
return result;
}
/* <result> := <i> - <n> */
INLINE_DECL bi_ptr bi_sub_si( bi_ptr result, const bi_ptr i, const long n) {
// n should be unsigned
BN_copy( result, i); // result := i
BN_sub_word( result, n); // result := result - n
return result;
}
/* <result> := <i> - <n> */
INLINE_DECL bi_ptr bi_sub( bi_ptr result, const bi_ptr i, const bi_ptr n) {
BN_sub( result, i, n);
return result;
}
/* <result> := ( <g> ^ <e> ) mod <m> */
INLINE_DECL bi_ptr bi_mod_exp( bi_ptr result, const bi_ptr g, const bi_ptr e, const bi_ptr m) {
BN_mod_exp( result, g, e, m, context); // result := (g ^ e) mod bi_m
return result;
}
/* set <result> by the division of <i> by the long <n> */
/* <result> := <i> / <n> */
INLINE_DECL bi_ptr bi_div_si( bi_ptr result, const bi_ptr i, const long n) {
BN_copy( result, i);
BN_div_word( result, n);
return result;
}
/* <result> := <i> / <n> */
INLINE_DECL bi_ptr bi_div( bi_ptr result, const bi_ptr i, const bi_ptr n) {
BN_div( result, NULL, i, n, context);
return result;
}
/***********************************************************************************
COMPARAISON
*************************************************************************************/
/* n1<n2 return negative value
* n1 = n2 return 0
* n1>n2 return positive value
*/
INLINE_DECL int bi_cmp( const bi_ptr n1, const bi_ptr n2) {
return BN_cmp( n1, n2);
}
/* n1<n2 return negative value
* n1 = n2 return 0
* n1>n2 return positive value
*/
INLINE_DECL int bi_cmp_si( const bi_ptr n1, const int n2) {
BIGNUM *temp = BN_new();
BN_set_word( temp, n2);
int res = BN_cmp( n1, temp);
BN_free( temp);
return res;
}
/* n1 == n2 return 1 (true)
* else return 0
*/
INLINE_DECL int bi_equals( const bi_ptr n1, const bi_ptr n2) {
return BN_cmp( n1, n2) == 0 ? 1 :0;
}
/* n1 == n2 return 1 (true)
* else return 0
*/
INLINE_DECL int bi_equals_si( const bi_ptr n1, const int n2) {
return BN_is_word( n1, n2);
}
/***********************************************************************************
CONVERSIONS
*************************************************************************************/
INLINE_DECL char *bi_2_hex_char(const bi_ptr i) {
char *result = BN_bn2hex( i);
if( result == NULL) {
return NULL;
}
list_add( allocs, result);
return result;
}
INLINE_DECL char *bi_2_dec_char(const bi_ptr i) {
char *result = BN_bn2dec( i);
if( result == NULL) {
return NULL;
}
list_add( allocs, result);
return result;
}
INLINE_DECL bi_ptr bi_set( bi_ptr result, const bi_ptr value) {
BN_copy( result, value);
return result;
}
INLINE_DECL bi_ptr bi_set_as_hex( bi_ptr result, const char *value) {
BN_hex2bn( &result, value);
return result;
}
INLINE_DECL bi_ptr bi_set_as_dec( bi_ptr result, const char *value) {
BN_dec2bn( &result, value);
return result;
}
/* set <i> with the value represented by unsigned int <value> */
/* <i> := <value> */
INLINE_DECL bi_ptr bi_set_as_si( bi_ptr result, const int value) {
if( value < 0) {
BN_set_word( result, -value);
result->neg=1;
} else
BN_set_word( result, value);
return result;
}
/* return (long)bi_t */
INLINE_DECL long bi_get_si(const bi_ptr i) {
long result = BN_get_word( i);
if( i->neg == 1) {
return -result;
}
return result;
}
/* return the size of a network byte order representation of <i> */
INLINE_DECL long bi_nbin_size(const bi_ptr i) {
return BN_num_bytes( i);
}
/* return a BYTE * in network byte order - big endian - and update the length <length> */
INLINE_DECL unsigned char *bi_2_nbin( int *length, const bi_ptr i) {
unsigned char *ret;
*length = BN_num_bytes( i);
ret = (unsigned char *)bi_alloc( *length * 2);
if( ret == NULL) return NULL;
BN_bn2bin( i, ret);
return ret;
}
/* return a BYTE * - in network byte order - and update the length <length> */
/* different from bi_2_nbin: you should reserve enough memory for the storage */
INLINE_DECL void bi_2_nbin1( int *length, unsigned char *buffer, const bi_ptr i) {
*length = BN_num_bytes( i);
BN_bn2bin( i, buffer);
}
/* return a bi_ptr that correspond to the big endian encoded BYTE array of length <n_length> */
INLINE_DECL bi_ptr bi_set_as_nbin( const unsigned long length, const unsigned char *buffer) {
bi_ptr ret_bi = bi_new_ptr();
if( ret_bi == NULL) return NULL;
if( BN_bin2bn( buffer, length, ret_bi) == NULL) {
bi_free( ret_bi);
return NULL;
}
return ret_bi;
}
/* convert a bi to a openssl BIGNUM struct */
INLINE_DECL BIGNUM *bi_2_BIGNUM( const bi_ptr i) {
return i;
}
/* set <i> with the value represented by the given openssl BIGNUM struct */
INLINE_DECL bi_ptr bi_set_as_BIGNUM( bi_ptr i, BIGNUM *bn) {
return bi_set( i, bn);
}
/***********************************************************************************
BITS OPERATION
*************************************************************************************/
/* set the bit to 1 */
INLINE_DECL bi_ptr bi_setbit(bi_ptr result, const int bit) {
BN_set_bit( result, bit);
return result;
}
/* <result> := <i> << <n> */
INLINE_DECL bi_ptr bi_shift_left( bi_ptr result, const bi_ptr i, const int n) {
BN_lshift( result, i, n);
return result;
}
/* <result> := <i> >> <n> */
INLINE_DECL bi_ptr bi_shift_right( bi_ptr result, const bi_ptr i, const int n) {
BN_rshift( result, i, n);
return result;
}
/* create a random of length <length> bits */
/* res := random( length) */
INLINE_DECL bi_ptr bi_urandom( bi_ptr result, const long length) {
/*
* <result> will be a generated cryptographically strong pseudo-random number of length
* <length>
*/
BN_rand( result, length, -1, 0);
return result;
}
/* res := <n> mod <m> */
INLINE_DECL bi_ptr bi_mod_si( bi_ptr result, const bi_ptr n, const long m) {
BIGNUM *mod = BN_new();
BN_set_word( mod, m);
BN_mod( result, n, mod, context);
BN_free( mod);
return result;
}
/* res := <n> mod <m> */
INLINE_DECL bi_ptr bi_mod( bi_ptr result, const bi_ptr n, const bi_ptr m) {
BN_mod( result, n, m, context);
if( result->neg == 1) {
result->neg=0;
BN_sub( result, m, result);
}
return result;
}
/* result := (inverse of <i>) mod <m> */
/* if the inverse exist, return >0, otherwise 0 */
INLINE_DECL int bi_invert_mod( bi_ptr result, const bi_ptr i, const bi_ptr m) {
while( ERR_get_error() != 0);
BN_mod_inverse( result, i, m, context);
return ERR_get_error() == 0 ? 1 : 0;
}
/* generate a prime number of <length> bits */
INLINE_DECL bi_ptr bi_generate_prime( bi_ptr result, const long bit_length) {
BN_generate_prime(result, bit_length, 0, NULL, NULL, NULL, NULL);
return result;
}
/* generate a safe prime number of <length> bits */
/* by safe we mean a prime p so that (p-1)/2 is also prime */
INLINE_DECL bi_ptr bi_generate_safe_prime( bi_ptr result, const long bit_length) {
BN_generate_prime(result, bit_length, 1, NULL, NULL, NULL, NULL);
return result;
}
/* return in <result> the greatest common divisor of <a> and <b> */
/* <result> := gcd( <a>, <b>) */
INLINE_DECL bi_ptr bi_gcd( bi_ptr result, bi_ptr a, bi_ptr b) {
BN_gcd( result, a, b, context);
return result;
}
#endif /*BI_OPENSSL_*/
|