char *BN_bn2hex(const BIGNUM *bn) { int width = bn_minimal_width(bn); char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ + width * BN_BYTES * 2 + 1 /* trailing NUL */); if (buf == NULL) { OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); return NULL; } char *p = buf; if (bn->neg) { *(p++) = '-'; } if (BN_is_zero(bn)) { *(p++) = '0'; } int z = 0; for (int i = width - 1; i >= 0; i--) { for (int j = BN_BITS2 - 8; j >= 0; j -= 8) { // strip leading zeros int v = ((int)(bn->d[i] >> (long)j)) & 0xff; if (z || v != 0) { *(p++) = hextable[v >> 4]; *(p++) = hextable[v & 0x0f]; z = 1; } } }
int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w) { switch (bn_minimal_width(bn)) { case 1: return bn->d[0] == w; case 0: return w == 0; default: return 0; } }
int BN_is_pow2(const BIGNUM *bn) { int width = bn_minimal_width(bn); if (width == 0 || bn->neg) { return 0; } for (int i = 0; i < width - 1; i++) { if (bn->d[i] != 0) { return 0; } } return 0 == (bn->d[width-1] & (bn->d[width-1] - 1)); }
int BN_sub_word(BIGNUM *a, BN_ULONG w) { int i; // degenerate case: w is zero if (!w) { return 1; } // degenerate case: a is zero if (BN_is_zero(a)) { i = BN_set_word(a, w); if (i != 0) { BN_set_negative(a, 1); } return i; } // handle 'a' when negative if (a->neg) { a->neg = 0; i = BN_add_word(a, w); a->neg = 1; return i; } if ((bn_minimal_width(a) == 1) && (a->d[0] < w)) { a->d[0] = w - a->d[0]; a->neg = 1; return 1; } i = 0; for (;;) { if (a->d[i] >= w) { a->d[i] -= w; break; } else { a->d[i] -= w; i++; w = 1; } } if ((a->d[i] == 0) && (i == (a->width - 1))) { a->width--; } return 1; }
int BN_is_zero(const BIGNUM *bn) { return bn_minimal_width(bn) == 0; }
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { int max, min, dif; register BN_ULONG t1, t2, *ap, *bp, *rp; int i, carry; max = bn_minimal_width(a); min = bn_minimal_width(b); dif = max - min; if (dif < 0) // hmm... should not be happening { OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3); return 0; } if (!bn_wexpand(r, max)) { return 0; } ap = a->d; bp = b->d; rp = r->d; carry = 0; for (i = min; i != 0; i--) { t1 = *(ap++); t2 = *(bp++); if (carry) { carry = (t1 <= t2); t1 -= t2 + 1; } else { carry = (t1 < t2); t1 -= t2; } *(rp++) = t1; } if (carry) // subtracted { if (!dif) { // error: a < b return 0; } while (dif) { dif--; t1 = *(ap++); t2 = t1 - 1; *(rp++) = t2; if (t1) { break; } } } if (dif > 0 && rp != ap) { OPENSSL_memcpy(rp, ap, sizeof(*rp) * dif); } r->width = max; r->neg = 0; bn_set_minimal_width(r); return 1; }