/* Computes the sum * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1] * gracefully ignoring NULL scalar values. */ int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) { BN_CTX *new_ctx = NULL; int ret = 0; size_t i; EC_POINT *p=NULL; EC_POINT *acc = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } /* This implementation is more efficient than the wNAF implementation for 2 * or fewer points. Use the ec_wNAF_mul implementation for 3 or more points, * or if we can perform a fast multiplication based on precomputation. */ if ((scalar && (num > 1)) || (num > 2) || (num == 0 && EC_GROUP_have_precompute_mult(group))) { ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); goto err; } if ((p = EC_POINT_new(group)) == NULL) goto err; if ((acc = EC_POINT_new(group)) == NULL) goto err; if (!EC_POINT_set_to_infinity(group, acc)) goto err; if (scalar) { if (!ec_GF2m_montgomery_point_multiply(group, p, scalar, group->generator, ctx)) goto err; if (BN_is_negative(scalar)) if (!group->meth->invert(group, p, ctx)) goto err; if (!group->meth->add(group, acc, acc, p, ctx)) goto err; } for (i = 0; i < num; i++) { if (!ec_GF2m_montgomery_point_multiply(group, p, scalars[i], points[i], ctx)) goto err; if (BN_is_negative(scalars[i])) if (!group->meth->invert(group, p, ctx)) goto err; if (!group->meth->add(group, acc, acc, p, ctx)) goto err; } if (!EC_POINT_copy(r, acc)) goto err; ret = 1; err: if (p) EC_POINT_free(p); if (acc) EC_POINT_free(acc); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai) { ASN1_ENUMERATED *ret; int len,j; if (ai == NULL) ret=M_ASN1_ENUMERATED_new(); else ret=ai; if (ret == NULL) { OPENSSL_PUT_ERROR(ASN1, BN_to_ASN1_ENUMERATED, ASN1_R_NESTED_ASN1_ERROR); goto err; } if(BN_is_negative(bn)) ret->type = V_ASN1_NEG_ENUMERATED; else ret->type=V_ASN1_ENUMERATED; j=BN_num_bits(bn); len=((j == 0)?0:((j/8)+1)); if (ret->length < len+4) { unsigned char *new_data=OPENSSL_realloc(ret->data, len+4); if (!new_data) { OPENSSL_PUT_ERROR(ASN1, BN_to_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); goto err; } ret->data=new_data; } ret->length=BN_bn2bin(bn,ret->data); return(ret); err: if (ret != ai) M_ASN1_ENUMERATED_free(ret); return(NULL); }
static void store_array(void) { struct number *inumber; struct value *value; struct stack *stack; u_long idx; int reg; reg = readreg(); if (reg >= 0) { inumber = pop_number(); if (inumber == NULL) return; value = pop(); if (value == NULL) { free_number(inumber); return; } idx = get_ulong(inumber); if (BN_is_negative(inumber->number)) { warnx("negative idx"); stack_free_value(value); } else if (idx == ULONG_MAX || idx > MAX_ARRAY_INDEX) { warnx("idx too big"); stack_free_value(value); } else { stack = &bmachine.reg[reg]; frame_assign(stack, idx, value); } free_number(inumber); } }
/** * Encode the varint using two's complement * * @return Vector of bytes in two's complement */ std::vector<unsigned char> encode_varint() const { // Handle NULL and zero varint if (!big_number_ || BN_num_bytes(big_number_.get()) == 0) { std::vector<unsigned char> bytes(1); bytes[0] = 0x00; return bytes; } size_t number_of_bytes = BN_num_bytes(big_number_.get()) + 1; std::vector<unsigned char> bytes(number_of_bytes); if (BN_bn2bin(big_number_.get(), &bytes[1]) > 0) { // Set the sign and convert to two's complement (if necessary) if (BN_is_negative(big_number_.get())) { bool is_carry = true; for (ssize_t i = number_of_bytes - 1; i >= 0; --i) { bytes[i] ^= 0xFF; if (is_carry) { is_carry = ((++bytes[i]) == 0); } } bytes[0] |= 0x80; } else { bytes[0] = 0x00; } } return bytes; }
int BN_bn2cbb(CBB *cbb, const BIGNUM *bn) { /* Negative numbers are unsupported. */ if (BN_is_negative(bn)) { OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); return 0; } CBB child; if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) { OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR); return 0; } /* The number must be padded with a leading zero if the high bit would * otherwise be set (or |bn| is zero). */ if (BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) { OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR); return 0; } uint8_t *out; if (!CBB_add_space(&child, &out, BN_num_bytes(bn))) { OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR); return 0; } BN_bn2bin(bn, out); if (!CBB_flush(cbb)) { OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR); return 0; } return 1; }
static void load_array(void) { struct number *inumber, *n; struct stack *stack; struct value *v; struct value copy; u_long idx; int reg; reg = readreg(); if (reg >= 0) { inumber = pop_number(); if (inumber == NULL) return; idx = get_ulong(inumber); if (BN_is_negative(inumber->number)) warnx("negative idx"); else if (idx == ULONG_MAX || idx > MAX_ARRAY_INDEX) warnx("idx too big"); else { stack = &bmachine.reg[reg]; v = frame_retrieve(stack, idx); if (v == NULL || v->type == BCODE_NONE) { n = new_number(); bn_check(BN_zero(n->number)); push_number(n); } else push(stack_dup_value(v, ©)); } free_number(inumber); } }
void bn8_from_bn(bn8 r, const BIGNUM *a) { int n = BN_num_bytes(a); memset(r, 0, BN8_SIZE); BN_bn2bin(a, r+1+(BN8_SIZE-1)-n); if(BN_is_negative(a)) bn8_negative(r); }
int64_t bigint::to_int64() const { FC_ASSERT(BN_num_bits(n) <= 63); size_t size = BN_num_bytes(n); uint64_t abs_value = 0; BN_bn2bin(n, (unsigned char*)&abs_value + (sizeof(uint64_t) - size)); return BN_is_negative(n) ? -(int64_t)bswap_64(abs_value) : bswap_64(abs_value); }
int rsa_greater_than_pow2(const BIGNUM *b, int n) { if (BN_is_negative(b) || n == INT_MAX) { return 0; } int b_bits = BN_num_bits(b); return b_bits > n + 1 || (b_bits == n + 1 && !BN_is_pow2(b)); }
extern "C" int Java_java_math_NativeBN_sign(JNIEnv* env, jclass, jlong a) { if (!oneValidHandle(env, a)) return -2; if (BN_is_zero(toBigNum(a))) { return 0; } else if (BN_is_negative(toBigNum(a))) { return -1; } return 1; }
int _hc_BN_to_integer(BIGNUM *bn, heim_integer *integer) { integer->length = BN_num_bytes(bn); integer->data = malloc(integer->length); if (integer->data == NULL) return ENOMEM; BN_bn2bin(bn, integer->data); integer->negative = BN_is_negative(bn); return 0; }
static krb5_error_code BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) { integer->length = BN_num_bytes(bn); integer->data = malloc(integer->length); if (integer->data == NULL) { krb5_clear_error_message(context); return ENOMEM; } BN_bn2bin(bn, integer->data); integer->negative = BN_is_negative(bn); return 0; }
static int bn2heim_int(BIGNUM *bn, heim_integer *integer) { integer->length = BN_num_bytes(bn); integer->data = malloc(integer->length); if (integer->data == NULL) { integer->length = 0; return ENOMEM; } BN_bn2bin(bn, integer->data); integer->negative = BN_is_negative(bn); return 0; }
/** * Convert BIGNUM to bytea. (Copied from pg-bignum) */ bytea * bignum_to_bytea(BIGNUM *bn) { int len; bytea *results; // create bytea results. len = BN_num_bytes(bn); results = (bytea *) palloc(len + 1 + VARHDRSZ); *VARDATA(results) = BN_is_negative(bn) ? 0x01 : 0x00; BN_bn2bin(bn, (unsigned char *) VARDATA(results) + 1); SET_VARSIZE(results, len + 1 + VARHDRSZ); return results; }
int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, unsigned char *buf, int off) { int n, i; const char *neg; if (num == NULL) return (1); neg = (BN_is_negative(num)) ? "-" : ""; if (!BIO_indent(bp, off, 128)) return 0; if (BN_is_zero(num)) { if (BIO_printf(bp, "%s 0\n", number) <= 0) return 0; return 1; } if (BN_num_bytes(num) <= BN_BYTES) { if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg, (unsigned long)num->d[0], neg, (unsigned long)num->d[0]) <= 0) return (0); } else { buf[0] = 0; if (BIO_printf(bp, "%s%s", number, (neg[0] == '-') ? " (Negative)" : "") <= 0) return (0); n = BN_bn2bin(num, &buf[1]); if (buf[1] & 0x80) n++; else buf++; for (i = 0; i < n; i++) { if ((i % 15) == 0) { if (BIO_puts(bp, "\n") <= 0 || !BIO_indent(bp, off + 4, 128)) return 0; } if (BIO_printf(bp, "%02x%s", buf[i], ((i + 1) == n) ? "" : ":") <= 0) return (0); } if (BIO_write(bp, "\n", 1) <= 0) return (0); } return (1); }
int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, unsigned char *ign, int indent) { int n, rv = 0; const char *neg; unsigned char *buf = NULL, *tmp = NULL; int buflen; if (num == NULL) return 1; neg = BN_is_negative(num) ? "-" : ""; if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT)) return 0; if (BN_is_zero(num)) { if (BIO_printf(bp, "%s 0\n", number) <= 0) return 0; return 1; } if (BN_num_bytes(num) <= BN_BYTES) { if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg, (unsigned long)bn_get_words(num)[0], neg, (unsigned long)bn_get_words(num)[0]) <= 0) return 0; return 1; } buflen = BN_num_bytes(num) + 1; buf = tmp = OPENSSL_malloc(buflen); if (buf == NULL) goto err; buf[0] = 0; if (BIO_printf(bp, "%s%s\n", number, (neg[0] == '-') ? " (Negative)" : "") <= 0) goto err; n = BN_bn2bin(num, buf + 1); if (buf[1] & 0x80) n++; else tmp++; if (ASN1_buf_print(bp, tmp, n, indent + 4) == 0) goto err; rv = 1; err: OPENSSL_clear_free(buf, buflen); return rv; }
/* g^x is a legal value */ static int is_legal(const BIGNUM *gx, const JPAKE_CTX *ctx) { BIGNUM *t; int res; if(BN_is_negative(gx) || BN_is_zero(gx) || BN_cmp(gx, ctx->p.p) >= 0) return 0; t = BN_new(); BN_mod_exp(t, gx, ctx->p.q, ctx->p.p, ctx->ctx); res = BN_is_one(t); BN_free(t); return res; }
static int set_Jprojective_coordinate_GFp(const EC_GROUP *group, BIGNUM *out, const BIGNUM *in, BN_CTX *ctx) { if (in == NULL) { return 1; } if (BN_is_negative(in) || BN_cmp(in, &group->field) >= 0) { OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); return 0; } if (group->meth->field_encode) { return group->meth->field_encode(group, out, in, ctx); } return BN_copy(out, in) != NULL; }
static int check_mod_inverse(int *out_ok, const BIGNUM *a, const BIGNUM *ainv, const BIGNUM *m, int check_reduced, BN_CTX *ctx) { BN_CTX_start(ctx); BIGNUM *tmp = BN_CTX_get(ctx); int ret = tmp != NULL && bn_mul_consttime(tmp, a, ainv, ctx) && bn_div_consttime(NULL, tmp, tmp, m, ctx); if (ret) { *out_ok = BN_is_one(tmp); if (check_reduced && (BN_is_negative(ainv) || BN_cmp(ainv, m) >= 0)) { *out_ok = 0; } } BN_CTX_end(ctx); return ret; }
static void bsqrt(void) { struct number *n; struct number *r; BIGNUM *x, *y; u_int scale, onecount; BN_CTX *ctx; onecount = 0; n = pop_number(); if (n == NULL) { return; } if (BN_is_zero(n->number)) { r = new_number(); push_number(r); } else if (BN_is_negative(n->number)) warnx("square root of negative number"); else { scale = max(bmachine.scale, n->scale); normalize(n, 2*scale); x = BN_dup(n->number); bn_checkp(x); bn_check(BN_rshift(x, x, BN_num_bits(x)/2)); y = BN_new(); bn_checkp(y); ctx = BN_CTX_new(); bn_checkp(ctx); for (;;) { bn_checkp(BN_copy(y, x)); bn_check(BN_div(x, NULL, n->number, x, ctx)); bn_check(BN_add(x, x, y)); bn_check(BN_rshift1(x, x)); if (bsqrt_stop(x, y, &onecount)) break; } r = bmalloc(sizeof(*r)); r->scale = scale; r->number = y; BN_free(x); BN_CTX_free(ctx); push_number(r); } free_number(n); }
int dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) { int i; int n = BN_num_bits(dh_pub); int bits_set = 0; BIGNUM *tmp; const BIGNUM *p; if (BN_is_negative(dh_pub)) { logit("invalid public DH value: negative"); return 0; } if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */ logit("invalid public DH value: <= 1"); return 0; } if ((tmp = BN_new()) == NULL) { error("%s: BN_new failed", __func__); return 0; } DH_get0_pqg(dh, &p, NULL, NULL); if (!BN_sub(tmp, p, BN_value_one()) || BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ BN_clear_free(tmp); logit("invalid public DH value: >= p-1"); return 0; } BN_clear_free(tmp); for (i = 0; i <= n; i++) if (BN_is_bit_set(dh_pub, i)) bits_set++; debug2("bits set: %d/%d", bits_set, BN_num_bits(p)); /* * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */ if (bits_set < 4) { logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(p)); return 0; } return 1; }
ASN1_INTEGER *BN_to_ASN1_INTEGER (const BIGNUM * bn, ASN1_INTEGER * ai) { ASN1_INTEGER *ret; int len, j; if (ai == NULL) ret = M_ASN1_INTEGER_new (); else ret = ai; if (ret == NULL) { ASN1err (ASN1_F_BN_TO_ASN1_INTEGER, ERR_R_NESTED_ASN1_ERROR); goto err; } if (BN_is_negative (bn)) ret->type = V_ASN1_NEG_INTEGER; else ret->type = V_ASN1_INTEGER; j = BN_num_bits (bn); len = ((j == 0) ? 0 : ((j / 8) + 1)); if (ret->length < len + 4) { unsigned char *new_data = OPENSSL_realloc (ret->data, len + 4); if (!new_data) { ASN1err (ASN1_F_BN_TO_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); goto err; } ret->data = new_data; } ret->length = BN_bn2bin (bn, ret->data); /* Correct zero case */ if (!ret->length) { ret->data[0] = 0; ret->length = 1; } return (ret); err: if (ret != ai) M_ASN1_INTEGER_free (ret); return (NULL); }
static void CheckSerial(X509 *x509) { ASN1_INTEGER *serial = X509_get_serialNumber(x509); BIGNUM *bn_serial = ASN1_INTEGER_to_BN(serial, NULL); if (BN_is_negative(bn_serial) || BN_is_zero(bn_serial)) { SetError(ERR_SERIAL_NOT_POSITIVE); } if (serial->length > 20) { SetError(ERR_SERIAL_TOO_LARGE); } CheckASN1_integer(serial); BN_free(bn_serial); }
static void set_scale(void) { struct number *n; u_long scale; n = pop_number(); if (n != NULL) { if (BN_is_negative(n->number)) warnx("scale must be a nonnegative number"); else { scale = get_ulong(n); if (scale != ULONG_MAX && scale <= UINT_MAX) bmachine.scale = (u_int)scale; else warnx("scale too large"); } free_number(n); } }
void print_ascii(FILE *f, const struct number *n) { BIGNUM *v; int numbits, i, ch; v = BN_dup(n->number); bn_checkp(v); if (BN_is_negative(v)) BN_set_negative(v, 0); numbits = BN_num_bytes(v) * 8; while (numbits > 0) { ch = 0; for (i = 0; i < 8; i++) ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i); putc(ch, f); numbits -= 8; } BN_free(v); }
static int stackint(GPtrArray *stack, int index) { struct buffer *buf = stacktop(stack, index); BIGNUM bn; BN_init(&bn); int ret = -1; if (!CastToBigNum(&bn, buf)) goto out; if (!BN_is_negative(&bn)) ret = BN_get_word(&bn); else { BN_set_negative(&bn, 0); ret = BN_get_word(&bn); ret = -ret; } out: BN_clear_free(&bn); return ret; }
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1, i; BN_CTX *ctx; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; const EC_GROUP *group; const EC_POINT *pub_key; /* check input values */ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); return -1; } ctx = BN_CTX_new(); if (!ctx) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); return -1; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (!X) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* digest -> m */ i = BN_num_bits(order); /* Need to truncate digest if it is too long: first truncate whole * bytes. */ if (8 * dgst_len > i) dgst_len = (i + 7)/8; if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* If still too long truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if ((point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(u1, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (point) EC_POINT_free(point); return ret; }
static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { BIGNUM *r1,*m1,*vrfy; BIGNUM local_dmp1, local_dmq1; BIGNUM *dmp1, *dmq1; int ret=0; BN_CTX_start(ctx); r1 = BN_CTX_get(ctx); m1 = BN_CTX_get(ctx); vrfy = BN_CTX_get(ctx); MONT_HELPER(rsa, ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err); MONT_HELPER(rsa, ctx, q, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err); MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); if (!BN_mod(r1,I,rsa->q,ctx)) goto err; if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME)) { dmq1 = &local_dmq1; BN_with_flags(dmq1, rsa->dmq1, BN_FLG_EXP_CONSTTIME); } else dmq1 = rsa->dmq1; if (!rsa->meth->bn_mod_exp(m1,r1,dmq1,rsa->q,ctx, rsa->_method_mod_q)) goto err; if (!BN_mod(r1,I,rsa->p,ctx)) goto err; if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME)) { dmp1 = &local_dmp1; BN_with_flags(dmp1, rsa->dmp1, BN_FLG_EXP_CONSTTIME); } else dmp1 = rsa->dmp1; if (!rsa->meth->bn_mod_exp(r0,r1,dmp1,rsa->p,ctx, rsa->_method_mod_p)) goto err; if (!BN_sub(r0,r0,m1)) goto err; /* This will help stop the size of r0 increasing, which does * affect the multiply if it optimised for a power of 2 size */ if (BN_is_negative(r0)) if (!BN_add(r0,r0,rsa->p)) goto err; if (!BN_mul(r1,r0,rsa->iqmp,ctx)) goto err; if (!BN_mod(r0,r1,rsa->p,ctx)) goto err; /* If p < q it is occasionally possible for the correction of * adding 'p' if r0 is negative above to leave the result still * negative. This can break the private key operations: the following * second correction should *always* correct this rare occurrence. * This will *never* happen with OpenSSL generated keys because * they ensure p > q [steve] */ if (BN_is_negative(r0)) if (!BN_add(r0,r0,rsa->p)) goto err; if (!BN_mul(r1,r0,rsa->q,ctx)) goto err; if (!BN_add(r0,r1,m1)) goto err; if (rsa->e && rsa->n) { if (!rsa->meth->bn_mod_exp(vrfy,r0,rsa->e,rsa->n,ctx,rsa->_method_mod_n)) goto err; /* If 'I' was greater than (or equal to) rsa->n, the operation * will be equivalent to using 'I mod n'. However, the result of * the verify will *always* be less than 'n' so we don't check * for absolute equality, just congruency. */ if (!BN_sub(vrfy, vrfy, I)) goto err; if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) goto err; if (BN_is_negative(vrfy)) if (!BN_add(vrfy, vrfy, rsa->n)) goto err; if (!BN_is_zero(vrfy)) { /* 'I' and 'vrfy' aren't congruent mod n. Don't leak * miscalculated CRT output, just do a raw (slower) * mod_exp and return that instead. */ BIGNUM local_d; BIGNUM *d = NULL; if (!(rsa->flags & RSA_FLAG_NO_EXP_CONSTTIME)) { d = &local_d; BN_with_flags(d, rsa->d, BN_FLG_EXP_CONSTTIME); } else d = rsa->d; if (!rsa->meth->bn_mod_exp(r0,I,d,rsa->n,ctx, rsa->_method_mod_n)) goto err; } } ret=1; err: BN_CTX_end(ctx); return(ret); }
int DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes) { BIGNUM *bn = NULL, *sum = NULL; int ret = 0; *codes = 0; /** * Checks that the function performs are: * - pub_key is not negative */ if (BN_is_negative(pub_key)) goto out; /** * - pub_key > 1 and pub_key < p - 1, * to avoid small subgroups attack. */ bn = BN_new(); if (bn == NULL) goto out; if (!BN_set_word(bn, 1)) goto out; if (BN_cmp(bn, pub_key) >= 0) *codes |= DH_CHECK_PUBKEY_TOO_SMALL; sum = BN_new(); if (sum == NULL) goto out; BN_uadd(sum, pub_key, bn); if (BN_cmp(sum, dh->p) >= 0) *codes |= DH_CHECK_PUBKEY_TOO_LARGE; /** * - if g == 2, pub_key have more then one bit set, * if bits set is 1, log_2(pub_key) is trival */ if (!BN_set_word(bn, 2)) goto out; if (BN_cmp(bn, dh->g) == 0) { unsigned i, n = BN_num_bits(pub_key); unsigned bits = 0; for (i = 0; i <= n; i++) if (BN_is_bit_set(pub_key, i)) bits++; if (bits < 2) { *codes |= DH_CHECK_PUBKEY_TOO_SMALL; goto out; } } ret = 1; out: if (bn) BN_free(bn); if (sum) BN_free(sum); return ret; }
static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { assert(ctx != NULL); assert(rsa->n != NULL); assert(rsa->e != NULL); assert(rsa->d != NULL); assert(rsa->p != NULL); assert(rsa->q != NULL); assert(rsa->dmp1 != NULL); assert(rsa->dmq1 != NULL); assert(rsa->iqmp != NULL); BIGNUM *r1, *m1, *vrfy; BIGNUM local_dmp1, local_dmq1, local_c, local_r1; BIGNUM *dmp1, *dmq1, *c, *pr1; int ret = 0; size_t i, num_additional_primes = 0; if (rsa->additional_primes != NULL) { num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes); } BN_CTX_start(ctx); r1 = BN_CTX_get(ctx); m1 = BN_CTX_get(ctx); vrfy = BN_CTX_get(ctx); if (r1 == NULL || m1 == NULL || vrfy == NULL) { goto err; } { BIGNUM local_p, local_q; BIGNUM *p = NULL, *q = NULL; /* Make sure BN_mod in Montgomery initialization uses BN_FLG_CONSTTIME. */ BN_init(&local_p); p = &local_p; BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); BN_init(&local_q); q = &local_q; BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME); if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) || !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx)) { goto err; } } if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) { goto err; } /* compute I mod q */ c = &local_c; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->q, ctx)) { goto err; } /* compute r1^dmq1 mod q */ dmq1 = &local_dmq1; BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) { goto err; } /* compute I mod p */ c = &local_c; BN_with_flags(c, I, BN_FLG_CONSTTIME); if (!BN_mod(r1, c, rsa->p, ctx)) { goto err; } /* compute r1^dmp1 mod p */ dmp1 = &local_dmp1; BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) { goto err; } if (!BN_sub(r0, r0, m1)) { goto err; } /* This will help stop the size of r0 increasing, which does * affect the multiply if it optimised for a power of 2 size */ if (BN_is_negative(r0)) { if (!BN_add(r0, r0, rsa->p)) { goto err; } } if (!BN_mul(r1, r0, rsa->iqmp, ctx)) { goto err; } /* Turn BN_FLG_CONSTTIME flag on before division operation */ pr1 = &local_r1; BN_with_flags(pr1, r1, BN_FLG_CONSTTIME); if (!BN_mod(r0, pr1, rsa->p, ctx)) { goto err; } /* If p < q it is occasionally possible for the correction of * adding 'p' if r0 is negative above to leave the result still * negative. This can break the private key operations: the following * second correction should *always* correct this rare occurrence. * This will *never* happen with OpenSSL generated keys because * they ensure p > q [steve] */ if (BN_is_negative(r0)) { if (!BN_add(r0, r0, rsa->p)) { goto err; } } if (!BN_mul(r1, r0, rsa->q, ctx)) { goto err; } if (!BN_add(r0, r1, m1)) { goto err; } for (i = 0; i < num_additional_primes; i++) { /* multi-prime RSA. */ BIGNUM local_exp, local_prime; BIGNUM *exp = &local_exp, *prime = &local_prime; RSA_additional_prime *ap = sk_RSA_additional_prime_value(rsa->additional_primes, i); BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME); BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME); /* c will already point to a BIGNUM with the correct flags. */ if (!BN_mod(r1, c, prime, ctx)) { goto err; } if (!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx) || !BN_mod_exp_mont_consttime(m1, r1, exp, prime, ctx, ap->mont)) { goto err; } BN_set_flags(m1, BN_FLG_CONSTTIME); if (!BN_sub(m1, m1, r0) || !BN_mul(m1, m1, ap->coeff, ctx) || !BN_mod(m1, m1, prime, ctx) || (BN_is_negative(m1) && !BN_add(m1, m1, prime)) || !BN_mul(m1, m1, ap->r, ctx) || !BN_add(r0, r0, m1)) { goto err; } } ret = 1; err: BN_CTX_end(ctx); return ret; }