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