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; }
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) { /* * If a is only one word long and constant time is false, use the faster * exponenentiation function. */ if (bn_get_top(a) == 1 && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0)) { BN_ULONG A = bn_get_words(a)[0]; return BN_mod_exp_mont_word(r, A, p, m, ctx, m_ctx); } else return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); }
int RSA_memory_lock(RSA *r) { int i, j, k, off; char *p; BIGNUM *bn, **t[6], *b; BN_ULONG *ul; if (r->d == NULL) return (1); t[0] = &r->d; t[1] = &r->p; t[2] = &r->q; t[3] = &r->dmp1; t[4] = &r->dmq1; t[5] = &r->iqmp; k = bn_sizeof_BIGNUM() * 6; off = k / sizeof(BN_ULONG) + 1; j = 1; for (i = 0; i < 6; i++) j += bn_get_top(*t[i]); if ((p = OPENSSL_malloc((off + j) * sizeof(*p))) == NULL) { RSAerr(RSA_F_RSA_MEMORY_LOCK, ERR_R_MALLOC_FAILURE); return (0); } memset(p, 0, sizeof(*p) * (off + j)); bn = (BIGNUM *)p; ul = (BN_ULONG *)&(p[off]); for (i = 0; i < 6; i++) { b = *(t[i]); *(t[i]) = bn_array_el(bn, i); memcpy(bn_array_el(bn, i), b, bn_sizeof_BIGNUM()); memcpy(ul, bn_get_words(b), sizeof(*ul) * bn_get_top(b)); bn_set_static_words(bn_array_el(bn, i), ul, bn_get_top(b)); ul += bn_get_top(b); BN_clear_free(b); } /* I should fix this so it can still be done */ r->flags &= ~(RSA_FLAG_CACHE_PRIVATE | RSA_FLAG_CACHE_PUBLIC); r->bignum_data = p; return (1); }
/* signature verification */ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { BIGNUM *f, *ret; int i, num = 0, r = -1; unsigned char *p; unsigned char *buf = NULL; BN_CTX *ctx = NULL; if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE); return -1; } if (BN_ucmp(rsa->n, rsa->e) <= 0) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE); return -1; } /* for large moduli, enforce exponent limit */ if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) { if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE); return -1; } } if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); f = BN_CTX_get(ctx); ret = BN_CTX_get(ctx); num = BN_num_bytes(rsa->n); buf = OPENSSL_malloc(num); if (ret == NULL || buf == NULL) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, ERR_R_MALLOC_FAILURE); goto err; } /* * This check was for equality but PGP does evil things and chops off the * top '0' bytes */ if (flen > num) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN); goto err; } if (BN_bin2bn(from, flen, f) == NULL) goto err; if (BN_ucmp(f, rsa->n) >= 0) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) if (!BN_MONT_CTX_set_locked (&rsa->_method_mod_n, rsa->lock, rsa->n, ctx)) goto err; if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx, rsa->_method_mod_n)) goto err; if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret)[0] & 0xf) != 12)) if (!BN_sub(ret, rsa->n, ret)) goto err; p = buf; i = BN_bn2bin(ret, p); switch (padding) { case RSA_PKCS1_PADDING: r = RSA_padding_check_PKCS1_type_1(to, num, buf, i, num); break; case RSA_X931_PADDING: r = RSA_padding_check_X931(to, num, buf, i, num); break; case RSA_NO_PADDING: r = RSA_padding_check_none(to, num, buf, i, num); break; default: RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (r < 0) RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED); err: if (ctx != NULL) BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_clear_free(buf, num); return r; }
/* Computes scalar*point and stores the result in r. * point can not equal r. * Uses a modified algorithm 2P of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * * To protect against side-channel attack the function uses constant time swap, * avoiding conditional branches. */ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx) { BIGNUM *x1, *x2, *z1, *z2; int ret = 0, i; BN_ULONG mask,word; if (r == point) { ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT); return 0; } /* if result should be point at infinity */ if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || EC_POINT_is_at_infinity(group, point)) { return EC_POINT_set_to_infinity(group, r); } /* only support affine coordinates */ if (!point->Z_is_one) return 0; /* Since point_multiply is static we can guarantee that ctx != NULL. */ BN_CTX_start(ctx); x1 = BN_CTX_get(ctx); z1 = BN_CTX_get(ctx); if (z1 == NULL) goto err; x2 = r->X; z2 = r->Y; bn_wexpand(x1, bn_get_top(group->field)); bn_wexpand(z1, bn_get_top(group->field)); bn_wexpand(x2, bn_get_top(group->field)); bn_wexpand(z2, bn_get_top(group->field)); if (!BN_GF2m_mod_arr(x1, point->X, group->poly)) goto err; /* x1 = x */ if (!BN_one(z1)) goto err; /* z1 = 1 */ if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */ if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err; if (!BN_GF2m_add(x2, x2, group->b)) goto err; /* x2 = x^4 + b */ /* find top most bit and go one past it */ i = bn_get_top(scalar) - 1; mask = BN_TBIT; word = bn_get_words(scalar)[i]; while (!(word & mask)) mask >>= 1; mask >>= 1; /* if top most bit was at word break, go to next word */ if (!mask) { i--; mask = BN_TBIT; } for (; i >= 0; i--) { word = bn_get_words(scalar)[i]; while (mask) { BN_consttime_swap(word & mask, x1, x2, bn_get_top(group->field)); BN_consttime_swap(word & mask, z1, z2, bn_get_top(group->field)); if (!gf2m_Madd(group, point->X, x2, z2, x1, z1, ctx)) goto err; if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; BN_consttime_swap(word & mask, x1, x2, bn_get_top(group->field)); BN_consttime_swap(word & mask, z1, z2, bn_get_top(group->field)); mask >>= 1; } mask = BN_TBIT; } /* convert out of "projective" coordinates */ i = gf2m_Mxy(group, point->X, point->Y, x1, z1, x2, z2, ctx); if (i == 0) goto err; else if (i == 1) { if (!EC_POINT_set_to_infinity(group, r)) goto err; } else { if (!BN_one(r->Z)) goto err; r->Z_is_one = 1; } /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ BN_set_negative(r->X, 0); BN_set_negative(r->Y, 0); ret = 1; err: BN_CTX_end(ctx); return ret; }
BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) { BIGNUM *local_n = NULL; BIGNUM *e, *n; BN_CTX *ctx; BN_BLINDING *ret = NULL; if (in_ctx == NULL) { if ((ctx = BN_CTX_new()) == NULL) return 0; } else ctx = in_ctx; BN_CTX_start(ctx); e = BN_CTX_get(ctx); if (e == NULL) { RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE); goto err; } if (rsa->e == NULL) { e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx); if (e == NULL) { RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT); goto err; } } else e = rsa->e; if ((RAND_status() == 0) && rsa->d != NULL && bn_get_words(rsa->d) != NULL) { /* * if PRNG is not properly seeded, resort to secret exponent as * unpredictable seed */ RAND_add(bn_get_words(rsa->d), bn_get_dmax(rsa->d) * sizeof(BN_ULONG), 0.0); } if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { /* Set BN_FLG_CONSTTIME flag */ local_n = n = BN_new(); if (!local_n) { RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE); goto err; } BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME); } else n = rsa->n; ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp, rsa->_method_mod_n); if (ret == NULL) { RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB); goto err; } CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret)); err: BN_CTX_end(ctx); if (in_ctx == NULL) BN_CTX_free(ctx); if (rsa->e == NULL) BN_free(e); if (local_n) BN_free(local_n); return ret; }