|
@@ -94,11 +94,6 @@
|
|
|
|
|
|
#define MAX_STRONGEST_RAND_SIZE 256
|
|
|
|
|
|
-
|
|
|
-#define PUBLIC_KEY_OK(k) ((k) && (k)->key && (k)->key->n)
|
|
|
-
|
|
|
-#define PRIVATE_KEY_OK(k) ((k) && (k)->key && (k)->key->p)
|
|
|
-
|
|
|
#ifndef NEW_THREAD_API
|
|
|
|
|
|
static tor_mutex_t **openssl_mutexes_ = NULL;
|
|
@@ -440,6 +435,24 @@ crypto_thread_cleanup(void)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * Return 1 iff the public key is valid, 0 if obviously invalid.
|
|
|
+ */
|
|
|
+static int
|
|
|
+crypto_pk_private_ok(const crypto_pk_t *k)
|
|
|
+{
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+ if (!k || !k->key)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ BIGNUM *p, *q;
|
|
|
+ RSA_get0_factors(k->key, &p, &q);
|
|
|
+ return p != NULL;
|
|
|
+#else
|
|
|
+ return k && k->key && k->key->p;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
crypto_pk_t *
|
|
|
crypto_new_pk_from_rsa_(RSA *rsa)
|
|
@@ -802,7 +815,7 @@ crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
|
|
|
char *s;
|
|
|
int r;
|
|
|
|
|
|
- tor_assert(PRIVATE_KEY_OK(env));
|
|
|
+ tor_assert(crypto_pk_private_ok(env));
|
|
|
|
|
|
if (!(bio = BIO_new(BIO_s_mem())))
|
|
|
return -1;
|
|
@@ -844,7 +857,7 @@ int
|
|
|
crypto_pk_key_is_private(const crypto_pk_t *key)
|
|
|
{
|
|
|
tor_assert(key);
|
|
|
- return PRIVATE_KEY_OK(key);
|
|
|
+ return crypto_pk_private_ok(key);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -856,7 +869,15 @@ crypto_pk_public_exponent_ok(crypto_pk_t *env)
|
|
|
tor_assert(env);
|
|
|
tor_assert(env->key);
|
|
|
|
|
|
- return BN_is_word(env->key->e, 65537);
|
|
|
+ BIGNUM *e;
|
|
|
+
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+ BIGNUM *n, *d;
|
|
|
+ RSA_get0_key(env->key, &n, &e, &d);
|
|
|
+#else
|
|
|
+ e = env->key->e;
|
|
|
+#endif
|
|
|
+ return BN_is_word(e, 65537);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -877,12 +898,27 @@ crypto_pk_cmp_keys(const crypto_pk_t *a, const crypto_pk_t *b)
|
|
|
if (an_argument_is_null)
|
|
|
return result;
|
|
|
|
|
|
- tor_assert(PUBLIC_KEY_OK(a));
|
|
|
- tor_assert(PUBLIC_KEY_OK(b));
|
|
|
- result = BN_cmp((a->key)->n, (b->key)->n);
|
|
|
+ BIGNUM *a_n, *a_e;
|
|
|
+ BIGNUM *b_n, *b_e;
|
|
|
+
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+ BIGNUM *a_d, *b_d;
|
|
|
+ RSA_get0_key(a->key, &a_n, &a_e, &a_d);
|
|
|
+ RSA_get0_key(b->key, &b_n, &b_e, &b_d);
|
|
|
+#else
|
|
|
+ a_n = a->key->n;
|
|
|
+ a_e = a->key->e;
|
|
|
+ b_n = b->key->n;
|
|
|
+ b_e = b->key->e;
|
|
|
+#endif
|
|
|
+
|
|
|
+ tor_assert(a_n != NULL && a_e != NULL);
|
|
|
+ tor_assert(b_n != NULL && b_e != NULL);
|
|
|
+
|
|
|
+ result = BN_cmp(a_n, b_n);
|
|
|
if (result)
|
|
|
return result;
|
|
|
- return BN_cmp((a->key)->e, (b->key)->e);
|
|
|
+ return BN_cmp(a_e, b_e);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -913,9 +949,20 @@ crypto_pk_num_bits(crypto_pk_t *env)
|
|
|
{
|
|
|
tor_assert(env);
|
|
|
tor_assert(env->key);
|
|
|
- tor_assert(env->key->n);
|
|
|
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+
|
|
|
+ * before calling RSA_bits().
|
|
|
+ */
|
|
|
+ BIGNUM *n, *e, *d;
|
|
|
+ RSA_get0_key(env->key, &n, &e, &d);
|
|
|
+ tor_assert(n != NULL);
|
|
|
+
|
|
|
+ return RSA_bits(env->key);
|
|
|
+#else
|
|
|
+ tor_assert(env->key->n);
|
|
|
return BN_num_bits(env->key->n);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
|
|
@@ -940,7 +987,7 @@ crypto_pk_copy_full(crypto_pk_t *env)
|
|
|
tor_assert(env);
|
|
|
tor_assert(env->key);
|
|
|
|
|
|
- if (PRIVATE_KEY_OK(env)) {
|
|
|
+ if (crypto_pk_private_ok(env)) {
|
|
|
new_key = RSAPrivateKey_dup(env->key);
|
|
|
privatekey = 1;
|
|
|
} else {
|
|
@@ -1009,7 +1056,7 @@ crypto_pk_private_decrypt(crypto_pk_t *env, char *to,
|
|
|
tor_assert(env->key);
|
|
|
tor_assert(fromlen<INT_MAX);
|
|
|
tor_assert(tolen >= crypto_pk_keysize(env));
|
|
|
- if (!env->key->p)
|
|
|
+ if (!crypto_pk_key_is_private(env))
|
|
|
|
|
|
return -1;
|
|
|
|
|
@@ -1115,7 +1162,7 @@ crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
|
|
|
tor_assert(to);
|
|
|
tor_assert(fromlen < INT_MAX);
|
|
|
tor_assert(tolen >= crypto_pk_keysize(env));
|
|
|
- if (!env->key->p)
|
|
|
+ if (!crypto_pk_key_is_private(env))
|
|
|
|
|
|
return -1;
|
|
|
|
|
@@ -2108,25 +2155,35 @@ crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
|
|
|
DH *dh = NULL;
|
|
|
int ret = -1;
|
|
|
|
|
|
-
|
|
|
+
|
|
|
if (!(dh = DH_new()))
|
|
|
goto out;
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+ BIGNUM *dh_p, *dh_g;
|
|
|
+ if (!(dh_p = BN_dup(p)))
|
|
|
+ goto out;
|
|
|
+ if (!(dh_g = BN_dup(g)))
|
|
|
+ goto out;
|
|
|
+ if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
|
|
|
+ goto out;
|
|
|
+#else
|
|
|
if (!(dh->p = BN_dup(p)))
|
|
|
goto out;
|
|
|
if (!(dh->g = BN_dup(g)))
|
|
|
goto out;
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
int codes = 0;
|
|
|
if (!DH_check(dh, &codes))
|
|
|
goto out;
|
|
|
- if (BN_is_word(dh->g, DH_GENERATOR_2)) {
|
|
|
+ if (BN_is_word(g, DH_GENERATOR_2)) {
|
|
|
|
|
|
*
|
|
|
* OpenSSL checks the prime is congruent to 11 when g = 2; while the
|
|
|
* IETF's primes are congruent to 23 when g = 2.
|
|
|
*/
|
|
|
- BN_ULONG residue = BN_mod_word(dh->p, 24);
|
|
|
+ BN_ULONG residue = BN_mod_word(p, 24);
|
|
|
if (residue == 11 || residue == 23)
|
|
|
codes &= ~DH_NOT_SUITABLE_GENERATOR;
|
|
|
}
|
|
@@ -2257,6 +2314,30 @@ crypto_dh_new(int dh_type)
|
|
|
if (!(res->dh = DH_new()))
|
|
|
goto err;
|
|
|
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+ BIGNUM *dh_p = NULL, *dh_g = NULL;
|
|
|
+
|
|
|
+ if (dh_type == DH_TYPE_TLS) {
|
|
|
+ dh_p = BN_dup(dh_param_p_tls);
|
|
|
+ } else {
|
|
|
+ dh_p = BN_dup(dh_param_p);
|
|
|
+ }
|
|
|
+ if (!dh_p)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ dh_g = BN_dup(dh_param_g);
|
|
|
+ if (!dh_g) {
|
|
|
+ BN_free(dh_p);
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!DH_set0_pqg(res->dh, dh_p, NULL, dh_g)) {
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!DH_set_length(res->dh, DH_PRIVATE_KEY_BITS))
|
|
|
+ goto err;
|
|
|
+#else
|
|
|
if (dh_type == DH_TYPE_TLS) {
|
|
|
if (!(res->dh->p = BN_dup(dh_param_p_tls)))
|
|
|
goto err;
|
|
@@ -2269,6 +2350,7 @@ crypto_dh_new(int dh_type)
|
|
|
goto err;
|
|
|
|
|
|
res->dh->length = DH_PRIVATE_KEY_BITS;
|
|
|
+#endif
|
|
|
|
|
|
return res;
|
|
|
err:
|
|
@@ -2305,11 +2387,26 @@ crypto_dh_get_bytes(crypto_dh_t *dh)
|
|
|
int
|
|
|
crypto_dh_generate_public(crypto_dh_t *dh)
|
|
|
{
|
|
|
+#ifndef OPENSSL_1_1_API
|
|
|
again:
|
|
|
+#endif
|
|
|
if (!DH_generate_key(dh->dh)) {
|
|
|
crypto_log_errors(LOG_WARN, "generating DH key");
|
|
|
return -1;
|
|
|
}
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+
|
|
|
+ * recreating the DH object. I have no idea what sort of aliasing madness
|
|
|
+ * can occur here, so do the check, and just bail on failure.
|
|
|
+ */
|
|
|
+ BIGNUM *pub_key, *priv_key;
|
|
|
+ DH_get0_key(dh->dh, &pub_key, &priv_key);
|
|
|
+ if (tor_check_dh_key(LOG_WARN, pub_key)<0) {
|
|
|
+ log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
|
|
|
+ "the-universe chances really do happen. Treating as a failure.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+#else
|
|
|
if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) {
|
|
|
log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
|
|
|
"the-universe chances really do happen. Trying again.");
|
|
@@ -2319,6 +2416,7 @@ crypto_dh_generate_public(crypto_dh_t *dh)
|
|
|
dh->dh->pub_key = dh->dh->priv_key = NULL;
|
|
|
goto again;
|
|
|
}
|
|
|
+#endif
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2331,13 +2429,30 @@ crypto_dh_get_public(crypto_dh_t *dh, char *pubkey, size_t pubkey_len)
|
|
|
{
|
|
|
int bytes;
|
|
|
tor_assert(dh);
|
|
|
- if (!dh->dh->pub_key) {
|
|
|
+
|
|
|
+ BIGNUM *dh_pub;
|
|
|
+
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+ BIGNUM *dh_priv;
|
|
|
+ DH_get0_key(dh->dh, &dh_pub, &dh_priv);
|
|
|
+#else
|
|
|
+ dh_pub = dh->dh->pub_key;
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (!dh_pub) {
|
|
|
if (crypto_dh_generate_public(dh)<0)
|
|
|
return -1;
|
|
|
+ else {
|
|
|
+#ifdef OPENSSL_1_1_API
|
|
|
+ DH_get0_key(dh->dh, &dh_pub, &dh_priv);
|
|
|
+#else
|
|
|
+ dh_pub = dh->dh->pub_key;
|
|
|
+#endif
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- tor_assert(dh->dh->pub_key);
|
|
|
- bytes = BN_num_bytes(dh->dh->pub_key);
|
|
|
+ tor_assert(dh_pub);
|
|
|
+ bytes = BN_num_bytes(dh_pub);
|
|
|
tor_assert(bytes >= 0);
|
|
|
if (pubkey_len < (size_t)bytes) {
|
|
|
log_warn(LD_CRYPTO,
|
|
@@ -2347,7 +2462,7 @@ crypto_dh_get_public(crypto_dh_t *dh, char *pubkey, size_t pubkey_len)
|
|
|
}
|
|
|
|
|
|
memset(pubkey, 0, pubkey_len);
|
|
|
- BN_bn2bin(dh->dh->pub_key, (unsigned char*)(pubkey+(pubkey_len-bytes)));
|
|
|
+ BN_bn2bin(dh_pub, (unsigned char*)(pubkey+(pubkey_len-bytes)));
|
|
|
|
|
|
return 0;
|
|
|
}
|