aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ipsec/ikev2_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ipsec/ikev2_crypto.c')
-rw-r--r--src/vnet/ipsec/ikev2_crypto.c149
1 files changed, 129 insertions, 20 deletions
diff --git a/src/vnet/ipsec/ikev2_crypto.c b/src/vnet/ipsec/ikev2_crypto.c
index 32927629c5e..c201d3eb41f 100644
--- a/src/vnet/ipsec/ikev2_crypto.c
+++ b/src/vnet/ipsec/ikev2_crypto.c
@@ -343,6 +343,7 @@ ikev2_decrypt_data (ikev2_sa_t * sa, u8 * data, int len)
v8 *r;
int out_len = 0, block_size;
ikev2_sa_transform_t *tr_encr;
+ u8 *key = sa->is_initiator ? sa->sk_er : sa->sk_ei;
tr_encr =
ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
@@ -357,7 +358,7 @@ ikev2_decrypt_data (ikev2_sa_t * sa, u8 * data, int len)
EVP_CIPHER_CTX_init (&ctx);
r = vec_new (u8, len - block_size);
- EVP_DecryptInit_ex (&ctx, tr_encr->cipher, NULL, sa->sk_ei, data);
+ EVP_DecryptInit_ex (&ctx, tr_encr->cipher, NULL, key, data);
EVP_DecryptUpdate (&ctx, r, &out_len, data + block_size, len - block_size);
EVP_DecryptFinal_ex (&ctx, r + out_len, &out_len);
@@ -375,6 +376,7 @@ ikev2_encrypt_data (ikev2_sa_t * sa, v8 * src, u8 * dst)
int out_len;
int bs;
ikev2_sa_transform_t *tr_encr;
+ u8 *key = sa->is_initiator ? sa->sk_ei : sa->sk_er;
tr_encr =
ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
@@ -385,7 +387,7 @@ ikev2_encrypt_data (ikev2_sa_t * sa, v8 * src, u8 * dst)
EVP_CIPHER_CTX_init (&ctx);
- EVP_EncryptInit_ex (&ctx, tr_encr->cipher, NULL, sa->sk_er, dst /* dst */ );
+ EVP_EncryptInit_ex (&ctx, tr_encr->cipher, NULL, key, dst /* dst */ );
EVP_EncryptUpdate (&ctx, dst + bs, &out_len, src, vec_len (src));
EVP_CIPHER_CTX_cleanup (&ctx);
@@ -407,16 +409,29 @@ ikev2_generate_dh (ikev2_sa_t * sa, ikev2_sa_transform_t * t)
BN_hex2bn (&dh->g, t->dh_g);
DH_generate_key (dh);
- sa->r_dh_data = vec_new (u8, t->key_len);
- r = BN_bn2bin (dh->pub_key, sa->r_dh_data);
- ASSERT (r == t->key_len);
+ if (sa->is_initiator)
+ {
+ sa->i_dh_data = vec_new (u8, t->key_len);
+ r = BN_bn2bin (dh->pub_key, sa->i_dh_data);
+ ASSERT (r == t->key_len);
- BIGNUM *ex;
- sa->dh_shared_key = vec_new (u8, t->key_len);
- ex = BN_bin2bn (sa->i_dh_data, vec_len (sa->i_dh_data), NULL);
- r = DH_compute_key (sa->dh_shared_key, ex, dh);
- ASSERT (r == t->key_len);
- BN_clear_free (ex);
+ sa->dh_private_key = vec_new (u8, t->key_len);
+ r = BN_bn2bin (dh->priv_key, sa->dh_private_key);
+ ASSERT (r == t->key_len);
+
+ }
+ else
+ {
+ sa->r_dh_data = vec_new (u8, t->key_len);
+ r = BN_bn2bin (dh->pub_key, sa->r_dh_data);
+ ASSERT (r == t->key_len);
+ BIGNUM *ex;
+ sa->dh_shared_key = vec_new (u8, t->key_len);
+ ex = BN_bin2bn (sa->i_dh_data, vec_len (sa->i_dh_data), NULL);
+ r = DH_compute_key (sa->dh_shared_key, ex, dh);
+ ASSERT (r == t->key_len);
+ BN_clear_free (ex);
+ }
DH_free (dh);
}
else if (t->dh_group == IKEV2_DH_GROUP_ECP)
@@ -439,21 +454,113 @@ ikev2_generate_dh (ikev2_sa_t * sa, ikev2_sa_transform_t * t)
len = t->key_len / 2;
EC_POINT_get_affine_coordinates_GFp (group, r_point, x, y, bn_ctx);
- sa->r_dh_data = vec_new (u8, t->key_len);
- x_off = len - BN_num_bytes (x);
- memset (sa->r_dh_data, 0, x_off);
- BN_bn2bin (x, sa->r_dh_data + x_off);
- y_off = t->key_len - BN_num_bytes (y);
- memset (sa->r_dh_data + len, 0, y_off - len);
- BN_bn2bin (y, sa->r_dh_data + y_off);
+
+ if (sa->is_initiator)
+ {
+ sa->i_dh_data = vec_new (u8, t->key_len);
+ x_off = len - BN_num_bytes (x);
+ memset (sa->i_dh_data, 0, x_off);
+ BN_bn2bin (x, sa->i_dh_data + x_off);
+ y_off = t->key_len - BN_num_bytes (y);
+ memset (sa->i_dh_data + len, 0, y_off - len);
+ BN_bn2bin (y, sa->i_dh_data + y_off);
+
+ const BIGNUM *prv = EC_KEY_get0_private_key (ec);
+ sa->dh_private_key = vec_new (u8, BN_num_bytes (prv));
+ r = BN_bn2bin (prv, sa->dh_private_key);
+ ASSERT (r == BN_num_bytes (prv));
+ }
+ else
+ {
+ sa->r_dh_data = vec_new (u8, t->key_len);
+ x_off = len - BN_num_bytes (x);
+ memset (sa->r_dh_data, 0, x_off);
+ BN_bn2bin (x, sa->r_dh_data + x_off);
+ y_off = t->key_len - BN_num_bytes (y);
+ memset (sa->r_dh_data + len, 0, y_off - len);
+ BN_bn2bin (y, sa->r_dh_data + y_off);
+
+ x = BN_bin2bn (sa->i_dh_data, len, x);
+ y = BN_bin2bn (sa->i_dh_data + len, len, y);
+ EC_POINT_set_affine_coordinates_GFp (group, i_point, x, y, bn_ctx);
+ sa->dh_shared_key = vec_new (u8, t->key_len);
+ EC_POINT_mul (group, shared_point, NULL, i_point,
+ EC_KEY_get0_private_key (ec), NULL);
+ EC_POINT_get_affine_coordinates_GFp (group, shared_point, x, y,
+ bn_ctx);
+ x_off = len - BN_num_bytes (x);
+ memset (sa->dh_shared_key, 0, x_off);
+ BN_bn2bin (x, sa->dh_shared_key + x_off);
+ y_off = t->key_len - BN_num_bytes (y);
+ memset (sa->dh_shared_key + len, 0, y_off - len);
+ BN_bn2bin (y, sa->dh_shared_key + y_off);
+ }
+
+ EC_KEY_free (ec);
+ BN_free (x);
+ BN_free (y);
+ BN_CTX_free (bn_ctx);
+ EC_POINT_free (i_point);
+ EC_POINT_free (shared_point);
+ }
+}
+
+void
+ikev2_complete_dh (ikev2_sa_t * sa, ikev2_sa_transform_t * t)
+{
+ int r;
+
+ if (t->dh_group == IKEV2_DH_GROUP_MODP)
+ {
+ DH *dh = DH_new ();
+ BN_hex2bn (&dh->p, t->dh_p);
+ BN_hex2bn (&dh->g, t->dh_g);
+ dh->priv_key =
+ BN_bin2bn (sa->dh_private_key, vec_len (sa->dh_private_key), NULL);
+
+ BIGNUM *ex;
+ sa->dh_shared_key = vec_new (u8, t->key_len);
+ ex = BN_bin2bn (sa->r_dh_data, vec_len (sa->r_dh_data), NULL);
+ r = DH_compute_key (sa->dh_shared_key, ex, dh);
+ ASSERT (r == t->key_len);
+ BN_clear_free (ex);
+ DH_free (dh);
+ }
+ else if (t->dh_group == IKEV2_DH_GROUP_ECP)
+ {
+ EC_KEY *ec = EC_KEY_new_by_curve_name (t->nid);
+ ASSERT (ec);
+
+ const EC_GROUP *group = EC_KEY_get0_group (ec);
+ BIGNUM *x = NULL, *y = NULL;
+ BN_CTX *bn_ctx = BN_CTX_new ();
+ u16 x_off, y_off, len;
+ BIGNUM *prv;
+
+ prv =
+ BN_bin2bn (sa->dh_private_key, vec_len (sa->dh_private_key), NULL);
+ EC_KEY_set_private_key (ec, prv);
+
+ x = BN_new ();
+ y = BN_new ();
+ len = t->key_len / 2;
+
+ x = BN_bin2bn (sa->r_dh_data, len, x);
+ y = BN_bin2bn (sa->r_dh_data + len, len, y);
+ EC_POINT *r_point = EC_POINT_new (group);
+ EC_POINT_set_affine_coordinates_GFp (group, r_point, x, y, bn_ctx);
+ EC_KEY_set_public_key (ec, r_point);
+
+ EC_POINT *i_point = EC_POINT_new (group);
+ EC_POINT *shared_point = EC_POINT_new (group);
x = BN_bin2bn (sa->i_dh_data, len, x);
y = BN_bin2bn (sa->i_dh_data + len, len, y);
EC_POINT_set_affine_coordinates_GFp (group, i_point, x, y, bn_ctx);
- sa->dh_shared_key = vec_new (u8, t->key_len);
- EC_POINT_mul (group, shared_point, NULL, i_point,
+ EC_POINT_mul (group, shared_point, NULL, r_point,
EC_KEY_get0_private_key (ec), NULL);
EC_POINT_get_affine_coordinates_GFp (group, shared_point, x, y, bn_ctx);
+ sa->dh_shared_key = vec_new (u8, t->key_len);
x_off = len - BN_num_bytes (x);
memset (sa->dh_shared_key, 0, x_off);
BN_bn2bin (x, sa->dh_shared_key + x_off);
@@ -464,8 +571,10 @@ ikev2_generate_dh (ikev2_sa_t * sa, ikev2_sa_transform_t * t)
EC_KEY_free (ec);
BN_free (x);
BN_free (y);
+ BN_free (prv);
BN_CTX_free (bn_ctx);
EC_POINT_free (i_point);
+ EC_POINT_free (r_point);
EC_POINT_free (shared_point);
}
}