1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "../common/dbgnew.hh"
14 #include <openssl/crypto.h>
21 // We cannot check without using a "./configure" script or such if we have
22 // llabs() or not. Define our own function instead.
23 inline long long ll_abs(long long x
) { return ((x
>= 0) ? (x
) : (-x
)); }
27 string
Int2string(const Int
& i
)
30 s
= mprintf("%lld", i
);
36 Int
string2Int(const char *s
, const Location
& loc
)
39 Int i
= strtoll(s
, NULL
, 10);
42 if (loc
.get_filename() != NULL
) {
43 loc
.error("Overflow when converting `%s' to integer value: %s", s
,
46 FATAL_ERROR("Overflow when converting `%s' to integer value: %s", s
,
53 FATAL_ERROR("Unexpected error when converting `%s' to integer: %s", s
,
59 int_val_t::int_val_t() : native_flag(true)
64 int_val_t::int_val_t(const int_val_t
& v
)
66 native_flag
= v
.is_native();
67 if (native_flag
) val
.native
= v
.get_val();
68 else val
.openssl
= BN_dup(v
.get_val_openssl());
71 int_val_t::int_val_t(const char *s
, const Location
& loc
)
74 if (!BN_dec2bn(&n
, *s
== '+' ? s
+ 1 : s
))
75 loc
.error("Unexpected error when converting `%s' to integer", s
);
76 if (BN_num_bits(n
) > (int)sizeof(long long) * 8 - 1) {
81 val
.native
= string2Int(s
, loc
);
86 int_val_t::~int_val_t()
88 if (!native_flag
) BN_free(val
.openssl
);
91 string
int_val_t::t_str() const
95 tmp
= mprintf("%lld", val
.native
);
100 if (!(tmp
= BN_bn2dec(val
.openssl
)))
101 FATAL_ERROR("int_val_t::t_str()");
108 BIGNUM
*int_val_t::to_openssl() const
112 string str
= Int2string(val
.native
);
113 if (!BN_dec2bn(&big
, str
.c_str())) FATAL_ERROR("int_val_t::to_openssl()");
115 big
= BN_dup(val
.openssl
);
116 if (!big
) FATAL_ERROR("int_val_t::to_openssl()");
121 bool int_val_t::operator==(Int right
) const
123 if (!native_flag
) return false;
124 return val
.native
== right
;
127 bool int_val_t::operator==(const int_val_t
& v
) const
129 if (native_flag
!= v
.is_native()) return false;
130 if (native_flag
) return val
.native
== v
.get_val();
131 return !BN_cmp(val
.openssl
, v
.get_val_openssl());
134 bool int_val_t::operator<(const int_val_t
& v
) const
138 return val
.native
< v
.get_val();
140 BIGNUM
*this_big
= to_openssl();
141 if (!this_big
) FATAL_ERROR("int_val_t::operator<(int_val_t& v)");
142 int this_equ
= BN_cmp(this_big
, v
.get_val_openssl());
144 return this_equ
== -1;
148 BIGNUM
*v_big
= v
.to_openssl();
149 if (!v_big
) FATAL_ERROR("int_val_t::operator<(int_val_t& v)");
150 int v_equ
= BN_cmp(val
.openssl
, v_big
);
154 return BN_cmp(val
.openssl
, v
.val
.openssl
) == -1;
159 int_val_t
int_val_t::operator-() const
162 if (val
.native
== LLONG_MIN
) {
163 BIGNUM
*result
= int_val_t(LLONG_MIN
).to_openssl();
164 BN_set_negative(result
, 0);
165 return int_val_t(result
);
167 return int_val_t(-val
.native
);
170 BIGNUM
*llong_max_plus_one
= int_val_t(LLONG_MIN
).to_openssl();
171 BN_set_negative(llong_max_plus_one
, 0);
172 int cmp
= BN_cmp(val
.openssl
, llong_max_plus_one
);
173 BN_free(llong_max_plus_one
);
175 return int_val_t(LLONG_MIN
);
177 BIGNUM
*result
= BN_dup(val
.openssl
);
178 BN_set_negative(result
, !BN_is_negative(result
));
179 return int_val_t(result
);
184 int_val_t
int_val_t::operator+(const int_val_t
& right
) const
189 // -a + -b = -(a add b)
190 // Use only inline functions and BN_* directly. Call out for operator- in
192 bool a_neg
= is_negative();
193 bool b_neg
= right
.is_negative();
194 bool r_neg
= a_neg
&& b_neg
;
195 if (!a_neg
&& b_neg
) return operator-(-right
);
196 if (a_neg
&& !b_neg
) return right
.operator-(-(*this));
199 if (right
.is_native()) {
200 unsigned long long result
= val
.native
+ right
.get_val();
201 result_
= val
.native
+ right
.get_val();
202 if (static_cast<long long>(result
) != result_
||
203 (!r_neg
&& result_
< 0) || (r_neg
&& result_
> 0)) {
204 // We can safely assume that the sum of two non-negative long long
205 // values fit in an unsigned long long. limits.h says:
206 // # ifndef ULLONG_MAX
207 // # define ULLONG_MAX (LLONG_MAX * 2ULL + 1)
209 // This is the most complicated case. We cannot be sure that
210 // sizeof(BN_ULONG) == sizeof(long long). First convert the long long
211 // to string and feed BN_dec2bn.
212 BIGNUM
*left_
= to_openssl();
213 BIGNUM
*right_
= right
.to_openssl();
214 BN_add(left_
, left_
, right_
);
216 return int_val_t(left_
);
218 return int_val_t(result_
);
221 // long long (>= 0) + BIGNUM == BIGNUM.
222 BIGNUM
*result
= BN_new();
223 BIGNUM
*left_
= to_openssl();
224 BN_add(result
, left_
, right
.get_val_openssl());
225 return int_val_t(result
);
228 // BIGNUM + long long (>= 0) == BIGNUM.
229 BIGNUM
*result
= BN_new();
231 right_
= right
.is_native() ? right
.to_openssl() : right
.get_val_openssl();
232 BN_add(result
, val
.openssl
, right_
);
233 if (right
.is_native())
235 return int_val_t(result
);
239 int_val_t
int_val_t::operator-(const int_val_t
& right
) const
242 // -a - b = -(a add b)
244 // -a - -b = -a add b = b sub a
245 bool a_neg
= is_negative();
246 bool b_neg
= right
.is_negative();
247 if (!a_neg
&& b_neg
) return operator+(-right
);
248 if (a_neg
&& !b_neg
) return -right
.operator+(-(*this));
250 if (right
.is_native()) {
251 // Since both operands are non-negative the most negative result of a
252 // subtraction can be -LLONG_MAX and according to limits.h:
253 // # ifndef LLONG_MIN
254 // # define LLONG_MIN (-LLONG_MAX-1)
256 return int_val_t(val
.native
- right
.get_val());
258 BIGNUM
*left_bn
= to_openssl();
259 BN_sub(left_bn
, left_bn
, right
.get_val_openssl());
260 // The result can be small enough to fit in long long. The same is true
261 // for division. Back conversion is a really costly operation using
262 // strings all the time. TODO Improve it.
263 if (BN_num_bits(left_bn
) <= (int)sizeof(long long) * 8 - 1) {
264 char *result_str
= BN_bn2dec(left_bn
);
265 Int result_ll
= string2Int(result_str
, Location());
266 OPENSSL_free(result_str
);
268 return int_val_t(result_ll
);
270 return int_val_t(left_bn
);
274 BIGNUM
*result
= BN_new();
276 right_bn
= right
.is_native() ? right
.to_openssl() :
277 right
.get_val_openssl();
278 BN_sub(result
, val
.openssl
, right_bn
);
279 if (right
.is_native()) BN_free(right_bn
);
280 if (BN_num_bits(result
) <= (int)sizeof(long long) * 8 - 1) {
281 char *result_str
= BN_bn2dec(result
);
282 Int result_ll
= string2Int(result_str
, Location());
283 OPENSSL_free(result_str
);
284 return int_val_t(result_ll
);
286 return int_val_t(result
);
291 int_val_t
int_val_t::operator*(const int_val_t
& right
) const
293 if ((native_flag
&& val
.native
== 0LL) ||
294 (right
.native_flag
&& right
.val
.native
== 0LL))
295 return int_val_t(0LL);
297 if (right
.native_flag
) {
298 // 2^15 is used as a simple heuristic.
300 if (ll_abs(val
.native
) < 32768LL && ll_abs(right
.val
.native
) < 32768LL) {
301 return int_val_t(val
.native
* right
.val
.native
);
303 BIGNUM
*left_bn
= to_openssl();
304 BIGNUM
*right_bn
= right
.to_openssl();
305 BN_CTX
*ctx
= BN_CTX_new();
307 BN_mul(left_bn
, left_bn
, right_bn
, ctx
);
310 if (BN_num_bits(left_bn
) < (int)sizeof(long long) * 8) {
312 return int_val_t(val
.native
* right
.val
.native
);
314 return int_val_t(left_bn
);
318 BIGNUM
*this_bn
= to_openssl();
319 BN_CTX
*ctx
= BN_CTX_new();
321 BN_mul(this_bn
, this_bn
, right
.get_val_openssl(), ctx
);
323 return int_val_t(this_bn
);
326 BIGNUM
*result
= BN_new();
328 BN_CTX
*ctx
= BN_CTX_new();
330 right_bn
= right
.native_flag
? right
.to_openssl()
331 : right
.get_val_openssl();
332 BN_mul(result
, val
.openssl
, right_bn
, ctx
);
334 if (right
.native_flag
) BN_free(right_bn
);
335 return int_val_t(result
);
339 int_val_t
int_val_t::operator/(const int_val_t
& right
) const
341 if (native_flag
&& val
.native
== 0LL)
342 return int_val_t(0LL);
343 if (right
.is_native() && right
.get_val() == 0LL)
344 FATAL_ERROR("Division by zero after semantic check");
346 if (right
.native_flag
) {
347 return int_val_t(val
.native
/ right
.get_val());
349 BIGNUM
*left_bn
= to_openssl();
350 BN_CTX
*ctx
= BN_CTX_new();
352 BN_div(left_bn
, NULL
, left_bn
, right
.get_val_openssl(), ctx
);
354 if (BN_num_bits(left_bn
) <= (int)sizeof(long long) * 8 - 1) {
355 char *result_str
= BN_bn2dec(left_bn
);
356 Int result_ll
= string2Int(result_str
, Location());
357 OPENSSL_free(result_str
);
359 return int_val_t(result_ll
);
361 return int_val_t(left_bn
);
365 BIGNUM
*result
= BN_new();
367 BN_CTX
*ctx
= BN_CTX_new();
369 right_bn
= right
.is_native() ? right
.to_openssl() :
370 right
.get_val_openssl();
371 BN_div(result
, NULL
, val
.openssl
, right_bn
, ctx
);
373 if (BN_num_bits(result
) <= (int)sizeof(long long) * 8 - 1) {
374 char *result_str
= BN_bn2dec(result
);
375 Int result_ll
= string2Int(result_str
, Location());
376 OPENSSL_free(result_str
);
377 return int_val_t(result_ll
);
379 if (right
.is_native())
381 return int_val_t(result
);
386 int_val_t
int_val_t::operator&(Int right
) const
388 // TODO Right can be int_val_t. Now it works only if right fits in
389 // BN_ULONG. If it's not true right must be converted to BIGNUM and the
390 // bits should be set with BN_is_bit_set/BN_set_bit.
391 BN_ULONG right_bn_ulong
= (BN_ULONG
)right
;
392 if (right
!= (long long)right_bn_ulong
)
393 FATAL_ERROR("Bitmask is too big");
395 return int_val_t(val
.native
& right
);
397 BIGNUM
*tmp
= BN_dup(val
.openssl
);
398 BN_mask_bits(tmp
, sizeof(BN_ULONG
) * 8);
399 BN_ULONG word
= BN_get_word(tmp
);
401 return int_val_t(word
& right_bn_ulong
);
405 int_val_t
int_val_t::operator>>(Int right
) const
408 // Shifting right (or left) with a number greater or equal to the bits of
409 // the type of the left operand has an undefined behaviour.
410 // http://bytes.com/groups/c/495137-right-shift-weird-result-why
411 Int shifted_value
= right
>= static_cast<Int
>(sizeof(Int
) * 8) ? 0 :
413 return int_val_t(shifted_value
);
415 BIGNUM
*result
= BN_new();
416 BN_rshift(result
, val
.openssl
, right
);
417 if (BN_num_bits(result
) < (int)sizeof(long long) * 8 - 1) {
418 char *result_str
= BN_bn2dec(result
);
419 Int result_ll
= string2Int(result_str
, Location());
420 OPENSSL_free(result_str
);
422 return int_val_t(result_ll
);
424 return int_val_t(result
);
429 const Int
& int_val_t::get_val() const
431 if (!native_flag
) FATAL_ERROR("Invalid conversion of a large integer value");
435 BIGNUM
*int_val_t::get_val_openssl() const
437 if (native_flag
) FATAL_ERROR("Invalid conversion of a large integer value");
441 Real
int_val_t::to_real() const
444 return (double)val
.native
;
446 char *result_str
= BN_bn2dec(val
.openssl
);
448 // Use fixed-point notation. The mantissa is usually at most 52-bits.
449 // Bigger integer values will be rounded.
450 if (sscanf(result_str
, "%lf", &result
) != 1)
451 FATAL_ERROR("Conversion of integer value `%s' to float failed",
452 result_str
); // No deallocation, it'll crash anyway...
453 OPENSSL_free(result_str
);
458 int_val_t
& int_val_t::operator=(const int_val_t
& right
)
460 if (!native_flag
) BN_free(val
.openssl
);
461 native_flag
= right
.native_flag
;
462 if (native_flag
) val
.native
= right
.get_val();
463 else val
.openssl
= BN_dup(right
.get_val_openssl());
467 int_val_t
& int_val_t::operator<<=(Int right
)
469 // It makes no sense to support negative operands. GCC returns constant "0"
470 // with "warning: left shift count is negative" for these shifts.
471 // BN_set_word is not enough since sizeof(BN_ULONG) != sizeof(long long).
472 // In TTCN-3 <<= right means >>= -right.
473 if (right
< 0) FATAL_ERROR("The second operand of bitwise shift operators "
474 "cannot be negative");
475 if (right
== 0) return *this;
477 BIGNUM
*result
= BN_new();
478 BN_dec2bn(&result
, Int2string(val
.native
).c_str());
479 BN_lshift(result
, result
, right
);
480 if (BN_num_bits(result
) > (int)sizeof(long long) * 8 - 1) {
481 val
.openssl
= result
;
484 val
.native
<<= right
;
488 BN_lshift(val
.openssl
, val
.openssl
, right
);
493 int_val_t
& int_val_t::operator>>=(Int right
)
495 if (right
< 0) FATAL_ERROR("The second operand of bitwise shift operators "
496 "cannot be negative");
497 if (right
== 0) return *this;
499 val
.native
>>= right
;
501 BN_rshift(val
.openssl
, val
.openssl
, right
);
502 if (BN_num_bits(val
.openssl
) <= (int)sizeof(long long) * 8 - 1) {
503 char *result_str
= BN_bn2dec(val
.openssl
);
504 Int result_ll
= string2Int(result_str
, Location());
505 OPENSSL_free(result_str
);
507 BN_free(val
.openssl
);
508 val
.native
= result_ll
;
514 int_val_t
& int_val_t::operator+=(Int right
)
516 // Unfortunately we have to check the sign of the "right" operand and
517 // perform addition or subtraction accordingly.
518 if (right
== 0) return *this;
519 bool neg
= right
< 0;
521 BIGNUM
*result
= BN_new();
522 BN_set_word(result
, (BN_ULONG
)val
.native
);
523 if (neg
) BN_sub_word(result
, (BN_ULONG
)right
);
524 else BN_add_word(result
, (BN_ULONG
)right
);
525 if (BN_num_bits(result
) > (int)sizeof(long long) * 8 - 1) {
526 val
.openssl
= result
;
533 if (neg
) BN_sub_word(val
.openssl
, (BN_ULONG
)right
);
534 else BN_add_word(val
.openssl
, (BN_ULONG
)right
);
535 if (BN_num_bits(val
.openssl
) <= (int)sizeof(long long) * 8 - 1) {
536 // TODO BN_ULONG != long long.
537 BN_ULONG tmp
= BN_get_word(val
.openssl
);
538 if (BN_is_negative(val
.openssl
)) tmp
*= -1;
539 BN_free(val
.openssl
);
This page took 0.043354 seconds and 6 git commands to generate.