passing chunks, not prf+, to kernel interface

gives us better control of keymat in CHILD_SA
This commit is contained in:
Martin Willi
2008-10-14 15:17:44 +00:00
parent c25c8dce60
commit e517b4b174
7 changed files with 263 additions and 210 deletions
+6 -7
View File
@@ -85,14 +85,13 @@ static status_t get_cpi(private_kernel_interface_t *this, host_t *src, host_t *d
static status_t add_sa(private_kernel_interface_t *this, host_t *src, host_t *dst, static status_t add_sa(private_kernel_interface_t *this, host_t *src, host_t *dst,
u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard, u_int64_t expire_soft, u_int64_t expire_hard,
u_int16_t enc_alg, u_int16_t enc_size, u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, u_int16_t int_size, u_int16_t int_alg, chunk_t int_key,
prf_plus_t *prf_plus, ipsec_mode_t mode, u_int16_t ipcomp, bool encap, ipsec_mode_t mode, u_int16_t ipcomp, bool encap, bool update)
bool update)
{ {
return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid, return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
expire_soft, expire_hard, enc_alg, enc_size, int_alg, int_size, expire_soft, expire_hard, enc_alg, enc_key, int_alg, int_key,
prf_plus, mode, ipcomp, encap, update); mode, ipcomp, encap, update);
} }
/** /**
@@ -371,7 +370,7 @@ kernel_interface_t *kernel_interface_create()
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.get_cpi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi; this->public.get_cpi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,ipsec_mode_t,u_int16_t,bool,bool))add_sa; this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,bool,bool))add_sa;
this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa; this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa;
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa; this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy; this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy;
+5 -7
View File
@@ -101,10 +101,9 @@ struct kernel_interface_t {
* @param expire_soft lifetime in seconds before rekeying * @param expire_soft lifetime in seconds before rekeying
* @param expire_hard lifetime in seconds before delete * @param expire_hard lifetime in seconds before delete
* @param enc_alg Algorithm to use for encryption (ESP only) * @param enc_alg Algorithm to use for encryption (ESP only)
* @param enc_size key length of encryption algorithm, if dynamic * @param enc_key key to use for encryption
* @param int_alg Algorithm to use for integrity protection * @param int_alg Algorithm to use for integrity protection
* @param int_size key length of integrity algorithm, if dynamic * @param int_key key to use for integrity protection
* @param prf_plus PRF to derive keys from
* @param mode mode of the SA (tunnel, transport) * @param mode mode of the SA (tunnel, transport)
* @param ipcomp IPComp transform to use * @param ipcomp IPComp transform to use
* @param encap enable UDP encapsulation for NAT traversal * @param encap enable UDP encapsulation for NAT traversal
@@ -115,10 +114,9 @@ struct kernel_interface_t {
host_t *src, host_t *dst, u_int32_t spi, host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid, protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard, u_int64_t expire_soft, u_int64_t expire_hard,
u_int16_t enc_alg, u_int16_t enc_size, u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, u_int16_t int_size, u_int16_t int_alg, chunk_t int_key,
prf_plus_t *prf_plus, ipsec_mode_t mode, ipsec_mode_t mode, u_int16_t ipcomp, bool encap,
u_int16_t ipcomp, bool encap,
bool update); bool update);
/** /**
+5 -7
View File
@@ -133,10 +133,9 @@ struct kernel_ipsec_t {
* @param expire_soft lifetime in seconds before rekeying * @param expire_soft lifetime in seconds before rekeying
* @param expire_hard lifetime in seconds before delete * @param expire_hard lifetime in seconds before delete
* @param enc_alg Algorithm to use for encryption (ESP only) * @param enc_alg Algorithm to use for encryption (ESP only)
* @param enc_size key length of encryption algorithm, if dynamic * @param enc_key key to use for encryption
* @param int_alg Algorithm to use for integrity protection * @param int_alg Algorithm to use for integrity protection
* @param int_size key length of integrity algorithm, if dynamic * @param int_key key to use for integrity protection
* @param prf_plus PRF to derive keys from
* @param mode mode of the SA (tunnel, transport) * @param mode mode of the SA (tunnel, transport)
* @param ipcomp IPComp transform to use * @param ipcomp IPComp transform to use
* @param encap enable UDP encapsulation for NAT traversal * @param encap enable UDP encapsulation for NAT traversal
@@ -147,10 +146,9 @@ struct kernel_ipsec_t {
host_t *src, host_t *dst, u_int32_t spi, host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid, protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard, u_int64_t expire_soft, u_int64_t expire_hard,
u_int16_t enc_alg, u_int16_t enc_size, u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, u_int16_t int_size, u_int16_t int_alg, chunk_t int_key,
prf_plus_t *prf_plus, ipsec_mode_t mode, ipsec_mode_t mode, u_int16_t ipcomp, bool encap,
u_int16_t ipcomp, bool encap,
bool update); bool update);
/** /**
@@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
* Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
@@ -76,24 +76,18 @@
typedef struct kernel_algorithm_t kernel_algorithm_t; typedef struct kernel_algorithm_t kernel_algorithm_t;
/** /**
* Mapping from the algorithms defined in IKEv2 to * Mapping of IKEv2 kernel identifier to linux crypto API names
* kernel level algorithm names and their key length
*/ */
struct kernel_algorithm_t { struct kernel_algorithm_t {
/** /**
* Identifier specified in IKEv2 * Identifier specified in IKEv2
*/ */
int ikev2_id; int ikev2;
/** /**
* Name of the algorithm, as used as kernel identifier * Name of the algorithm in linux crypto API
*/ */
char *name; char *name;
/**
* Key length in bits, if fixed size
*/
u_int key_size;
}; };
#define END_OF_LIST -1 #define END_OF_LIST -1
@@ -102,71 +96,65 @@ struct kernel_algorithm_t {
* Algorithms for encryption * Algorithms for encryption
*/ */
static kernel_algorithm_t encryption_algs[] = { static kernel_algorithm_t encryption_algs[] = {
/* {ENCR_DES_IV64, "***", 0}, */ /* {ENCR_DES_IV64, "***" }, */
{ENCR_DES, "des", 64}, {ENCR_DES, "des" },
{ENCR_3DES, "des3_ede", 192}, {ENCR_3DES, "des3_ede" },
/* {ENCR_RC5, "***", 0}, */ /* {ENCR_RC5, "***" }, */
/* {ENCR_IDEA, "***", 0}, */ /* {ENCR_IDEA, "***" }, */
{ENCR_CAST, "cast128", 0}, {ENCR_CAST, "cast128" },
{ENCR_BLOWFISH, "blowfish", 0}, {ENCR_BLOWFISH, "blowfish" },
/* {ENCR_3IDEA, "***", 0}, */ /* {ENCR_3IDEA, "***" }, */
/* {ENCR_DES_IV32, "***", 0}, */ /* {ENCR_DES_IV32, "***" }, */
{ENCR_NULL, "cipher_null", 0}, {ENCR_NULL, "cipher_null" },
{ENCR_AES_CBC, "aes", 0}, {ENCR_AES_CBC, "aes" },
/* {ENCR_AES_CTR, "***", 0}, */ /* {ENCR_AES_CTR, "***" }, */
{ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))", 64}, /* key_size = ICV size */ {ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))" },
{ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))", 96}, /* key_size = ICV size */ {ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))" },
{ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))", 128}, /* key_size = ICV size */ {ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))" },
{ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))", 64}, /* key_size = ICV size */ {ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))" },
{ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))", 96}, /* key_size = ICV size */ {ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))" },
{ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))", 128}, /* key_size = ICV size */ {ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))" },
{END_OF_LIST, NULL, 0}, {END_OF_LIST, NULL },
}; };
/** /**
* Algorithms for integrity protection * Algorithms for integrity protection
*/ */
static kernel_algorithm_t integrity_algs[] = { static kernel_algorithm_t integrity_algs[] = {
{AUTH_HMAC_MD5_96, "md5", 128}, {AUTH_HMAC_MD5_96, "md5" },
{AUTH_HMAC_SHA1_96, "sha1", 160}, {AUTH_HMAC_SHA1_96, "sha1" },
{AUTH_HMAC_SHA2_256_128, "sha256", 256}, {AUTH_HMAC_SHA2_256_128, "sha256" },
{AUTH_HMAC_SHA2_384_192, "sha384", 384}, {AUTH_HMAC_SHA2_384_192, "sha384" },
{AUTH_HMAC_SHA2_512_256, "sha512", 512}, {AUTH_HMAC_SHA2_512_256, "sha512" },
/* {AUTH_DES_MAC, "***", 0}, */ /* {AUTH_DES_MAC, "***" }, */
/* {AUTH_KPDK_MD5, "***", 0}, */ /* {AUTH_KPDK_MD5, "***" }, */
{AUTH_AES_XCBC_96, "xcbc(aes)", 128}, {AUTH_AES_XCBC_96, "xcbc(aes)" },
{END_OF_LIST, NULL, 0}, {END_OF_LIST, NULL },
}; };
/** /**
* Algorithms for IPComp * Algorithms for IPComp
*/ */
static kernel_algorithm_t compression_algs[] = { static kernel_algorithm_t compression_algs[] = {
/* {IPCOMP_OUI, "***", 0}, */ /* {IPCOMP_OUI, "***" }, */
{IPCOMP_DEFLATE, "deflate", 0}, {IPCOMP_DEFLATE, "deflate" },
{IPCOMP_LZS, "lzs", 0}, {IPCOMP_LZS, "lzs" },
{IPCOMP_LZJH, "lzjh", 0}, {IPCOMP_LZJH, "lzjh" },
{END_OF_LIST, NULL, 0}, {END_OF_LIST, NULL },
}; };
/** /**
* Look up a kernel algorithm name and its key size * Look up a kernel algorithm name and its key size
*/ */
static char* lookup_algorithm(kernel_algorithm_t *kernel_algo, static char* lookup_algorithm(kernel_algorithm_t *list, int ikev2)
u_int16_t ikev2_algo, u_int16_t *key_size)
{ {
while (kernel_algo->ikev2_id != END_OF_LIST) while (list->ikev2 != END_OF_LIST)
{ {
if (ikev2_algo == kernel_algo->ikev2_id) if (list->ikev2 == ikev2)
{ {
/* match, evaluate key length */ return list->name;
if (key_size && *key_size == 0)
{ /* update key size if not set */
*key_size = kernel_algo->key_size;
}
return kernel_algo->name;
} }
kernel_algo++; list++;
} }
return NULL; return NULL;
} }
@@ -688,23 +676,22 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
host_t *src, host_t *dst, u_int32_t spi, host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid, protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard, u_int64_t expire_soft, u_int64_t expire_hard,
u_int16_t enc_alg, u_int16_t enc_size, u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, u_int16_t int_size, u_int16_t int_alg, chunk_t int_key,
prf_plus_t *prf_plus, ipsec_mode_t mode, ipsec_mode_t mode, u_int16_t ipcomp, bool encap,
u_int16_t ipcomp, bool encap,
bool replace) bool replace)
{ {
unsigned char request[NETLINK_BUFFER_SIZE]; unsigned char request[NETLINK_BUFFER_SIZE];
char *alg_name; char *alg_name;
/* additional 4 octets KEYMAT required for AES-GCM as of RFC4106 8.1. */
u_int16_t add_keymat = 32;
struct nlmsghdr *hdr; struct nlmsghdr *hdr;
struct xfrm_usersa_info *sa; struct xfrm_usersa_info *sa;
u_int16_t icv_size = 64;
memset(&request, 0, sizeof(request)); memset(&request, 0, sizeof(request));
DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%d}", ntohl(spi), reqid); DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%d}",
ntohl(spi), reqid);
hdr = (struct nlmsghdr*)request; hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; hdr->nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
@@ -741,19 +728,19 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
case ENCR_UNDEFINED: case ENCR_UNDEFINED:
/* no encryption */ /* no encryption */
break; break;
case ENCR_AES_CCM_ICV8:
case ENCR_AES_CCM_ICV12:
case ENCR_AES_CCM_ICV16: case ENCR_AES_CCM_ICV16:
/* AES-CCM needs only 3 additional octets KEYMAT as of RFC 4309 7.1. */
add_keymat = 24;
/* fall-through */
case ENCR_AES_GCM_ICV8:
case ENCR_AES_GCM_ICV12:
case ENCR_AES_GCM_ICV16: case ENCR_AES_GCM_ICV16:
icv_size += 32;
/* FALL */
case ENCR_AES_CCM_ICV12:
case ENCR_AES_GCM_ICV12:
icv_size += 32;
/* FALL */
case ENCR_AES_CCM_ICV8:
case ENCR_AES_GCM_ICV8:
{ {
u_int16_t icv_size = 0;
rthdr->rta_type = XFRMA_ALG_AEAD; rthdr->rta_type = XFRMA_ALG_AEAD;
alg_name = lookup_algorithm(encryption_algs, enc_alg, &icv_size); alg_name = lookup_algorithm(encryption_algs, enc_alg);
if (alg_name == NULL) if (alg_name == NULL)
{ {
DBG1(DBG_KNL, "algorithm %N not supported by kernel!", DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -761,12 +748,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
return FAILED; return FAILED;
} }
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
encryption_algorithm_names, enc_alg, enc_size); encryption_algorithm_names, enc_alg, enc_key.len * 8);
/* additional KEYMAT required */ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_key.len);
enc_size += add_keymat;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_size / 8);
hdr->nlmsg_len += rthdr->rta_len; hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
@@ -774,10 +758,10 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
} }
struct xfrm_algo_aead* algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr); struct xfrm_algo_aead* algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr);
algo->alg_key_len = enc_size; algo->alg_key_len = enc_key.len * 8;
algo->alg_icv_len = icv_size; algo->alg_icv_len = icv_size;
strcpy(algo->alg_name, alg_name); strcpy(algo->alg_name, alg_name);
prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key); memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr); rthdr = XFRM_RTA_NEXT(rthdr);
break; break;
@@ -785,7 +769,7 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
default: default:
{ {
rthdr->rta_type = XFRMA_ALG_CRYPT; rthdr->rta_type = XFRMA_ALG_CRYPT;
alg_name = lookup_algorithm(encryption_algs, enc_alg, &enc_size); alg_name = lookup_algorithm(encryption_algs, enc_alg);
if (alg_name == NULL) if (alg_name == NULL)
{ {
DBG1(DBG_KNL, "algorithm %N not supported by kernel!", DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -793,9 +777,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
return FAILED; return FAILED;
} }
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
encryption_algorithm_names, enc_alg, enc_size); encryption_algorithm_names, enc_alg, enc_key.len * 8);
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_size / 8); rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len);
hdr->nlmsg_len += rthdr->rta_len; hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
@@ -803,9 +787,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
} }
struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = enc_size; algo->alg_key_len = enc_key.len * 8;
strcpy(algo->alg_name, alg_name); strcpy(algo->alg_name, alg_name);
prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key); memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr); rthdr = XFRM_RTA_NEXT(rthdr);
break; break;
@@ -815,7 +799,7 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
if (int_alg != AUTH_UNDEFINED) if (int_alg != AUTH_UNDEFINED)
{ {
rthdr->rta_type = XFRMA_ALG_AUTH; rthdr->rta_type = XFRMA_ALG_AUTH;
alg_name = lookup_algorithm(integrity_algs, int_alg, &int_size); alg_name = lookup_algorithm(integrity_algs, int_alg);
if (alg_name == NULL) if (alg_name == NULL)
{ {
DBG1(DBG_KNL, "algorithm %N not supported by kernel!", DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -823,9 +807,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
return FAILED; return FAILED;
} }
DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
integrity_algorithm_names, int_alg, int_size); integrity_algorithm_names, int_alg, int_key.len * 8);
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_size / 8); rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len);
hdr->nlmsg_len += rthdr->rta_len; hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
@@ -833,9 +817,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
} }
struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = int_size; algo->alg_key_len = int_key.len * 8;
strcpy(algo->alg_name, alg_name); strcpy(algo->alg_name, alg_name);
prf_plus->get_bytes(prf_plus, int_size / 8, algo->alg_key); memcpy(algo->alg_key, int_key.ptr, int_key.len);
rthdr = XFRM_RTA_NEXT(rthdr); rthdr = XFRM_RTA_NEXT(rthdr);
} }
@@ -843,7 +827,7 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
if (ipcomp != IPCOMP_NONE) if (ipcomp != IPCOMP_NONE)
{ {
rthdr->rta_type = XFRMA_ALG_COMP; rthdr->rta_type = XFRMA_ALG_COMP;
alg_name = lookup_algorithm(compression_algs, ipcomp, NULL); alg_name = lookup_algorithm(compression_algs, ipcomp);
if (alg_name == NULL) if (alg_name == NULL)
{ {
DBG1(DBG_KNL, "algorithm %N not supported by kernel!", DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -1559,7 +1543,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
/* public functions */ /* public functions */
this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi; this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,ipsec_mode_t,u_int16_t,bool,bool))add_sa; this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,bool,bool))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa; this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t))del_sa; this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy; this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy;
@@ -384,24 +384,18 @@ static u_int8_t dir2kernel(policy_dir_t dir)
typedef struct kernel_algorithm_t kernel_algorithm_t; typedef struct kernel_algorithm_t kernel_algorithm_t;
/** /**
* Mapping from the algorithms defined in IKEv2 to * Mapping of IKEv2 algorithms to PF_KEY algorithms
* kernel level algorithm identifiers and their key length
*/ */
struct kernel_algorithm_t { struct kernel_algorithm_t {
/** /**
* Identifier specified in IKEv2 * Identifier specified in IKEv2
*/ */
int ikev2_id; int ikev2;
/** /**
* Identifier as defined in pfkeyv2.h * Identifier as defined in pfkeyv2.h
*/ */
int kernel_id; int kernel;
/**
* Key length in bits, if fixed size
*/
u_int key_size;
}; };
#define END_OF_LIST -1 #define END_OF_LIST -1
@@ -410,71 +404,65 @@ struct kernel_algorithm_t {
* Algorithms for encryption * Algorithms for encryption
*/ */
static kernel_algorithm_t encryption_algs[] = { static kernel_algorithm_t encryption_algs[] = {
/* {ENCR_DES_IV64, 0, 0}, */ /* {ENCR_DES_IV64, 0 }, */
{ENCR_DES, SADB_EALG_DESCBC, 64}, {ENCR_DES, SADB_EALG_DESCBC },
{ENCR_3DES, SADB_EALG_3DESCBC, 192}, {ENCR_3DES, SADB_EALG_3DESCBC },
/* {ENCR_RC5, 0, 0}, */ /* {ENCR_RC5, 0 }, */
/* {ENCR_IDEA, 0, 0}, */ /* {ENCR_IDEA, 0 }, */
{ENCR_CAST, SADB_X_EALG_CASTCBC, 0}, {ENCR_CAST, SADB_X_EALG_CASTCBC },
{ENCR_BLOWFISH, SADB_X_EALG_BLOWFISHCBC, 0}, {ENCR_BLOWFISH, SADB_X_EALG_BLOWFISHCBC },
/* {ENCR_3IDEA, 0, 0}, */ /* {ENCR_3IDEA, 0 }, */
/* {ENCR_DES_IV32, 0, 0}, */ /* {ENCR_DES_IV32, 0 }, */
{ENCR_NULL, SADB_EALG_NULL, 0}, {ENCR_NULL, SADB_EALG_NULL },
{ENCR_AES_CBC, SADB_X_EALG_AESCBC, 0}, {ENCR_AES_CBC, SADB_X_EALG_AESCBC },
/* {ENCR_AES_CTR, 0, 0}, */ /* {ENCR_AES_CTR, 0 }, */
/* {ENCR_AES_CCM_ICV8, 0, 64}, */ /* key_size = ICV size */ /* {ENCR_AES_CCM_ICV8, 0 }, */
/* {ENCR_AES_CCM_ICV12, 0, 96}, */ /* key_size = ICV size */ /* {ENCR_AES_CCM_ICV12, 0 }, */
/* {ENCR_AES_CCM_ICV16, 0, 128},*/ /* key_size = ICV size */ /* {ENCR_AES_CCM_ICV16, 0 }, */
/* {ENCR_AES_GCM_ICV8, 0, 64}, */ /* key_size = ICV size */ /* {ENCR_AES_GCM_ICV8, 0 }, */
/* {ENCR_AES_GCM_ICV12, 0, 96}, */ /* key_size = ICV size */ /* {ENCR_AES_GCM_ICV12, 0 }, */
/* {ENCR_AES_GCM_ICV16, 0, 128},*/ /* key_size = ICV size */ /* {ENCR_AES_GCM_ICV16, 0 }, */
{END_OF_LIST, 0, 0}, {END_OF_LIST, 0 },
}; };
/** /**
* Algorithms for integrity protection * Algorithms for integrity protection
*/ */
static kernel_algorithm_t integrity_algs[] = { static kernel_algorithm_t integrity_algs[] = {
{AUTH_HMAC_MD5_96, SADB_AALG_MD5HMAC, 128}, {AUTH_HMAC_MD5_96, SADB_AALG_MD5HMAC },
{AUTH_HMAC_SHA1_96, SADB_AALG_SHA1HMAC, 160}, {AUTH_HMAC_SHA1_96, SADB_AALG_SHA1HMAC },
{AUTH_HMAC_SHA2_256_128, SADB_X_AALG_SHA2_256HMAC, 256}, {AUTH_HMAC_SHA2_256_128, SADB_X_AALG_SHA2_256HMAC },
{AUTH_HMAC_SHA2_384_192, SADB_X_AALG_SHA2_384HMAC, 384}, {AUTH_HMAC_SHA2_384_192, SADB_X_AALG_SHA2_384HMAC },
{AUTH_HMAC_SHA2_512_256, SADB_X_AALG_SHA2_512HMAC, 512}, {AUTH_HMAC_SHA2_512_256, SADB_X_AALG_SHA2_512HMAC },
/* {AUTH_DES_MAC, 0, 0}, */ /* {AUTH_DES_MAC, 0, }, */
/* {AUTH_KPDK_MD5, 0, 0}, */ /* {AUTH_KPDK_MD5, 0, }, */
{AUTH_AES_XCBC_96, SADB_X_AALG_AES_XCBC_MAC, 128}, {AUTH_AES_XCBC_96, SADB_X_AALG_AES_XCBC_MAC, },
{END_OF_LIST, 0, 0}, {END_OF_LIST, 0, },
}; };
/** /**
* Algorithms for IPComp * Algorithms for IPComp
*/ */
static kernel_algorithm_t compression_algs[] = { static kernel_algorithm_t compression_algs[] = {
/* {IPCOMP_OUI, 0, 0}, */ /* {IPCOMP_OUI, 0 }, */
{IPCOMP_DEFLATE, SADB_X_CALG_DEFLATE, 0}, {IPCOMP_DEFLATE, SADB_X_CALG_DEFLATE },
{IPCOMP_LZS, SADB_X_CALG_LZS, 0}, {IPCOMP_LZS, SADB_X_CALG_LZS },
{IPCOMP_LZJH, SADB_X_CALG_LZJH, 0}, {IPCOMP_LZJH, SADB_X_CALG_LZJH },
{END_OF_LIST, 0, 0}, {END_OF_LIST, 0 },
}; };
/** /**
* Look up a kernel algorithm ID and its key size * Look up a kernel algorithm ID and its key size
*/ */
static int lookup_algorithm(kernel_algorithm_t *kernel_algo, static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
u_int16_t ikev2_algo, u_int16_t *key_size)
{ {
while (kernel_algo->ikev2_id != END_OF_LIST) while (list->ikev2 != END_OF_LIST)
{ {
if (ikev2_algo == kernel_algo->ikev2_id) if (ikev2 == list->ikev2)
{ {
/* match, evaluate key length */ return list->kernel;
if (key_size && *key_size == 0)
{ /* update key size if not set */
*key_size = kernel_algo->key_size;
}
return kernel_algo->kernel_id;
} }
kernel_algo++; list++;
} }
return 0; return 0;
} }
@@ -977,10 +965,9 @@ static status_t add_sa(private_kernel_pfkey_ipsec_t *this,
host_t *src, host_t *dst, u_int32_t spi, host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid, protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard, u_int64_t expire_soft, u_int64_t expire_hard,
u_int16_t enc_alg, u_int16_t enc_size, u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, u_int16_t int_size, u_int16_t int_alg, chunk_t int_key,
prf_plus_t *prf_plus, ipsec_mode_t mode, ipsec_mode_t mode, u_int16_t ipcomp, bool encap,
u_int16_t ipcomp, bool encap,
bool replace) bool replace)
{ {
unsigned char request[PFKEY_BUFFER_SIZE]; unsigned char request[PFKEY_BUFFER_SIZE];
@@ -1007,10 +994,8 @@ static status_t add_sa(private_kernel_pfkey_ipsec_t *this,
sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa)); sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
sa->sadb_sa_spi = spi; sa->sadb_sa_spi = spi;
sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32; sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
sa->sadb_sa_auth = lookup_algorithm(integrity_algs, sa->sadb_sa_auth = lookup_algorithm(integrity_algs, int_alg);
int_alg, &int_size); sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs, enc_alg);
sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs,
enc_alg, &enc_size);
PFKEY_EXT_ADD(msg, sa); PFKEY_EXT_ADD(msg, sa);
sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg); sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg);
@@ -1047,17 +1032,17 @@ static status_t add_sa(private_kernel_pfkey_ipsec_t *this,
if (!sa->sadb_sa_encrypt) if (!sa->sadb_sa_encrypt)
{ {
DBG1(DBG_KNL, "algorithm %N not supported by kernel!", DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
encryption_algorithm_names, enc_alg); encryption_algorithm_names, enc_alg);
return FAILED; return FAILED;
} }
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
encryption_algorithm_names, enc_alg, enc_size); encryption_algorithm_names, enc_alg, enc_key.len * 8);
key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg); key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
key->sadb_key_bits = enc_size; key->sadb_key_bits = enc_key.len * 8;
key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_size / 8); key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len);
prf_plus->get_bytes(prf_plus, enc_size / 8, (void*)(key + 1)); memcpy(key + 1, enc_key.ptr, enc_key.len);
PFKEY_EXT_ADD(msg, key); PFKEY_EXT_ADD(msg, key);
} }
@@ -1071,13 +1056,13 @@ static status_t add_sa(private_kernel_pfkey_ipsec_t *this,
return FAILED; return FAILED;
} }
DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
integrity_algorithm_names, int_alg, int_size); integrity_algorithm_names, int_alg, int_key.len * 8);
key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg); key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
key->sadb_key_exttype = SADB_EXT_KEY_AUTH; key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
key->sadb_key_bits = int_size; key->sadb_key_bits = int_key.len * 8;
key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_size / 8); key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len);
prf_plus->get_bytes(prf_plus, int_size / 8, (void*)(key + 1)); memcpy(key + 1, int_key.ptr, int_key.len);
PFKEY_EXT_ADD(msg, key); PFKEY_EXT_ADD(msg, key);
} }
@@ -1765,7 +1750,7 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
/* public functions */ /* public functions */
this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi; this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,ipsec_mode_t,u_int16_t,bool,bool))add_sa; this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,bool,bool))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa; this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t))del_sa; this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy; this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy;
+107 -18
View File
@@ -182,6 +182,58 @@ struct private_child_sa_t {
char *iface; char *iface;
}; };
typedef struct keylen_entry_t keylen_entry_t;
/**
* Implicit key length for an algorithm
*/
struct keylen_entry_t {
/** IKEv2 algorithm identifier */
int algo;
/** key length in bits */
int len;
};
#define END_OF_LIST -1
/**
* Keylen for encryption algos
*/
keylen_entry_t keylen_enc[] = {
{ENCR_DES, 64},
{ENCR_3DES, 192},
{END_OF_LIST, 0}
};
/**
* Keylen for integrity algos
*/
keylen_entry_t keylen_int[] = {
{AUTH_HMAC_MD5_96, 128},
{AUTH_HMAC_SHA1_96, 160},
{AUTH_HMAC_SHA2_256_128, 256},
{AUTH_HMAC_SHA2_384_192, 384},
{AUTH_HMAC_SHA2_512_256, 512},
{AUTH_AES_XCBC_96, 128},
{END_OF_LIST, 0}
};
/**
* Lookup key length of an algorithm
*/
static int lookup_keylen(keylen_entry_t *list, int algo)
{
while (list->algo != END_OF_LIST)
{
if (algo == list->algo)
{
return list->len;
}
list++;
}
return 0;
}
/** /**
* Implementation of child_sa_t.get_name. * Implementation of child_sa_t.get_name.
*/ */
@@ -530,10 +582,11 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
static status_t install(private_child_sa_t *this, proposal_t *proposal, static status_t install(private_child_sa_t *this, proposal_t *proposal,
ipsec_mode_t mode, prf_plus_t *prf_plus, bool mine) ipsec_mode_t mode, prf_plus_t *prf_plus, bool mine)
{ {
u_int32_t spi, soft, hard; u_int32_t spi, cpi, soft, hard;
host_t *src; host_t *src, *dst;
host_t *dst;
status_t status; status_t status;
chunk_t enc_key = chunk_empty, int_key = chunk_empty;
int add_keymat;
this->protocol = proposal->get_protocol(proposal); this->protocol = proposal->get_protocol(proposal);
@@ -549,8 +602,8 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
this->me.spi = this->alloc_esp_spi; this->me.spi = this->alloc_esp_spi;
if (this->alloc_ah_spi) if (this->alloc_ah_spi)
{ {
charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr, charon->kernel_interface->del_sa(charon->kernel_interface,
this->alloc_ah_spi, PROTO_AH); this->me.addr, this->alloc_ah_spi, PROTO_AH);
} }
} }
else else
@@ -558,8 +611,8 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
this->me.spi = this->alloc_ah_spi; this->me.spi = this->alloc_ah_spi;
if (this->alloc_esp_spi) if (this->alloc_esp_spi)
{ {
charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr, charon->kernel_interface->del_sa(charon->kernel_interface,
this->alloc_esp_spi, PROTO_ESP); this->me.addr, this->alloc_esp_spi, PROTO_ESP);
} }
} }
spi = this->me.spi; spi = this->me.spi;
@@ -577,23 +630,55 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
DBG2(DBG_CHD, "adding %s %N SA", mine ? "inbound" : "outbound", DBG2(DBG_CHD, "adding %s %N SA", mine ? "inbound" : "outbound",
protocol_id_names, this->protocol); protocol_id_names, this->protocol);
/* select encryption algo */ /* select encryption algo, derive key */
if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
&this->enc_alg, &this->enc_size)) &this->enc_alg, &this->enc_size))
{ {
DBG2(DBG_CHD, " using %N for encryption", DBG2(DBG_CHD, " using %N for encryption",
encryption_algorithm_names, this->enc_alg); encryption_algorithm_names, this->enc_alg);
} }
if (!this->enc_size)
{
this->enc_size = lookup_keylen(keylen_enc, this->enc_alg);
}
if (this->enc_size && this->enc_alg != ENCR_UNDEFINED)
{
/* CCM/GCM needs additional keymat */
switch (this->enc_alg)
{
case ENCR_AES_CCM_ICV8:
case ENCR_AES_CCM_ICV12:
case ENCR_AES_CCM_ICV16:
add_keymat = 3;
break;
case ENCR_AES_GCM_ICV8:
case ENCR_AES_GCM_ICV12:
case ENCR_AES_GCM_ICV16:
add_keymat = 4;
break;
default:
add_keymat = 0;
break;
}
prf_plus->allocate_bytes(prf_plus, this->enc_size / 8 + add_keymat,
&enc_key);
}
/* select integrity algo */ /* select integrity algo, derive key */
if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
&this->int_alg, &this->int_size)) &this->int_alg, &this->int_size))
{ {
DBG2(DBG_CHD, " using %N for integrity", DBG2(DBG_CHD, " using %N for integrity",
integrity_algorithm_names, this->int_alg); integrity_algorithm_names, this->int_alg);
} }
soft = this->config->get_lifetime(this->config, TRUE); if (!this->int_size)
hard = this->config->get_lifetime(this->config, FALSE); {
this->int_size = lookup_keylen(keylen_int, this->int_alg);
}
if (this->int_size && this->int_alg != AUTH_UNDEFINED)
{
prf_plus->allocate_bytes(prf_plus, this->int_size / 8, &int_key);
}
/* send SA down to the kernel */ /* send SA down to the kernel */
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst); DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
@@ -601,18 +686,22 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
if (this->ipcomp != IPCOMP_NONE) if (this->ipcomp != IPCOMP_NONE)
{ {
/* we install an additional IPComp SA */ /* we install an additional IPComp SA */
u_int32_t cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi)); cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi));
status = charon->kernel_interface->add_sa(charon->kernel_interface, charon->kernel_interface->add_sa(charon->kernel_interface,
src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0, src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
ENCR_UNDEFINED, 0, AUTH_UNDEFINED, 0, NULL, mode, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
this->ipcomp, FALSE, mine); mode, this->ipcomp, FALSE, mine);
} }
soft = this->config->get_lifetime(this->config, TRUE);
hard = this->config->get_lifetime(this->config, FALSE);
status = charon->kernel_interface->add_sa(charon->kernel_interface, status = charon->kernel_interface->add_sa(charon->kernel_interface,
src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard, src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard,
this->enc_alg, this->enc_size, this->int_alg, this->int_size, this->enc_alg, enc_key, this->int_alg, int_key,
prf_plus, mode, IPCOMP_NONE, this->encap, mine); mode, IPCOMP_NONE, this->encap, mine);
chunk_clear(&enc_key);
chunk_clear(&int_key);
this->install_time = time(NULL); this->install_time = time(NULL);
this->rekey_time = this->install_time + soft; this->rekey_time = this->install_time + soft;
return status; return status;
+10 -10
View File
@@ -1658,8 +1658,8 @@ static status_t derive_keys(private_ike_sa_t *this,
this->prf->allocate_bytes(this->prf, secret, &skeyseed); this->prf->allocate_bytes(this->prf, secret, &skeyseed);
DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
this->prf->set_key(this->prf, skeyseed); this->prf->set_key(this->prf, skeyseed);
chunk_free(&skeyseed); chunk_clear(&skeyseed);
chunk_free(&secret); chunk_clear(&secret);
prf_plus = prf_plus_create(this->prf, prf_plus_seed); prf_plus = prf_plus_create(this->prf, prf_plus_seed);
} }
else else
@@ -1670,13 +1670,13 @@ static status_t derive_keys(private_ike_sa_t *this,
child_prf->allocate_bytes(child_prf, secret, &skeyseed); child_prf->allocate_bytes(child_prf, secret, &skeyseed);
DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
old_prf->set_key(old_prf, skeyseed); old_prf->set_key(old_prf, skeyseed);
chunk_free(&skeyseed); chunk_clear(&skeyseed);
chunk_free(&secret); chunk_clear(&secret);
prf_plus = prf_plus_create(old_prf, prf_plus_seed); prf_plus = prf_plus_create(old_prf, prf_plus_seed);
} }
chunk_free(&full_nonce); chunk_free(&full_nonce);
chunk_free(&fixed_nonce); chunk_free(&fixed_nonce);
chunk_free(&prf_plus_seed); chunk_clear(&prf_plus_seed);
/* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */ /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
@@ -1687,7 +1687,7 @@ static status_t derive_keys(private_ike_sa_t *this,
prf_plus->allocate_bytes(prf_plus, key_size, &key); prf_plus->allocate_bytes(prf_plus, key_size, &key);
DBG4(DBG_IKE, "Sk_d secret %B", &key); DBG4(DBG_IKE, "Sk_d secret %B", &key);
this->child_prf->set_key(this->child_prf, key); this->child_prf->set_key(this->child_prf, key);
chunk_free(&key); chunk_clear(&key);
/* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */ /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */
if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)) if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
@@ -1711,12 +1711,12 @@ static status_t derive_keys(private_ike_sa_t *this,
prf_plus->allocate_bytes(prf_plus, key_size, &key); prf_plus->allocate_bytes(prf_plus, key_size, &key);
DBG4(DBG_IKE, "Sk_ai secret %B", &key); DBG4(DBG_IKE, "Sk_ai secret %B", &key);
signer_i->set_key(signer_i, key); signer_i->set_key(signer_i, key);
chunk_free(&key); chunk_clear(&key);
prf_plus->allocate_bytes(prf_plus, key_size, &key); prf_plus->allocate_bytes(prf_plus, key_size, &key);
DBG4(DBG_IKE, "Sk_ar secret %B", &key); DBG4(DBG_IKE, "Sk_ar secret %B", &key);
signer_r->set_key(signer_r, key); signer_r->set_key(signer_r, key);
chunk_free(&key); chunk_clear(&key);
if (initiator) if (initiator)
{ {
@@ -1752,12 +1752,12 @@ static status_t derive_keys(private_ike_sa_t *this,
prf_plus->allocate_bytes(prf_plus, key_size, &key); prf_plus->allocate_bytes(prf_plus, key_size, &key);
DBG4(DBG_IKE, "Sk_ei secret %B", &key); DBG4(DBG_IKE, "Sk_ei secret %B", &key);
crypter_i->set_key(crypter_i, key); crypter_i->set_key(crypter_i, key);
chunk_free(&key); chunk_clear(&key);
prf_plus->allocate_bytes(prf_plus, key_size, &key); prf_plus->allocate_bytes(prf_plus, key_size, &key);
DBG4(DBG_IKE, "Sk_er secret %B", &key); DBG4(DBG_IKE, "Sk_er secret %B", &key);
crypter_r->set_key(crypter_r, key); crypter_r->set_key(crypter_r, key);
chunk_free(&key); chunk_clear(&key);
if (initiator) if (initiator)
{ {