mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Basic diffie-helman wrappers with fixed modulus and tests
svn:r257
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
@@ -644,6 +646,120 @@ int crypto_SHA_digest(unsigned char *m, int len, unsigned char *digest)
|
||||
return (SHA1(m,len,digest) == NULL);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_dh_env_st {
|
||||
DH *dh;
|
||||
};
|
||||
|
||||
static BIGNUM *dh_param_p = NULL;
|
||||
static BIGNUM *dh_param_g = NULL;
|
||||
|
||||
|
||||
static void init_dh_param() {
|
||||
BIGNUM *p, *g;
|
||||
int r;
|
||||
if (dh_param_p && dh_param_g)
|
||||
return;
|
||||
|
||||
p = BN_new();
|
||||
g = BN_new();
|
||||
assert(p && g);
|
||||
|
||||
/* This is from draft-ietf-ipsec-ike-modp-groups-05.txt. It's a safe
|
||||
prime, and supposedly it equals:
|
||||
2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }
|
||||
*/
|
||||
r = BN_hex2bn(&p,
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF");
|
||||
assert(r);
|
||||
|
||||
r = BN_set_word(g, 2);
|
||||
assert(r);
|
||||
dh_param_p = p;
|
||||
dh_param_g = g;
|
||||
}
|
||||
|
||||
crypto_dh_env_t *crypto_dh_new()
|
||||
{
|
||||
crypto_dh_env_t *res = NULL;
|
||||
|
||||
if (!dh_param_p)
|
||||
init_dh_param();
|
||||
|
||||
if (!(res = malloc(sizeof(crypto_dh_env_t))))
|
||||
goto err;
|
||||
res->dh = NULL;
|
||||
|
||||
if (!(res->dh = DH_new()))
|
||||
goto err;
|
||||
|
||||
if (!(res->dh->p = BN_dup(dh_param_p)))
|
||||
goto err;
|
||||
|
||||
if (!(res->dh->g = BN_dup(dh_param_g)))
|
||||
goto err;
|
||||
|
||||
return res;
|
||||
err:
|
||||
if (res && res->dh) DH_free(res->dh); /* frees p and g too */
|
||||
if (res) free(res);
|
||||
return NULL;
|
||||
}
|
||||
int crypto_dh_get_bytes(crypto_dh_env_t *dh)
|
||||
{
|
||||
assert(dh);
|
||||
return DH_size(dh->dh);
|
||||
}
|
||||
int crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey, int pubkey_len)
|
||||
{
|
||||
int bytes;
|
||||
assert(dh);
|
||||
if (!DH_generate_key(dh->dh))
|
||||
return -1;
|
||||
|
||||
assert(dh->dh->pub_key);
|
||||
bytes = BN_num_bytes(dh->dh->pub_key);
|
||||
if (pubkey_len < bytes)
|
||||
return -1;
|
||||
|
||||
memset(pubkey, 0, pubkey_len);
|
||||
BN_bn2bin(dh->dh->pub_key, pubkey+(pubkey_len-bytes));
|
||||
|
||||
return 0;
|
||||
}
|
||||
int crypto_dh_compute_secret(crypto_dh_env_t *dh,
|
||||
char *pubkey, int pubkey_len,
|
||||
char *secret_out)
|
||||
{
|
||||
BIGNUM *pubkey_bn;
|
||||
int secret_len;
|
||||
assert(dh);
|
||||
|
||||
if (!(pubkey_bn = BN_bin2bn(pubkey, pubkey_len, NULL)))
|
||||
return -1;
|
||||
|
||||
secret_len = DH_compute_key(secret_out, pubkey_bn, dh->dh);
|
||||
BN_free(pubkey_bn);
|
||||
if (secret_len == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void crypto_dh_free(crypto_dh_env_t *dh)
|
||||
{
|
||||
assert(dh && dh->dh);
|
||||
DH_free(dh->dh);
|
||||
free(dh);
|
||||
}
|
||||
|
||||
|
||||
/* random numbers */
|
||||
int crypto_rand(unsigned int n, unsigned char *to)
|
||||
{
|
||||
@@ -662,3 +778,4 @@ char *crypto_perror()
|
||||
{
|
||||
return (char *)ERR_reason_error_string(ERR_get_error());
|
||||
}
|
||||
|
||||
|
||||
+13
-1
@@ -64,7 +64,19 @@ int crypto_pk_keysize(crypto_pk_env_t *env);
|
||||
|
||||
int crypto_pk_public_encrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding);
|
||||
int crypto_pk_private_decrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding);
|
||||
|
||||
|
||||
/* Key negotiation */
|
||||
typedef struct crypto_dh_env_st crypto_dh_env_t;
|
||||
#define CRYPTO_DH_SIZE (1536 / 8)
|
||||
crypto_dh_env_t *crypto_dh_new();
|
||||
int crypto_dh_get_bytes(crypto_dh_env_t *dh);
|
||||
int crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey_out,
|
||||
int pubkey_out_len);
|
||||
int crypto_dh_compute_secret(crypto_dh_env_t *dh,
|
||||
char *pubkey, int pubkey_len,
|
||||
char *secret_out);
|
||||
void crypto_dh_free(crypto_dh_env_t *dh);
|
||||
|
||||
/* symmetric crypto */
|
||||
int crypto_cipher_generate_key(crypto_cipher_env_t *env);
|
||||
int crypto_cipher_set_iv(crypto_cipher_env_t *env, unsigned char *iv);
|
||||
|
||||
+35
-1
@@ -229,8 +229,41 @@ test_buffers() {
|
||||
buf_free(buf2);
|
||||
}
|
||||
|
||||
void
|
||||
test_crypto_dh()
|
||||
{
|
||||
crypto_dh_env_t *dh1, *dh2;
|
||||
char p1[CRYPTO_DH_SIZE];
|
||||
char p2[CRYPTO_DH_SIZE];
|
||||
char s1[CRYPTO_DH_SIZE];
|
||||
char s2[CRYPTO_DH_SIZE];
|
||||
|
||||
dh1 = crypto_dh_new();
|
||||
dh2 = crypto_dh_new();
|
||||
test_eq(crypto_dh_get_bytes(dh1), CRYPTO_DH_SIZE);
|
||||
test_eq(crypto_dh_get_bytes(dh2), CRYPTO_DH_SIZE);
|
||||
|
||||
memset(p1, 0, CRYPTO_DH_SIZE);
|
||||
memset(p2, 0, CRYPTO_DH_SIZE);
|
||||
test_memeq(p1, p2, CRYPTO_DH_SIZE);
|
||||
test_assert(! crypto_dh_get_public(dh1, p1, CRYPTO_DH_SIZE));
|
||||
test_memneq(p1, p2, CRYPTO_DH_SIZE);
|
||||
test_assert(! crypto_dh_get_public(dh2, p2, CRYPTO_DH_SIZE));
|
||||
test_memneq(p1, p2, CRYPTO_DH_SIZE);
|
||||
|
||||
memset(s1, 0, CRYPTO_DH_SIZE);
|
||||
memset(s2, 0, CRYPTO_DH_SIZE);
|
||||
test_assert(! crypto_dh_compute_secret(dh1, p2, CRYPTO_DH_SIZE, s1));
|
||||
test_assert(! crypto_dh_compute_secret(dh2, p1, CRYPTO_DH_SIZE, s2));
|
||||
test_memeq(s1, s2, CRYPTO_DH_SIZE);
|
||||
|
||||
crypto_dh_free(dh1);
|
||||
crypto_dh_free(dh2);
|
||||
}
|
||||
|
||||
void
|
||||
test_crypto() {
|
||||
test_crypto()
|
||||
{
|
||||
crypto_cipher_env_t *env1, *env2;
|
||||
crypto_pk_env_t *pk1, *pk2;
|
||||
char *data1, *data2, *data3, *cp;
|
||||
@@ -441,6 +474,7 @@ main(int c, char**v) {
|
||||
puts("========================== Buffers =========================");
|
||||
test_buffers();
|
||||
puts("========================== Crypto ==========================");
|
||||
test_crypto_dh();
|
||||
test_crypto(); /* this seg faults :( */
|
||||
puts("\n========================== Util ============================");
|
||||
test_util();
|
||||
|
||||
Reference in New Issue
Block a user