pluto supports AES_CCM and AES_GCM ESP algorithms
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 11 Jul 2009 16:43:09 +0000 (18:43 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 11 Jul 2009 22:05:42 +0000 (00:05 +0200)
src/pluto/alg_info.c
src/pluto/constants.c
src/pluto/ipsec_doi.c
src/pluto/kernel.c
src/pluto/kernel_alg.c
src/pluto/kernel_netlink.c
src/pluto/spdb.c

index a85a189..c25418f 100644 (file)
@@ -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);
                }
        }
 }
index adcd771..e46728d 100644 (file)
@@ -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 */
index 929768e..cac2244 100644 (file)
@@ -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;
index 7148abc..46edac1 100644 (file)
@@ -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;
index f56e7a7..7e7d258 100644 (file)
@@ -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;
 }
index ba87981..0376e81 100644 (file)
@@ -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)
index b8f4a3c..a86c9f2 100644 (file)
@@ -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");