diff options
-rw-r--r-- | src/pluto/alg_info.c | 32 | ||||
-rw-r--r-- | src/pluto/constants.c | 3 | ||||
-rw-r--r-- | src/pluto/ipsec_doi.c | 119 | ||||
-rw-r--r-- | src/pluto/kernel.c | 186 | ||||
-rw-r--r-- | src/pluto/kernel_alg.c | 48 | ||||
-rw-r--r-- | src/pluto/kernel_netlink.c | 94 | ||||
-rw-r--r-- | src/pluto/spdb.c | 88 |
7 files changed, 349 insertions, 221 deletions
diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c index a85a18905..c25418fc1 100644 --- a/src/pluto/alg_info.c +++ b/src/pluto/alg_info.c @@ -139,6 +139,24 @@ static void __alg_info_esp_add(struct alg_info_esp *alg_info, int ealg_id, ) } +/** + * Returns true if the given alg is an authenticated encryption algorithm + */ +static bool is_authenticated_encryption(int ealg_id) +{ + switch (ealg_id) + { + case ESP_AES_CCM_8: + case ESP_AES_CCM_12: + case ESP_AES_CCM_16: + case ESP_AES_GCM_8: + case ESP_AES_GCM_12: + case ESP_AES_GCM_16: + return TRUE; + } + return FALSE; +} + /* * Add ESP alg info _with_ logic (policy): */ @@ -152,7 +170,13 @@ static void alg_info_esp_add(struct alg_info *alg_info, int ealg_id, } if (ealg_id > 0) { - if (aalg_id > 0) + if (is_authenticated_encryption(ealg_id)) + { + __alg_info_esp_add((struct alg_info_esp *)alg_info, + ealg_id, ek_bits, + AUTH_ALGORITHM_NONE, 0); + } + else if (aalg_id > 0) { __alg_info_esp_add((struct alg_info_esp *)alg_info, ealg_id, ek_bits, @@ -160,13 +184,13 @@ static void alg_info_esp_add(struct alg_info *alg_info, int ealg_id, } else { - /* Policy: default to MD5 and SHA1 */ + /* Policy: default to SHA-1 and MD5 */ __alg_info_esp_add((struct alg_info_esp *)alg_info, ealg_id, ek_bits, - AUTH_ALGORITHM_HMAC_MD5, ak_bits); + AUTH_ALGORITHM_HMAC_SHA1, ak_bits); __alg_info_esp_add((struct alg_info_esp *)alg_info, ealg_id, ek_bits, - AUTH_ALGORITHM_HMAC_SHA1, ak_bits); + AUTH_ALGORITHM_HMAC_MD5, ak_bits); } } } diff --git a/src/pluto/constants.c b/src/pluto/constants.c index adcd77131..e46728d84 100644 --- a/src/pluto/constants.c +++ b/src/pluto/constants.c @@ -663,6 +663,7 @@ enum_names enc_mode_names = /* Auth Algorithm attribute */ static const char *const auth_alg_name[] = { + "AUTH_NONE", "HMAC_MD5", "HMAC_SHA1", "DES_MAC", @@ -683,7 +684,7 @@ enum_names extended_auth_alg_names = { AUTH_ALGORITHM_NULL, AUTH_ALGORITHM_NULL, extended_auth_alg_name, NULL }; enum_names auth_alg_names = - { AUTH_ALGORITHM_HMAC_MD5, AUTH_ALGORITHM_SIG_RSA, auth_alg_name + { AUTH_ALGORITHM_NONE, AUTH_ALGORITHM_SIG_RSA, auth_alg_name , &extended_auth_alg_names }; /* From draft-beaulieu-ike-xauth */ diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index 929768ee9..cac22449e 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -2639,77 +2639,78 @@ static void compute_proto_keymat(struct state *st, u_int8_t protoid, */ switch (protoid) { - case PROTO_IPSEC_ESP: + case PROTO_IPSEC_ESP: + { + needed_len = kernel_alg_esp_enc_keylen(pi->attrs.transid); + + if (needed_len && pi->attrs.key_len) + { + needed_len = pi->attrs.key_len / BITS_PER_BYTE; + } + switch (pi->attrs.transid) { - case ESP_NULL: - needed_len = 0; - break; - case ESP_DES: - needed_len = DES_CBC_BLOCK_SIZE; - break; - case ESP_3DES: - needed_len = DES_CBC_BLOCK_SIZE * 3; - break; - default: -#ifndef NO_KERNEL_ALG - if((needed_len=kernel_alg_esp_enc_keylen(pi->attrs.transid))>0) { - /* XXX: check key_len "coupling with kernel.c's */ - if (pi->attrs.key_len) { - needed_len=pi->attrs.key_len/8; - DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" - "key_len=%d from peer", - (int)needed_len)); - } - break; - } -#endif - bad_case(pi->attrs.transid); + case ESP_NULL: + needed_len = 0; + break; + case ESP_AES_CCM_8: + case ESP_AES_CCM_12: + case ESP_AES_CCM_16: + needed_len += 3; + break; + case ESP_AES_GCM_8: + case ESP_AES_GCM_12: + case ESP_AES_GCM_16: + case ESP_AES_CTR: + needed_len += 4; + break; + default: + if (needed_len == 0) + { + bad_case(pi->attrs.transid); + } } -#ifndef NO_KERNEL_ALG - DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" - "needed_len (after ESP enc)=%d", - (int)needed_len)); - if (kernel_alg_esp_auth_ok(pi->attrs.auth, NULL)) { + if (kernel_alg_esp_auth_ok(pi->attrs.auth, NULL)) + { needed_len += kernel_alg_esp_auth_keylen(pi->attrs.auth); - } else -#endif - switch (pi->attrs.auth) + } + else { - case AUTH_ALGORITHM_NONE: - break; - case AUTH_ALGORITHM_HMAC_MD5: - needed_len += HMAC_MD5_KEY_LEN; - break; - case AUTH_ALGORITHM_HMAC_SHA1: - needed_len += HMAC_SHA1_KEY_LEN; - break; - case AUTH_ALGORITHM_DES_MAC: - default: - bad_case(pi->attrs.auth); + switch (pi->attrs.auth) + { + case AUTH_ALGORITHM_NONE: + break; + case AUTH_ALGORITHM_HMAC_MD5: + needed_len += HMAC_MD5_KEY_LEN; + break; + case AUTH_ALGORITHM_HMAC_SHA1: + needed_len += HMAC_SHA1_KEY_LEN; + break; + case AUTH_ALGORITHM_DES_MAC: + default: + bad_case(pi->attrs.auth); + } } - DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" - "needed_len (after ESP auth)=%d", - (int)needed_len)); break; - - case PROTO_IPSEC_AH: + } + case PROTO_IPSEC_AH: + { switch (pi->attrs.transid) { - case AH_MD5: - needed_len = HMAC_MD5_KEY_LEN; - break; - case AH_SHA: - needed_len = HMAC_SHA1_KEY_LEN; - break; - default: - bad_case(pi->attrs.transid); + case AH_MD5: + needed_len = HMAC_MD5_KEY_LEN; + break; + case AH_SHA: + needed_len = HMAC_SHA1_KEY_LEN; + break; + default: + bad_case(pi->attrs.transid); } break; - - default: - bad_case(protoid); + } + default: + bad_case(protoid); } pi->keymat_len = needed_len; diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c index 7148abc5c..46edac1cd 100644 --- a/src/pluto/kernel.c +++ b/src/pluto/kernel.c @@ -1850,7 +1850,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) if (st->nat_traversal & NAT_T_DETECTED) { natt_type = (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) ? - ESPINUDP_WITH_NON_ESP : ESPINUDP_WITH_NON_IKE; + ESPINUDP_WITH_NON_ESP : ESPINUDP_WITH_NON_IKE; natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port; natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port; natt_oa = st->nat_oa; @@ -1861,12 +1861,11 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) if (ei == &esp_info[countof(esp_info)]) { /* Check for additional kernel alg */ -#ifndef NO_KERNEL_ALG if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid, - st->st_esp.attrs.auth))!=NULL) { - break; + st->st_esp.attrs.auth))!=NULL) + { + break; } -#endif /* note: enum_show may use a static buffer, so two * calls in one printf would be a mistake. @@ -1879,9 +1878,11 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) goto fail; } - if (st->st_esp.attrs.transid == ei->transid - && st->st_esp.attrs.auth == ei->auth) + if (st->st_esp.attrs.transid == ei->transid && + st->st_esp.attrs.auth == ei->auth) + { break; + } } key_len = st->st_esp.attrs.key_len/8; @@ -1900,40 +1901,52 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) { key_len = ei->enckeylen; } - /* Grrrrr.... f*cking 7 bits jurassic algos */ - - /* 168 bits in kernel, need 192 bits for keymat_len */ - if (ei->transid == ESP_3DES && key_len == 21) - key_len = 24; - /* 56 bits in kernel, need 64 bits for keymat_len */ - if (ei->transid == ESP_DES && key_len == 7) - key_len = 8; + switch (ei->transid) + { + case ESP_3DES: + /* 168 bits in kernel, need 192 bits for keymat_len */ + if (key_len == 21) + { + key_len = 24; + } + break; + case ESP_DES: + /* 56 bits in kernel, need 64 bits for keymat_len */ + if (key_len == 7) + { + key_len = 8; + } + break; + case ESP_AES_CCM_8: + case ESP_AES_CCM_12: + case ESP_AES_CCM_16: + key_len += 3; + break; + case ESP_AES_GCM_8: + case ESP_AES_GCM_12: + case ESP_AES_GCM_16: + case ESP_AES_CTR: + key_len += 4; + break; + default: + break; + } /* divide up keying material */ - /* passert(st->st_esp.keymat_len == ei->enckeylen + ei->authkeylen); */ - DBG(DBG_KLIPS|DBG_CONTROL|DBG_PARSING, - if(st->st_esp.keymat_len != key_len + ei->authkeylen) - DBG_log("keymat_len=%d key_len=%d authkeylen=%d", - st->st_esp.keymat_len, (int)key_len, (int)ei->authkeylen); - ) - passert(st->st_esp.keymat_len == key_len + ei->authkeylen); - set_text_said(text_said, &dst.addr, esp_spi, SA_ESP); - said_next->src = &src.addr; said_next->dst = &dst.addr; said_next->src_client = &src_client; said_next->dst_client = &dst_client; said_next->spi = esp_spi; said_next->satype = SADB_SATYPE_ESP; - said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM; + said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? + REPLAY_WINDOW : REPLAY_WINDOW_XFRM; said_next->authalg = ei->authalg; said_next->authkeylen = ei->authkeylen; - /* said_next->authkey = esp_dst_keymat + ei->enckeylen; */ said_next->authkey = esp_dst_keymat + key_len; said_next->encalg = ei->encryptalg; - /* said_next->enckeylen = ei->enckeylen; */ said_next->enckeylen = key_len; said_next->enckey = esp_dst_keymat; said_next->encapsulation = encapsulation; @@ -1946,10 +1959,10 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) said_next->text_said = text_said; if (!kernel_ops->add_sa(said_next, replace)) + { goto fail; - + } said_next++; - encapsulation = ENCAPSULATION_MODE_TRANSPORT; } @@ -1964,29 +1977,27 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) switch (st->st_ah.attrs.auth) { - case AUTH_ALGORITHM_HMAC_MD5: - authalg = SADB_AALG_MD5HMAC; - break; - - case AUTH_ALGORITHM_HMAC_SHA1: - authalg = SADB_AALG_SHA1HMAC; - break; - - default: - loglog(RC_LOG_SERIOUS, "%s not implemented yet" - , enum_show(&auth_alg_names, st->st_ah.attrs.auth)); + case AUTH_ALGORITHM_HMAC_MD5: + authalg = SADB_AALG_MD5HMAC; + break; + case AUTH_ALGORITHM_HMAC_SHA1: + authalg = SADB_AALG_SHA1HMAC; + break; + default: + loglog(RC_LOG_SERIOUS, "%s not implemented yet", + enum_show(&auth_alg_names, st->st_ah.attrs.auth)); goto fail; } set_text_said(text_said, &dst.addr, ah_spi, SA_AH); - said_next->src = &src.addr; said_next->dst = &dst.addr; said_next->src_client = &src_client; said_next->dst_client = &dst_client; said_next->spi = ah_spi; said_next->satype = SADB_SATYPE_AH; - said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM; + said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? + REPLAY_WINDOW : REPLAY_WINDOW_XFRM; said_next->authalg = authalg; said_next->authkeylen = st->st_ah.keymat_len; said_next->authkey = ah_dst_keymat; @@ -1995,10 +2006,10 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) said_next->text_said = text_said; if (!kernel_ops->add_sa(said_next, replace)) + { goto fail; - + } said_next++; - encapsulation = ENCAPSULATION_MODE_TRANSPORT; } @@ -2094,7 +2105,9 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) s[1].text_said = text_said1; if (!kernel_ops->grp_sa(s + 1, s)) + { goto fail; + } } /* could update said, but it will not be used */ } @@ -2105,8 +2118,10 @@ fail: { /* undo the done SPIs */ while (said_next-- != said) - (void) del_spi(said_next->spi, said_next->proto - , &src.addr, said_next->dst); + { + (void) del_spi(said_next->spi, said_next->proto, &src.addr, + said_next->dst); + } return FALSE; } } @@ -2217,8 +2232,9 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time) *use_time = UNDEFINED_TIME; if (kernel_ops->get_sa == NULL || !st->st_esp.present) + { return FALSE; - + } memset(&sa, 0, sizeof(sa)); sa.proto = SA_ESP; @@ -2242,7 +2258,9 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time) DBG_log("get %s", text_said) ) if (!kernel_ops->get_sa(&sa, bytes)) + { return FALSE; + } DBG(DBG_KLIPS, DBG_log(" current: %d bytes", *bytes) ) @@ -2267,7 +2285,9 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time) sa.dst_client = &c->spd.that.client; } if (!kernel_ops->get_policy(&sa, inbound, use_time)) + { return FALSE; + } DBG(DBG_KLIPS, DBG_log(" use_time: %T", use_time, FALSE) ) @@ -2350,15 +2370,21 @@ bool install_inbound_ipsec_sa(struct state *st) struct connection *o = route_owner(c, &esr, NULL, NULL); if (o == NULL) + { break; /* nobody has a route */ + } /* note: we ignore the client addresses at this end */ - if (sameaddr(&o->spd.that.host_addr, &c->spd.that.host_addr) - && o->interface == c->interface) + if (sameaddr(&o->spd.that.host_addr, &c->spd.that.host_addr) && + o->interface == c->interface) + { break; /* existing route is compatible */ + } if (o->kind == CK_TEMPLATE && streq(o->name, c->name)) + { break; /* ??? is this good enough?? */ + } loglog(RC_LOG_SERIOUS, "route to peer's client conflicts with \"%s\" %s; releasing old connection to free the route" , o->name, ip_str(&o->spd.that.host_addr)); @@ -2370,12 +2396,11 @@ bool install_inbound_ipsec_sa(struct state *st) /* check that we will be able to route and eroute */ switch (could_route(c)) { - case route_easy: - case route_nearconflict: - break; - - default: - return FALSE; + case route_easy: + case route_nearconflict: + break; + default: + return FALSE; } #ifdef KLIPS @@ -2472,10 +2497,14 @@ bool route_and_eroute(struct connection *c USED_BY_KLIPS, /* if no state provided, then install a shunt for later */ if (st == NULL) + { eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE , ERO_ADD, "add"); + } else + { eroute_installed = sag_eroute(st, sr, ERO_ADD, "add"); + } } /* notify the firewall of a new tunnel */ @@ -2508,8 +2537,7 @@ bool route_and_eroute(struct connection *c USED_BY_KLIPS, (void) do_command(c, sr, "prepare"); /* just in case; ignore failure */ route_installed = do_command(c, sr, "route"); } - else if (routed(sr->routing) - || routes_agree(ro, c)) + else if (routed(sr->routing) || routes_agree(ro, c)) { route_installed = TRUE; /* nothing to be done */ } @@ -2659,11 +2687,13 @@ bool route_and_eroute(struct connection *c USED_BY_KLIPS, { /* there was no previous eroute: delete whatever we installed */ if (st == NULL) - (void) shunt_eroute(c, sr - , sr->routing, ERO_DELETE, "delete"); + { + (void) shunt_eroute(c, sr, sr->routing, ERO_DELETE, "delete"); + } else - (void) sag_eroute(st, sr - , ERO_DELETE, "delete"); + { + (void) sag_eroute(st, sr, ERO_DELETE, "delete"); + } } } @@ -2686,18 +2716,19 @@ bool install_ipsec_sa(struct state *st, bool inbound_also USED_BY_KLIPS) switch (could_route(st->st_connection)) { - case route_easy: - case route_nearconflict: - break; - - default: - return FALSE; + case route_easy: + case route_nearconflict: + break; + default: + return FALSE; } /* (attempt to) actually set up the SA group */ - if ((inbound_also && !setup_half_ipsec_sa(st, TRUE)) - || !setup_half_ipsec_sa(st, FALSE)) + if ((inbound_also && !setup_half_ipsec_sa(st, TRUE)) || + !setup_half_ipsec_sa(st, FALSE)) + { return FALSE; + } for (sr = &st->st_connection->spd; sr != NULL; sr = sr->next) { @@ -2731,12 +2762,11 @@ bool install_ipsec_sa(struct state *st, bool inbound_also USED_BY_KLIPS) switch (could_route(st->st_connection)) { - case route_easy: - case route_nearconflict: - break; - - default: - return FALSE; + case route_easy: + case route_nearconflict: + break; + default: + return FALSE; } @@ -2779,8 +2809,7 @@ void delete_ipsec_sa(struct state *st USED_BY_KLIPS, ? RT_ROUTED_PROSPECTIVE : RT_ROUTED_FAILURE; (void) do_command(c, sr, "down"); - if ((c->policy & POLICY_DONT_REKEY) - && c->kind == CK_INSTANCE) + if ((c->policy & POLICY_DONT_REKEY) && c->kind == CK_INSTANCE) { /* in this special case, even if the connection * is still alive (due to an ISAKMP SA), @@ -2889,8 +2918,7 @@ bool was_eroute_idle(struct state *st, time_t idle_max, time_t *idle_time) /* Can't open the file, perhaps were are on 26sec? */ time_t use_time; - if (get_sa_info(st, TRUE, &bytes, &use_time) - && use_time != UNDEFINED_TIME) + if (get_sa_info(st, TRUE, &bytes, &use_time) && use_time != UNDEFINED_TIME) { *idle_time = time(NULL) - use_time; ret = *idle_time >= idle_max; diff --git a/src/pluto/kernel_alg.c b/src/pluto/kernel_alg.c index f56e7a768..7e7d25872 100644 --- a/src/pluto/kernel_alg.c +++ b/src/pluto/kernel_alg.c @@ -341,7 +341,7 @@ void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen) sadb.msg++; - while(msglen) + while (msglen) { int supp_exttype = sadb.supported->sadb_supported_exttype; int supp_len = sadb.supported->sadb_supported_len*IPSEC_PFKEYv2_ALIGN; @@ -361,14 +361,14 @@ void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen) supp_len; supp_len -= sizeof(struct sadb_alg), sadb.alg++,i++) { - int ret = kernel_alg_add(satype, supp_exttype, sadb.alg); + kernel_alg_add(satype, supp_exttype, sadb.alg); DBG(DBG_KLIPS, DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: " "alg[%d], exttype=%d, satype=%d, alg_id=%d, " "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, " - "res=%d, ret=%d" - , satype==SADB_SATYPE_ESP? "ESP" : "AH" + "res=%d" + , satype == SADB_SATYPE_ESP? "ESP" : "AH" , i , supp_exttype , satype @@ -376,9 +376,25 @@ void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen) , sadb.alg->sadb_alg_ivlen , sadb.alg->sadb_alg_minbits , sadb.alg->sadb_alg_maxbits - , sadb.alg->sadb_alg_reserved - , ret) + , sadb.alg->sadb_alg_reserved) ) + /* if AES_CBC is registered then also register AES_CCM and AES_GCM */ + if (satype == SADB_SATYPE_ESP && + sadb.alg->sadb_alg_id == SADB_X_EALG_AESCBC) + { + struct sadb_alg alg = *sadb.alg; + int alg_id; + + for (alg_id = SADB_X_EALG_AES_CCM_ICV8; + alg_id <= SADB_X_EALG_AES_GCM_ICV16; alg_id++) + { + if (alg_id != ESP_UNASSIGNED_17) + { + alg.sadb_alg_id = alg_id; + kernel_alg_add(satype, supp_exttype, &alg); + } + } + } } } } @@ -515,7 +531,7 @@ void kernel_alg_show_connection(struct connection *c, const char *instance) } bool kernel_alg_esp_auth_ok(u_int auth, - struct alg_info_esp *alg_info __attribute__((unused))) + struct alg_info_esp *alg_info __attribute__((unused))) { return ESP_AALG_PRESENT(alg_info_esp_aa2sadb(auth)); } @@ -619,14 +635,15 @@ static bool kernel_alg_db_add(struct db_context *db_ctx, return FALSE; } - if (!(policy & POLICY_AUTHENTICATE)) /* skip ESP auth attrs for AH */ + if (!(policy & POLICY_AUTHENTICATE) && /* skip ESP auth attrs for AH */ + esp_info->esp_aalg_id != AUTH_ALGORITHM_NONE) { aalg_id = alg_info_esp_aa2sadb(esp_info->esp_aalg_id); if (!ESP_AALG_PRESENT(aalg_id)) { - DBG_log("kernel_alg_db_add() kernel auth " - "aalg_id=%d not present", aalg_id); + DBG_log("kernel_alg_db_add() kernel auth aalg_id=%d not present", + aalg_id); return FALSE; } } @@ -637,13 +654,18 @@ static bool kernel_alg_db_add(struct db_context *db_ctx, /* open new transformation */ db_trans_add(db_ctx, ealg_id); - /* add ESP auth attr */ - if (!(policy & POLICY_AUTHENTICATE)) + /* add ESP auth attr if not AH or AEAD */ + if (!(policy & POLICY_AUTHENTICATE) && + esp_info->esp_aalg_id != AUTH_ALGORITHM_NONE) + { db_attr_add_values(db_ctx, AUTH_ALGORITHM, esp_info->esp_aalg_id); + } - /* add keylegth if specified in esp= string */ + /* add keylength if specified in esp= string */ if (esp_info->esp_ealg_keylen) + { db_attr_add_values(db_ctx, KEY_LENGTH, esp_info->esp_ealg_keylen); + } return TRUE; } diff --git a/src/pluto/kernel_netlink.c b/src/pluto/kernel_netlink.c index ba879819e..0376e817b 100644 --- a/src/pluto/kernel_netlink.c +++ b/src/pluto/kernel_netlink.c @@ -590,6 +590,7 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace) char data[1024]; } req; struct rtattr *attr; + u_int16_t icv_size = 64; memset(&req, 0, sizeof(req)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; @@ -625,6 +626,11 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace) , sa->authalg); return FALSE; } + DBG(DBG_CRYPT, + DBG_log("configured authentication algorithm %s with key size %d", + enum_show(&auth_alg_names, sa->authalg), + sa->authkeylen * BITS_PER_BYTE) + ) strcpy(algo.alg_name, name); algo.alg_key_len = sa->authkeylen * BITS_PER_BYTE; @@ -640,30 +646,78 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace) attr = (struct rtattr *)((char *)attr + attr->rta_len); } - if (sa->encalg) + switch (sa->encalg) { - struct xfrm_algo algo; - const char *name; + case SADB_EALG_NONE: + /* no encryption */ + break; + case SADB_X_EALG_AES_CCM_ICV16: + case SADB_X_EALG_AES_GCM_ICV16: + icv_size += 32; + /* FALL */ + case SADB_X_EALG_AES_CCM_ICV12: + case SADB_X_EALG_AES_GCM_ICV12: + icv_size += 32; + /* FALL */ + case SADB_X_EALG_AES_CCM_ICV8: + case SADB_X_EALG_AES_GCM_ICV8: + { + struct xfrm_algo_aead *algo; + const char *name; - name = sparse_name(ealg_list, sa->encalg); - if (!name) { - loglog(RC_LOG_SERIOUS, "unknown encryption algorithm: %u" - , sa->encalg); - return FALSE; + name = sparse_name(ealg_list, sa->encalg); + if (!name) + { + loglog(RC_LOG_SERIOUS, "unknown encryption algorithm: %u", + sa->encalg); + return FALSE; + } + DBG(DBG_CRYPT, + DBG_log("configured esp encryption algorithm %s with key size %d", + enum_show(&esp_transformid_names, sa->encalg), + sa->enckeylen * BITS_PER_BYTE) + ) + attr->rta_type = XFRMA_ALG_AEAD; + attr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + sa->enckeylen); + req.n.nlmsg_len += attr->rta_len; + + algo = (struct xfrm_algo_aead*)RTA_DATA(attr); + algo->alg_key_len = sa->enckeylen * BITS_PER_BYTE; + algo->alg_icv_len = icv_size; + strcpy(algo->alg_name, name); + memcpy(algo->alg_key, sa->enckey, sa->enckeylen); + + attr = (struct rtattr *)((char *)attr + attr->rta_len); + break; } + default: + { + struct xfrm_algo *algo; + const char *name; - strcpy(algo.alg_name, name); - algo.alg_key_len = sa->enckeylen * BITS_PER_BYTE; - - attr->rta_type = XFRMA_ALG_CRYPT; - attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->enckeylen); - - memcpy(RTA_DATA(attr), &algo, sizeof(algo)); - memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->enckey - , sa->enckeylen); - - req.n.nlmsg_len += attr->rta_len; - attr = (struct rtattr *)((char *)attr + attr->rta_len); + name = sparse_name(ealg_list, sa->encalg); + if (!name) + { + loglog(RC_LOG_SERIOUS, "unknown encryption algorithm: %u", + sa->encalg); + return FALSE; + } + DBG(DBG_CRYPT, + DBG_log("configured esp encryption algorithm %s with key size %d", + enum_show(&esp_transformid_names, sa->encalg), + sa->enckeylen * BITS_PER_BYTE) + ) + attr->rta_type = XFRMA_ALG_CRYPT; + attr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + sa->enckeylen); + req.n.nlmsg_len += attr->rta_len; + + algo = (struct xfrm_algo*)RTA_DATA(attr); + algo->alg_key_len = sa->enckeylen * BITS_PER_BYTE; + strcpy(algo->alg_name, name); + memcpy(algo->alg_key, sa->enckey, sa->enckeylen); + + attr = (struct rtattr *)((char *)attr + attr->rta_len); + } } if (sa->compalg) diff --git a/src/pluto/spdb.c b/src/pluto/spdb.c index b8f4a3c23..a86c9f215 100644 --- a/src/pluto/spdb.c +++ b/src/pluto/spdb.c @@ -473,14 +473,13 @@ out_sa(pb_stream *outs if (!out_struct(&trans, trans_desc, &proposal_pbs, &trans_pbs)) return_on(ret, FALSE); - /* Within tranform: Attributes. */ + /* Within transform: Attributes. */ /* For Phase 2 / Quick Mode, GROUP_DESCRIPTION is * automatically generated because it must be the same * in every transform. Except IPCOMP. */ - if (p->protoid != PROTO_IPCOMP - && st->st_pfs_group != NULL) + if (p->protoid != PROTO_IPCOMP && st->st_pfs_group != NULL) { passert(!oakley_mode); passert(st->st_pfs_group != &unset_group); @@ -582,8 +581,7 @@ return_out: * The code is can only handle values that can fit in unsigned long. * "Clamping" is probably an acceptable way to impose this limitation. */ -static u_int32_t -decode_long_duration(pb_stream *pbs) +static u_int32_t decode_long_duration(pb_stream *pbs) { u_int32_t val = 0; @@ -631,8 +629,9 @@ preparse_isakmp_sa_body(const struct isakmp_sa *sa /* Situation */ if (!in_struct(ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL)) + { return SITUATION_NOT_SUPPORTED; - + } if (*ipsecdoisit != SIT_IDENTITY_ONLY) { loglog(RC_LOG_SERIOUS, "unsupported IPsec DOI situation (%s)" @@ -647,8 +646,9 @@ preparse_isakmp_sa_body(const struct isakmp_sa *sa * There may well be multiple transforms. */ if (!in_struct(proposal, &isakmp_proposal_desc, sa_pbs, proposal_pbs)) + { return PAYLOAD_MALFORMED; - + } if (proposal->isap_np != ISAKMP_NEXT_NONE) { loglog(RC_LOG_SERIOUS, "Proposal Payload must be alone in Oakley SA; found %s following Proposal" @@ -711,35 +711,31 @@ static struct { u_int8_t *roof; } backup; -/* - * backup the pointer into a pb_stream +/** + * Backup the pointer into a pb_stream */ -void -backup_pbs(pb_stream *pbs) +void backup_pbs(pb_stream *pbs) { backup.start = pbs->start; backup.cur = pbs->cur; backup.roof = pbs->roof; } -/* - * restore the pointer into a pb_stream +/** + * Restore the pointer into a pb_stream */ -void -restore_pbs(pb_stream *pbs) +void restore_pbs(pb_stream *pbs) { pbs->start = backup.start; pbs->cur = backup.cur; pbs->roof = backup.roof; } -/* +/** * Parse an ISAKMP Proposal Payload for RSA and PSK authentication policies */ -notification_t -parse_isakmp_policy(pb_stream *proposal_pbs - , u_int notrans - , lset_t *policy) +notification_t parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans, + lset_t *policy) { int last_transnum = -1; @@ -753,8 +749,9 @@ parse_isakmp_policy(pb_stream *proposal_pbs struct isakmp_transform trans; if (!in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs)) + { return BAD_PROPOSAL_SYNTAX; - + } if (trans.isat_transnum <= last_transnum) { /* picky, picky, picky */ @@ -781,8 +778,9 @@ parse_isakmp_policy(pb_stream *proposal_pbs pb_stream attr_pbs; if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs)) + { return BAD_PROPOSAL_SYNTAX; - + } passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32); switch (a.isaat_af_type) @@ -827,11 +825,10 @@ parse_isakmp_policy(pb_stream *proposal_pbs return NOTHING_WRONG; } -/* - * check that we can find a preshared secret +/** + * Check that we can find a preshared secret */ -static err_t -find_preshared_key(struct state* st) +static err_t find_preshared_key(struct state* st) { err_t ugh = NULL; struct connection *c = st->st_connection; @@ -842,9 +839,13 @@ find_preshared_key(struct state* st) idtoa(&c->spd.this.id, my_id, sizeof(my_id)); if (his_id_was_instantiated(c)) + { strcpy(his_id, "%any"); + } else + { idtoa(&c->spd.that.id, his_id, sizeof(his_id)); + } ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'" , my_id, his_id); } @@ -860,13 +861,12 @@ find_preshared_key(struct state* st) * * This routine is used by main_inI1_outR1() and main_inR1_outI2(). */ -notification_t -parse_isakmp_sa_body(u_int32_t ipsecdoisit - , pb_stream *proposal_pbs - , struct isakmp_proposal *proposal - , pb_stream *r_sa_pbs - , struct state *st - , bool initiator) +notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit, + pb_stream *proposal_pbs, + struct isakmp_proposal *proposal, + pb_stream *r_sa_pbs, + struct state *st, + bool initiator) { struct connection *c = st->st_connection; unsigned no_trans_left; @@ -1326,17 +1326,14 @@ static const struct ipsec_trans_attrs null_ipsec_trans_attrs = { 0, /* key_rounds */ }; -static bool -parse_ipsec_transform(struct isakmp_transform *trans -, struct ipsec_trans_attrs *attrs -, pb_stream *prop_pbs -, pb_stream *trans_pbs -, struct_desc *trans_desc -, int previous_transnum /* or -1 if none */ -, bool selection -, bool is_last -, bool is_ipcomp -, struct state *st) /* current state object */ +static bool parse_ipsec_transform(struct isakmp_transform *trans, + struct ipsec_trans_attrs *attrs, + pb_stream *prop_pbs, + pb_stream *trans_pbs, + struct_desc *trans_desc, + int previous_transnum, /* or -1 if none */ + bool selection, bool is_last, bool is_ipcomp, + struct state *st) /* current state object */ { lset_t seen_attrs = 0; lset_t seen_durations = 0; @@ -1344,8 +1341,9 @@ parse_ipsec_transform(struct isakmp_transform *trans const struct dh_desc *pfs_group = NULL; if (!in_struct(trans, trans_desc, prop_pbs, trans_pbs)) + { return FALSE; - + } if (trans->isat_transnum <= previous_transnum) { loglog(RC_LOG_SERIOUS, "Transform Numbers in Proposal are not monotonically increasing"); |