LCOV - code coverage report
Current view: top level - src/eap_peer - ikev2.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 447 643 69.5 %
Date: 2014-05-28 Functions: 27 28 96.4 %

          Line data    Source code
       1             : /*
       2             :  * IKEv2 responder (RFC 4306) for EAP-IKEV2
       3             :  * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "crypto/dh_groups.h"
      13             : #include "crypto/random.h"
      14             : #include "ikev2.h"
      15             : 
      16             : 
      17           6 : void ikev2_responder_deinit(struct ikev2_responder_data *data)
      18             : {
      19           6 :         ikev2_free_keys(&data->keys);
      20           6 :         wpabuf_free(data->i_dh_public);
      21           6 :         wpabuf_free(data->r_dh_private);
      22           6 :         os_free(data->IDi);
      23           6 :         os_free(data->IDr);
      24           6 :         os_free(data->shared_secret);
      25           6 :         wpabuf_free(data->i_sign_msg);
      26           6 :         wpabuf_free(data->r_sign_msg);
      27           6 :         os_free(data->key_pad);
      28           6 : }
      29             : 
      30             : 
      31           6 : static int ikev2_derive_keys(struct ikev2_responder_data *data)
      32             : {
      33             :         u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN];
      34             :         size_t buf_len, pad_len;
      35             :         struct wpabuf *shared;
      36             :         const struct ikev2_integ_alg *integ;
      37             :         const struct ikev2_prf_alg *prf;
      38             :         const struct ikev2_encr_alg *encr;
      39             :         int ret;
      40             :         const u8 *addr[2];
      41             :         size_t len[2];
      42             : 
      43             :         /* RFC 4306, Sect. 2.14 */
      44             : 
      45           6 :         integ = ikev2_get_integ(data->proposal.integ);
      46           6 :         prf = ikev2_get_prf(data->proposal.prf);
      47           6 :         encr = ikev2_get_encr(data->proposal.encr);
      48           6 :         if (integ == NULL || prf == NULL || encr == NULL) {
      49           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal");
      50           0 :                 return -1;
      51             :         }
      52             : 
      53           6 :         shared = dh_derive_shared(data->i_dh_public, data->r_dh_private,
      54             :                                   data->dh);
      55           6 :         if (shared == NULL)
      56           0 :                 return -1;
      57             : 
      58             :         /* Construct Ni | Nr | SPIi | SPIr */
      59             : 
      60           6 :         buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN;
      61           6 :         buf = os_malloc(buf_len);
      62           6 :         if (buf == NULL) {
      63           0 :                 wpabuf_free(shared);
      64           0 :                 return -1;
      65             :         }
      66             : 
      67           6 :         pos = buf;
      68           6 :         os_memcpy(pos, data->i_nonce, data->i_nonce_len);
      69           6 :         pos += data->i_nonce_len;
      70           6 :         os_memcpy(pos, data->r_nonce, data->r_nonce_len);
      71           6 :         pos += data->r_nonce_len;
      72           6 :         os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN);
      73           6 :         pos += IKEV2_SPI_LEN;
      74           6 :         os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN);
      75             : #ifdef CCNS_PL
      76             : #if __BYTE_ORDER == __LITTLE_ENDIAN
      77             :         {
      78             :                 int i;
      79             :                 u8 *tmp = pos - IKEV2_SPI_LEN;
      80             :                 /* Incorrect byte re-ordering on little endian hosts.. */
      81             :                 for (i = 0; i < IKEV2_SPI_LEN; i++)
      82             :                         *tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i];
      83             :                 for (i = 0; i < IKEV2_SPI_LEN; i++)
      84             :                         *tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i];
      85             :         }
      86             : #endif
      87             : #endif /* CCNS_PL */
      88             : 
      89             :         /* SKEYSEED = prf(Ni | Nr, g^ir) */
      90             :         /* Use zero-padding per RFC 4306, Sect. 2.14 */
      91           6 :         pad_len = data->dh->prime_len - wpabuf_len(shared);
      92             : #ifdef CCNS_PL
      93             :         /* Shared secret is not zero-padded correctly */
      94             :         pad_len = 0;
      95             : #endif /* CCNS_PL */
      96           6 :         pad = os_zalloc(pad_len ? pad_len : 1);
      97           6 :         if (pad == NULL) {
      98           0 :                 wpabuf_free(shared);
      99           0 :                 os_free(buf);
     100           0 :                 return -1;
     101             :         }
     102             : 
     103           6 :         addr[0] = pad;
     104           6 :         len[0] = pad_len;
     105           6 :         addr[1] = wpabuf_head(shared);
     106           6 :         len[1] = wpabuf_len(shared);
     107           6 :         if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len,
     108             :                            2, addr, len, skeyseed) < 0) {
     109           0 :                 wpabuf_free(shared);
     110           0 :                 os_free(buf);
     111           0 :                 os_free(pad);
     112           0 :                 return -1;
     113             :         }
     114           6 :         os_free(pad);
     115           6 :         wpabuf_free(shared);
     116             : 
     117             :         /* DH parameters are not needed anymore, so free them */
     118           6 :         wpabuf_free(data->i_dh_public);
     119           6 :         data->i_dh_public = NULL;
     120           6 :         wpabuf_free(data->r_dh_private);
     121           6 :         data->r_dh_private = NULL;
     122             : 
     123           6 :         wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED",
     124             :                         skeyseed, prf->hash_len);
     125             : 
     126           6 :         ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len,
     127             :                                    &data->keys);
     128           6 :         os_free(buf);
     129           6 :         return ret;
     130             : }
     131             : 
     132             : 
     133          24 : static int ikev2_parse_transform(struct ikev2_proposal_data *prop,
     134             :                                  const u8 *pos, const u8 *end)
     135             : {
     136             :         int transform_len;
     137             :         const struct ikev2_transform *t;
     138             :         u16 transform_id;
     139             :         const u8 *tend;
     140             : 
     141          24 :         if (end - pos < (int) sizeof(*t)) {
     142           0 :                 wpa_printf(MSG_INFO, "IKEV2: Too short transform");
     143           0 :                 return -1;
     144             :         }
     145             : 
     146          24 :         t = (const struct ikev2_transform *) pos;
     147          24 :         transform_len = WPA_GET_BE16(t->transform_length);
     148          24 :         if (transform_len < (int) sizeof(*t) || pos + transform_len > end) {
     149           0 :                 wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d",
     150             :                            transform_len);
     151           0 :                 return -1;
     152             :         }
     153          24 :         tend = pos + transform_len;
     154             : 
     155          24 :         transform_id = WPA_GET_BE16(t->transform_id);
     156             : 
     157          24 :         wpa_printf(MSG_DEBUG, "IKEV2:   Transform:");
     158          72 :         wpa_printf(MSG_DEBUG, "IKEV2:     Type: %d  Transform Length: %d  "
     159             :                    "Transform Type: %d  Transform ID: %d",
     160          48 :                    t->type, transform_len, t->transform_type, transform_id);
     161             : 
     162          24 :         if (t->type != 0 && t->type != 3) {
     163           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type");
     164           0 :                 return -1;
     165             :         }
     166             : 
     167          24 :         pos = (const u8 *) (t + 1);
     168          24 :         if (pos < tend) {
     169           6 :                 wpa_hexdump(MSG_DEBUG, "IKEV2:     Transform Attributes",
     170           6 :                             pos, tend - pos);
     171             :         }
     172             : 
     173          24 :         switch (t->transform_type) {
     174             :         case IKEV2_TRANSFORM_ENCR:
     175           6 :                 if (ikev2_get_encr(transform_id)) {
     176           6 :                         if (transform_id == ENCR_AES_CBC) {
     177           6 :                                 if (tend - pos != 4) {
     178           0 :                                         wpa_printf(MSG_DEBUG, "IKEV2: No "
     179             :                                                    "Transform Attr for AES");
     180           0 :                                         break;
     181             :                                 }
     182             : #ifdef CCNS_PL
     183             :                                 if (WPA_GET_BE16(pos) != 0x001d /* ?? */) {
     184             :                                         wpa_printf(MSG_DEBUG, "IKEV2: Not a "
     185             :                                                    "Key Size attribute for "
     186             :                                                    "AES");
     187             :                                         break;
     188             :                                 }
     189             : #else /* CCNS_PL */
     190           6 :                                 if (WPA_GET_BE16(pos) != 0x800e) {
     191           0 :                                         wpa_printf(MSG_DEBUG, "IKEV2: Not a "
     192             :                                                    "Key Size attribute for "
     193             :                                                    "AES");
     194           0 :                                         break;
     195             :                                 }
     196             : #endif /* CCNS_PL */
     197           6 :                                 if (WPA_GET_BE16(pos + 2) != 128) {
     198           0 :                                         wpa_printf(MSG_DEBUG, "IKEV2: "
     199             :                                                    "Unsupported AES key size "
     200             :                                                    "%d bits",
     201           0 :                                                    WPA_GET_BE16(pos + 2));
     202           0 :                                         break;
     203             :                                 }
     204             :                         }
     205           6 :                         prop->encr = transform_id;
     206             :                 }
     207           6 :                 break;
     208             :         case IKEV2_TRANSFORM_PRF:
     209           6 :                 if (ikev2_get_prf(transform_id))
     210           6 :                         prop->prf = transform_id;
     211           6 :                 break;
     212             :         case IKEV2_TRANSFORM_INTEG:
     213           6 :                 if (ikev2_get_integ(transform_id))
     214           6 :                         prop->integ = transform_id;
     215           6 :                 break;
     216             :         case IKEV2_TRANSFORM_DH:
     217           6 :                 if (dh_groups_get(transform_id))
     218           6 :                         prop->dh = transform_id;
     219           6 :                 break;
     220             :         }
     221             : 
     222          24 :         return transform_len;
     223             : }
     224             : 
     225             : 
     226           6 : static int ikev2_parse_proposal(struct ikev2_proposal_data *prop,
     227             :                                 const u8 *pos, const u8 *end)
     228             : {
     229             :         const u8 *pend, *ppos;
     230             :         int proposal_len, i;
     231             :         const struct ikev2_proposal *p;
     232             : 
     233           6 :         if (end - pos < (int) sizeof(*p)) {
     234           0 :                 wpa_printf(MSG_INFO, "IKEV2: Too short proposal");
     235           0 :                 return -1;
     236             :         }
     237             : 
     238             :         /* FIX: AND processing if multiple proposals use the same # */
     239             : 
     240           6 :         p = (const struct ikev2_proposal *) pos;
     241           6 :         proposal_len = WPA_GET_BE16(p->proposal_length);
     242           6 :         if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) {
     243           0 :                 wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d",
     244             :                            proposal_len);
     245           0 :                 return -1;
     246             :         }
     247           6 :         wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d",
     248           6 :                    p->proposal_num);
     249          12 :         wpa_printf(MSG_DEBUG, "IKEV2:   Type: %d  Proposal Length: %d "
     250             :                    " Protocol ID: %d",
     251          12 :                    p->type, proposal_len, p->protocol_id);
     252          12 :         wpa_printf(MSG_DEBUG, "IKEV2:   SPI Size: %d  Transforms: %d",
     253          12 :                    p->spi_size, p->num_transforms);
     254             : 
     255           6 :         if (p->type != 0 && p->type != 2) {
     256           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type");
     257           0 :                 return -1;
     258             :         }
     259             : 
     260           6 :         if (p->protocol_id != IKEV2_PROTOCOL_IKE) {
     261           0 :                 wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID "
     262             :                            "(only IKE allowed for EAP-IKEv2)");
     263           0 :                 return -1;
     264             :         }
     265             : 
     266           6 :         if (p->proposal_num != prop->proposal_num) {
     267           0 :                 if (p->proposal_num == prop->proposal_num + 1)
     268           0 :                         prop->proposal_num = p->proposal_num;
     269             :                 else {
     270           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #");
     271           0 :                         return -1;
     272             :                 }
     273             :         }
     274             : 
     275           6 :         ppos = (const u8 *) (p + 1);
     276           6 :         pend = pos + proposal_len;
     277           6 :         if (ppos + p->spi_size > pend) {
     278           0 :                 wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI "
     279             :                            "in proposal");
     280           0 :                 return -1;
     281             :         }
     282           6 :         if (p->spi_size) {
     283           0 :                 wpa_hexdump(MSG_DEBUG, "IKEV2:    SPI",
     284           0 :                             ppos, p->spi_size);
     285           0 :                 ppos += p->spi_size;
     286             :         }
     287             : 
     288             :         /*
     289             :          * For initial IKE_SA negotiation, SPI Size MUST be zero; for
     290             :          * subsequent negotiations, it must be 8 for IKE. We only support
     291             :          * initial case for now.
     292             :          */
     293           6 :         if (p->spi_size != 0) {
     294           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size");
     295           0 :                 return -1;
     296             :         }
     297             : 
     298           6 :         if (p->num_transforms == 0) {
     299           0 :                 wpa_printf(MSG_INFO, "IKEV2: At least one transform required");
     300           0 :                 return -1;
     301             :         }
     302             : 
     303          30 :         for (i = 0; i < (int) p->num_transforms; i++) {
     304          24 :                 int tlen = ikev2_parse_transform(prop, ppos, pend);
     305          24 :                 if (tlen < 0)
     306           0 :                         return -1;
     307          24 :                 ppos += tlen;
     308             :         }
     309             : 
     310           6 :         if (ppos != pend) {
     311           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unexpected data after "
     312             :                            "transforms");
     313           0 :                 return -1;
     314             :         }
     315             : 
     316           6 :         return proposal_len;
     317             : }
     318             : 
     319             : 
     320           6 : static int ikev2_process_sai1(struct ikev2_responder_data *data,
     321             :                               const u8 *sai1, size_t sai1_len)
     322             : {
     323             :         struct ikev2_proposal_data prop;
     324             :         const u8 *pos, *end;
     325           6 :         int found = 0;
     326             : 
     327             :         /* Security Association Payloads: <Proposals> */
     328             : 
     329           6 :         if (sai1 == NULL) {
     330           0 :                 wpa_printf(MSG_INFO, "IKEV2: SAi1 not received");
     331           0 :                 return -1;
     332             :         }
     333             : 
     334           6 :         os_memset(&prop, 0, sizeof(prop));
     335           6 :         prop.proposal_num = 1;
     336             : 
     337           6 :         pos = sai1;
     338           6 :         end = sai1 + sai1_len;
     339             : 
     340          18 :         while (pos < end) {
     341             :                 int plen;
     342             : 
     343           6 :                 prop.integ = -1;
     344           6 :                 prop.prf = -1;
     345           6 :                 prop.encr = -1;
     346           6 :                 prop.dh = -1;
     347           6 :                 plen = ikev2_parse_proposal(&prop, pos, end);
     348           6 :                 if (plen < 0)
     349           0 :                         return -1;
     350             : 
     351          12 :                 if (!found && prop.integ != -1 && prop.prf != -1 &&
     352          12 :                     prop.encr != -1 && prop.dh != -1) {
     353           6 :                         os_memcpy(&data->proposal, &prop, sizeof(prop));
     354           6 :                         data->dh = dh_groups_get(prop.dh);
     355           6 :                         found = 1;
     356             :                 }
     357             : 
     358           6 :                 pos += plen;
     359             :         }
     360             : 
     361           6 :         if (pos != end) {
     362           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposals");
     363           0 :                 return -1;
     364             :         }
     365             : 
     366           6 :         if (!found) {
     367           0 :                 wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found");
     368           0 :                 return -1;
     369             :         }
     370             : 
     371          12 :         wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d "
     372           6 :                    "INTEG:%d D-H:%d", data->proposal.proposal_num,
     373             :                    data->proposal.encr, data->proposal.prf,
     374             :                    data->proposal.integ, data->proposal.dh);
     375             : 
     376           6 :         return 0;
     377             : }
     378             : 
     379             : 
     380           6 : static int ikev2_process_kei(struct ikev2_responder_data *data,
     381             :                              const u8 *kei, size_t kei_len)
     382             : {
     383             :         u16 group;
     384             : 
     385             :         /*
     386             :          * Key Exchange Payload:
     387             :          * DH Group # (16 bits)
     388             :          * RESERVED (16 bits)
     389             :          * Key Exchange Data (Diffie-Hellman public value)
     390             :          */
     391             : 
     392           6 :         if (kei == NULL) {
     393           0 :                 wpa_printf(MSG_INFO, "IKEV2: KEi not received");
     394           0 :                 return -1;
     395             :         }
     396             : 
     397           6 :         if (kei_len < 4 + 96) {
     398           0 :                 wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload");
     399           0 :                 return -1;
     400             :         }
     401             : 
     402           6 :         group = WPA_GET_BE16(kei);
     403           6 :         wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u", group);
     404             : 
     405           6 :         if (group != data->proposal.dh) {
     406           0 :                 wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u does not match "
     407             :                            "with the selected proposal (%u)",
     408             :                            group, data->proposal.dh);
     409             :                 /* Reject message with Notify payload of type
     410             :                  * INVALID_KE_PAYLOAD (RFC 4306, Sect. 3.4) */
     411           0 :                 data->error_type = INVALID_KE_PAYLOAD;
     412           0 :                 data->state = NOTIFY;
     413           0 :                 return -1;
     414             :         }
     415             : 
     416           6 :         if (data->dh == NULL) {
     417           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group");
     418           0 :                 return -1;
     419             :         }
     420             : 
     421             :         /* RFC 4306, Section 3.4:
     422             :          * The length of DH public value MUST be equal to the length of the
     423             :          * prime modulus.
     424             :          */
     425           6 :         if (kei_len - 4 != data->dh->prime_len) {
     426           0 :                 wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length "
     427             :                            "%ld (expected %ld)",
     428           0 :                            (long) (kei_len - 4), (long) data->dh->prime_len);
     429           0 :                 return -1;
     430             :         }
     431             : 
     432           6 :         wpabuf_free(data->i_dh_public);
     433           6 :         data->i_dh_public = wpabuf_alloc(kei_len - 4);
     434           6 :         if (data->i_dh_public == NULL)
     435           0 :                 return -1;
     436           6 :         wpabuf_put_data(data->i_dh_public, kei + 4, kei_len - 4);
     437             : 
     438           6 :         wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value",
     439           6 :                         data->i_dh_public);
     440             :         
     441           6 :         return 0;
     442             : }
     443             : 
     444             : 
     445           6 : static int ikev2_process_ni(struct ikev2_responder_data *data,
     446             :                             const u8 *ni, size_t ni_len)
     447             : {
     448           6 :         if (ni == NULL) {
     449           0 :                 wpa_printf(MSG_INFO, "IKEV2: Ni not received");
     450           0 :                 return -1;
     451             :         }
     452             : 
     453           6 :         if (ni_len < IKEV2_NONCE_MIN_LEN || ni_len > IKEV2_NONCE_MAX_LEN) {
     454           0 :                 wpa_printf(MSG_INFO, "IKEV2: Invalid Ni length %ld",
     455             :                            (long) ni_len);
     456           0 :                 return -1;
     457             :         }
     458             : 
     459             : #ifdef CCNS_PL
     460             :         /* Zeros are removed incorrectly from the beginning of the nonces */
     461             :         while (ni_len > 1 && *ni == 0) {
     462             :                 ni_len--;
     463             :                 ni++;
     464             :         }
     465             : #endif /* CCNS_PL */
     466             : 
     467           6 :         data->i_nonce_len = ni_len;
     468           6 :         os_memcpy(data->i_nonce, ni, ni_len);
     469          12 :         wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni",
     470           6 :                     data->i_nonce, data->i_nonce_len);
     471             : 
     472           6 :         return 0;
     473             : }
     474             : 
     475             : 
     476           6 : static int ikev2_process_sa_init(struct ikev2_responder_data *data,
     477             :                                  const struct ikev2_hdr *hdr,
     478             :                                  struct ikev2_payloads *pl)
     479             : {
     480          12 :         if (ikev2_process_sai1(data, pl->sa, pl->sa_len) < 0 ||
     481          12 :             ikev2_process_kei(data, pl->ke, pl->ke_len) < 0 ||
     482           6 :             ikev2_process_ni(data, pl->nonce, pl->nonce_len) < 0)
     483           0 :                 return -1;
     484             : 
     485           6 :         os_memcpy(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN);
     486             : 
     487           6 :         return 0;
     488             : }
     489             : 
     490             : 
     491           6 : static int ikev2_process_idi(struct ikev2_responder_data *data,
     492             :                              const u8 *idi, size_t idi_len)
     493             : {
     494             :         u8 id_type;
     495             : 
     496           6 :         if (idi == NULL) {
     497           0 :                 wpa_printf(MSG_INFO, "IKEV2: No IDi received");
     498           0 :                 return -1;
     499             :         }
     500             : 
     501           6 :         if (idi_len < 4) {
     502           0 :                 wpa_printf(MSG_INFO, "IKEV2: Too short IDi payload");
     503           0 :                 return -1;
     504             :         }
     505             : 
     506           6 :         id_type = idi[0];
     507           6 :         idi += 4;
     508           6 :         idi_len -= 4;
     509             : 
     510           6 :         wpa_printf(MSG_DEBUG, "IKEV2: IDi ID Type %d", id_type);
     511           6 :         wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDi", idi, idi_len);
     512           6 :         os_free(data->IDi);
     513           6 :         data->IDi = os_malloc(idi_len);
     514           6 :         if (data->IDi == NULL)
     515           0 :                 return -1;
     516           6 :         os_memcpy(data->IDi, idi, idi_len);
     517           6 :         data->IDi_len = idi_len;
     518           6 :         data->IDi_type = id_type;
     519             : 
     520           6 :         return 0;
     521             : }
     522             : 
     523             : 
     524           6 : static int ikev2_process_cert(struct ikev2_responder_data *data,
     525             :                               const u8 *cert, size_t cert_len)
     526             : {
     527             :         u8 cert_encoding;
     528             : 
     529           6 :         if (cert == NULL) {
     530           6 :                 if (data->peer_auth == PEER_AUTH_CERT) {
     531           0 :                         wpa_printf(MSG_INFO, "IKEV2: No Certificate received");
     532           0 :                         return -1;
     533             :                 }
     534           6 :                 return 0;
     535             :         }
     536             : 
     537           0 :         if (cert_len < 1) {
     538           0 :                 wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field");
     539           0 :                 return -1;
     540             :         }
     541             : 
     542           0 :         cert_encoding = cert[0];
     543           0 :         cert++;
     544           0 :         cert_len--;
     545             : 
     546           0 :         wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding);
     547           0 :         wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len);
     548             : 
     549             :         /* TODO: validate certificate */
     550             : 
     551           0 :         return 0;
     552             : }
     553             : 
     554             : 
     555           0 : static int ikev2_process_auth_cert(struct ikev2_responder_data *data,
     556             :                                    u8 method, const u8 *auth, size_t auth_len)
     557             : {
     558           0 :         if (method != AUTH_RSA_SIGN) {
     559           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "
     560             :                            "method %d", method);
     561           0 :                 return -1;
     562             :         }
     563             : 
     564             :         /* TODO: validate AUTH */
     565           0 :         return 0;
     566             : }
     567             : 
     568             : 
     569           6 : static int ikev2_process_auth_secret(struct ikev2_responder_data *data,
     570             :                                      u8 method, const u8 *auth,
     571             :                                      size_t auth_len)
     572             : {
     573             :         u8 auth_data[IKEV2_MAX_HASH_LEN];
     574             :         const struct ikev2_prf_alg *prf;
     575             : 
     576           6 :         if (method != AUTH_SHARED_KEY_MIC) {
     577           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "
     578             :                            "method %d", method);
     579           0 :                 return -1;
     580             :         }
     581             : 
     582             :         /* msg | Nr | prf(SK_pi,IDi') */
     583          36 :         if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg,
     584          12 :                                    data->IDi, data->IDi_len, data->IDi_type,
     585           6 :                                    &data->keys, 1, data->shared_secret,
     586             :                                    data->shared_secret_len,
     587           6 :                                    data->r_nonce, data->r_nonce_len,
     588           6 :                                    data->key_pad, data->key_pad_len,
     589             :                                    auth_data) < 0) {
     590           0 :                 wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");
     591           0 :                 return -1;
     592             :         }
     593             : 
     594           6 :         wpabuf_free(data->i_sign_msg);
     595           6 :         data->i_sign_msg = NULL;
     596             : 
     597           6 :         prf = ikev2_get_prf(data->proposal.prf);
     598           6 :         if (prf == NULL)
     599           0 :                 return -1;
     600             : 
     601          12 :         if (auth_len != prf->hash_len ||
     602           6 :             os_memcmp(auth, auth_data, auth_len) != 0) {
     603           1 :                 wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data");
     604           1 :                 wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data",
     605             :                             auth, auth_len);
     606           1 :                 wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data",
     607             :                             auth_data, prf->hash_len);
     608           1 :                 data->error_type = AUTHENTICATION_FAILED;
     609           1 :                 data->state = NOTIFY;
     610           1 :                 return -1;
     611             :         }
     612             : 
     613           5 :         wpa_printf(MSG_DEBUG, "IKEV2: Server authenticated successfully "
     614             :                    "using shared keys");
     615             : 
     616           5 :         return 0;
     617             : }
     618             : 
     619             : 
     620           6 : static int ikev2_process_auth(struct ikev2_responder_data *data,
     621             :                               const u8 *auth, size_t auth_len)
     622             : {
     623             :         u8 auth_method;
     624             : 
     625           6 :         if (auth == NULL) {
     626           0 :                 wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload");
     627           0 :                 return -1;
     628             :         }
     629             : 
     630           6 :         if (auth_len < 4) {
     631           0 :                 wpa_printf(MSG_INFO, "IKEV2: Too short Authentication "
     632             :                            "Payload");
     633           0 :                 return -1;
     634             :         }
     635             : 
     636           6 :         auth_method = auth[0];
     637           6 :         auth += 4;
     638           6 :         auth_len -= 4;
     639             : 
     640           6 :         wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method);
     641           6 :         wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len);
     642             : 
     643           6 :         switch (data->peer_auth) {
     644             :         case PEER_AUTH_CERT:
     645           0 :                 return ikev2_process_auth_cert(data, auth_method, auth,
     646             :                                                auth_len);
     647             :         case PEER_AUTH_SECRET:
     648           6 :                 return ikev2_process_auth_secret(data, auth_method, auth,
     649             :                                                  auth_len);
     650             :         }
     651             : 
     652           0 :         return -1;
     653             : }
     654             : 
     655             : 
     656           6 : static int ikev2_process_sa_auth_decrypted(struct ikev2_responder_data *data,
     657             :                                            u8 next_payload,
     658             :                                            u8 *payload, size_t payload_len)
     659             : {
     660             :         struct ikev2_payloads pl;
     661             : 
     662           6 :         wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads");
     663             : 
     664           6 :         if (ikev2_parse_payloads(&pl, next_payload, payload, payload +
     665             :                                  payload_len) < 0) {
     666           0 :                 wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted "
     667             :                            "payloads");
     668           0 :                 return -1;
     669             :         }
     670             : 
     671          12 :         if (ikev2_process_idi(data, pl.idi, pl.idi_len) < 0 ||
     672          12 :             ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 ||
     673           6 :             ikev2_process_auth(data, pl.auth, pl.auth_len) < 0)
     674           1 :                 return -1;
     675             : 
     676           5 :         return 0;
     677             : }
     678             : 
     679             : 
     680           6 : static int ikev2_process_sa_auth(struct ikev2_responder_data *data,
     681             :                                  const struct ikev2_hdr *hdr,
     682             :                                  struct ikev2_payloads *pl)
     683             : {
     684             :         u8 *decrypted;
     685             :         size_t decrypted_len;
     686             :         int ret;
     687             : 
     688           6 :         decrypted = ikev2_decrypt_payload(data->proposal.encr,
     689             :                                           data->proposal.integ,
     690             :                                           &data->keys, 1, hdr, pl->encrypted,
     691             :                                           pl->encrypted_len, &decrypted_len);
     692           6 :         if (decrypted == NULL)
     693           0 :                 return -1;
     694             : 
     695           6 :         ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload,
     696             :                                               decrypted, decrypted_len);
     697           6 :         os_free(decrypted);
     698             : 
     699           6 :         return ret;
     700             : }
     701             : 
     702             : 
     703          12 : static int ikev2_validate_rx_state(struct ikev2_responder_data *data,
     704             :                                    u8 exchange_type, u32 message_id)
     705             : {
     706          12 :         switch (data->state) {
     707             :         case SA_INIT:
     708             :                 /* Expect to receive IKE_SA_INIT: HDR, SAi1, KEi, Ni */
     709           6 :                 if (exchange_type != IKE_SA_INIT) {
     710           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
     711             :                                    "%u in SA_INIT state", exchange_type);
     712           0 :                         return -1;
     713             :                 }
     714           6 :                 if (message_id != 0) {
     715           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
     716             :                                    "in SA_INIT state", message_id);
     717           0 :                         return -1;
     718             :                 }
     719           6 :                 break;
     720             :         case SA_AUTH:
     721             :                 /* Expect to receive IKE_SA_AUTH:
     722             :                  * HDR, SK {IDi, [CERT,] [CERTREQ,] [IDr,]
     723             :                  *      AUTH, SAi2, TSi, TSr}
     724             :                  */
     725           6 :                 if (exchange_type != IKE_SA_AUTH) {
     726           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
     727             :                                    "%u in SA_AUTH state", exchange_type);
     728           0 :                         return -1;
     729             :                 }
     730           6 :                 if (message_id != 1) {
     731           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
     732             :                                    "in SA_AUTH state", message_id);
     733           0 :                         return -1;
     734             :                 }
     735           6 :                 break;
     736             :         case CHILD_SA:
     737           0 :                 if (exchange_type != CREATE_CHILD_SA) {
     738           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
     739             :                                    "%u in CHILD_SA state", exchange_type);
     740           0 :                         return -1;
     741             :                 }
     742           0 :                 if (message_id != 2) {
     743           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
     744             :                                    "in CHILD_SA state", message_id);
     745           0 :                         return -1;
     746             :                 }
     747           0 :                 break;
     748             :         case NOTIFY:
     749             :         case IKEV2_DONE:
     750             :         case IKEV2_FAILED:
     751           0 :                 return -1;
     752             :         }
     753             : 
     754          12 :         return 0;
     755             : }
     756             : 
     757             : 
     758          12 : int ikev2_responder_process(struct ikev2_responder_data *data,
     759             :                             const struct wpabuf *buf)
     760             : {
     761             :         const struct ikev2_hdr *hdr;
     762             :         u32 length, message_id;
     763             :         const u8 *pos, *end;
     764             :         struct ikev2_payloads pl;
     765             : 
     766          12 :         wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)",
     767             :                    (unsigned long) wpabuf_len(buf));
     768             : 
     769          12 :         if (wpabuf_len(buf) < sizeof(*hdr)) {
     770           0 :                 wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR");
     771           0 :                 return -1;
     772             :         }
     773             : 
     774          12 :         data->error_type = 0;
     775          12 :         hdr = (const struct ikev2_hdr *) wpabuf_head(buf);
     776          12 :         end = wpabuf_head_u8(buf) + wpabuf_len(buf);
     777          12 :         message_id = WPA_GET_BE32(hdr->message_id);
     778          12 :         length = WPA_GET_BE32(hdr->length);
     779             : 
     780          12 :         wpa_hexdump(MSG_DEBUG, "IKEV2:   IKE_SA Initiator's SPI",
     781          12 :                     hdr->i_spi, IKEV2_SPI_LEN);
     782          12 :         wpa_hexdump(MSG_DEBUG, "IKEV2:   IKE_SA Responder's SPI",
     783          12 :                     hdr->r_spi, IKEV2_SPI_LEN);
     784          36 :         wpa_printf(MSG_DEBUG, "IKEV2:   Next Payload: %u  Version: 0x%x  "
     785             :                    "Exchange Type: %u",
     786          36 :                    hdr->next_payload, hdr->version, hdr->exchange_type);
     787          12 :         wpa_printf(MSG_DEBUG, "IKEV2:   Message ID: %u  Length: %u",
     788             :                    message_id, length);
     789             : 
     790          12 :         if (hdr->version != IKEV2_VERSION) {
     791           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x "
     792           0 :                            "(expected 0x%x)", hdr->version, IKEV2_VERSION);
     793           0 :                 return -1;
     794             :         }
     795             : 
     796          12 :         if (length != wpabuf_len(buf)) {
     797           0 :                 wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != "
     798             :                            "RX: %lu)", (unsigned long) length,
     799             :                            (unsigned long) wpabuf_len(buf));
     800           0 :                 return -1;
     801             :         }
     802             : 
     803          12 :         if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0)
     804           0 :                 return -1;
     805             : 
     806          12 :         if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) !=
     807             :             IKEV2_HDR_INITIATOR) {
     808           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x",
     809           0 :                            hdr->flags);
     810           0 :                 return -1;
     811             :         }
     812             : 
     813          12 :         if (data->state != SA_INIT) {
     814           6 :                 if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) {
     815           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "
     816             :                                    "Initiator's SPI");
     817           0 :                         return -1;
     818             :                 }
     819           6 :                 if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) {
     820           0 :                         wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "
     821             :                                    "Responder's SPI");
     822           0 :                         return -1;
     823             :                 }
     824             :         }
     825             : 
     826          12 :         pos = (const u8 *) (hdr + 1);
     827          12 :         if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0)
     828           0 :                 return -1;
     829             : 
     830          12 :         if (data->state == SA_INIT) {
     831           6 :                 data->last_msg = LAST_MSG_SA_INIT;
     832           6 :                 if (ikev2_process_sa_init(data, hdr, &pl) < 0) {
     833           0 :                         if (data->state == NOTIFY)
     834           0 :                                 return 0;
     835           0 :                         return -1;
     836             :                 }
     837           6 :                 wpabuf_free(data->i_sign_msg);
     838           6 :                 data->i_sign_msg = wpabuf_dup(buf);
     839             :         }
     840             : 
     841          12 :         if (data->state == SA_AUTH) {
     842           6 :                 data->last_msg = LAST_MSG_SA_AUTH;
     843           6 :                 if (ikev2_process_sa_auth(data, hdr, &pl) < 0) {
     844           1 :                         if (data->state == NOTIFY)
     845           1 :                                 return 0;
     846           0 :                         return -1;
     847             :                 }
     848             :         }
     849             : 
     850          11 :         return 0;
     851             : }
     852             : 
     853             : 
     854          12 : static void ikev2_build_hdr(struct ikev2_responder_data *data,
     855             :                             struct wpabuf *msg, u8 exchange_type,
     856             :                             u8 next_payload, u32 message_id)
     857             : {
     858             :         struct ikev2_hdr *hdr;
     859             : 
     860          12 :         wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR");
     861             : 
     862             :         /* HDR - RFC 4306, Sect. 3.1 */
     863          12 :         hdr = wpabuf_put(msg, sizeof(*hdr));
     864          12 :         os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN);
     865          12 :         os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN);
     866          12 :         hdr->next_payload = next_payload;
     867          12 :         hdr->version = IKEV2_VERSION;
     868          12 :         hdr->exchange_type = exchange_type;
     869          12 :         hdr->flags = IKEV2_HDR_RESPONSE;
     870          12 :         WPA_PUT_BE32(hdr->message_id, message_id);
     871          12 : }
     872             : 
     873             : 
     874           6 : static int ikev2_build_sar1(struct ikev2_responder_data *data,
     875             :                             struct wpabuf *msg, u8 next_payload)
     876             : {
     877             :         struct ikev2_payload_hdr *phdr;
     878             :         size_t plen;
     879             :         struct ikev2_proposal *p;
     880             :         struct ikev2_transform *t;
     881             : 
     882           6 :         wpa_printf(MSG_DEBUG, "IKEV2: Adding SAr1 payload");
     883             : 
     884             :         /* SAr1 - RFC 4306, Sect. 2.7 and 3.3 */
     885           6 :         phdr = wpabuf_put(msg, sizeof(*phdr));
     886           6 :         phdr->next_payload = next_payload;
     887           6 :         phdr->flags = 0;
     888             : 
     889           6 :         p = wpabuf_put(msg, sizeof(*p));
     890             : #ifdef CCNS_PL
     891             :         /* Seems to require that the Proposal # is 1 even though RFC 4306
     892             :          * Sect 3.3.1 has following requirement "When a proposal is accepted,
     893             :          * all of the proposal numbers in the SA payload MUST be the same and
     894             :          * MUST match the number on the proposal sent that was accepted.".
     895             :          */
     896             :         p->proposal_num = 1;
     897             : #else /* CCNS_PL */
     898           6 :         p->proposal_num = data->proposal.proposal_num;
     899             : #endif /* CCNS_PL */
     900           6 :         p->protocol_id = IKEV2_PROTOCOL_IKE;
     901           6 :         p->num_transforms = 4;
     902             : 
     903           6 :         t = wpabuf_put(msg, sizeof(*t));
     904           6 :         t->type = 3;
     905           6 :         t->transform_type = IKEV2_TRANSFORM_ENCR;
     906           6 :         WPA_PUT_BE16(t->transform_id, data->proposal.encr);
     907           6 :         if (data->proposal.encr == ENCR_AES_CBC) {
     908             :                 /* Transform Attribute: Key Len = 128 bits */
     909             : #ifdef CCNS_PL
     910             :                 wpabuf_put_be16(msg, 0x001d); /* ?? */
     911             : #else /* CCNS_PL */
     912           6 :                 wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */
     913             : #endif /* CCNS_PL */
     914           6 :                 wpabuf_put_be16(msg, 128); /* 128-bit key */
     915             :         }
     916           6 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t;
     917           6 :         WPA_PUT_BE16(t->transform_length, plen);
     918             : 
     919           6 :         t = wpabuf_put(msg, sizeof(*t));
     920           6 :         t->type = 3;
     921           6 :         WPA_PUT_BE16(t->transform_length, sizeof(*t));
     922           6 :         t->transform_type = IKEV2_TRANSFORM_PRF;
     923           6 :         WPA_PUT_BE16(t->transform_id, data->proposal.prf);
     924             : 
     925           6 :         t = wpabuf_put(msg, sizeof(*t));
     926           6 :         t->type = 3;
     927           6 :         WPA_PUT_BE16(t->transform_length, sizeof(*t));
     928           6 :         t->transform_type = IKEV2_TRANSFORM_INTEG;
     929           6 :         WPA_PUT_BE16(t->transform_id, data->proposal.integ);
     930             : 
     931           6 :         t = wpabuf_put(msg, sizeof(*t));
     932           6 :         WPA_PUT_BE16(t->transform_length, sizeof(*t));
     933           6 :         t->transform_type = IKEV2_TRANSFORM_DH;
     934           6 :         WPA_PUT_BE16(t->transform_id, data->proposal.dh);
     935             : 
     936           6 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p;
     937           6 :         WPA_PUT_BE16(p->proposal_length, plen);
     938             : 
     939           6 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
     940           6 :         WPA_PUT_BE16(phdr->payload_length, plen);
     941             : 
     942           6 :         return 0;
     943             : }
     944             : 
     945             : 
     946           6 : static int ikev2_build_ker(struct ikev2_responder_data *data,
     947             :                            struct wpabuf *msg, u8 next_payload)
     948             : {
     949             :         struct ikev2_payload_hdr *phdr;
     950             :         size_t plen;
     951             :         struct wpabuf *pv;
     952             : 
     953           6 :         wpa_printf(MSG_DEBUG, "IKEV2: Adding KEr payload");
     954             : 
     955           6 :         pv = dh_init(data->dh, &data->r_dh_private);
     956           6 :         if (pv == NULL) {
     957           0 :                 wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH");
     958           0 :                 return -1;
     959             :         }
     960             : 
     961             :         /* KEr - RFC 4306, Sect. 3.4 */
     962           6 :         phdr = wpabuf_put(msg, sizeof(*phdr));
     963           6 :         phdr->next_payload = next_payload;
     964           6 :         phdr->flags = 0;
     965             : 
     966           6 :         wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */
     967           6 :         wpabuf_put(msg, 2); /* RESERVED */
     968             :         /*
     969             :          * RFC 4306, Sect. 3.4: possible zero padding for public value to
     970             :          * match the length of the prime.
     971             :          */
     972           6 :         wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv));
     973           6 :         wpabuf_put_buf(msg, pv);
     974           6 :         wpabuf_free(pv);
     975             : 
     976           6 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
     977           6 :         WPA_PUT_BE16(phdr->payload_length, plen);
     978           6 :         return 0;
     979             : }
     980             : 
     981             : 
     982           6 : static int ikev2_build_nr(struct ikev2_responder_data *data,
     983             :                           struct wpabuf *msg, u8 next_payload)
     984             : {
     985             :         struct ikev2_payload_hdr *phdr;
     986             :         size_t plen;
     987             : 
     988           6 :         wpa_printf(MSG_DEBUG, "IKEV2: Adding Nr payload");
     989             : 
     990             :         /* Nr - RFC 4306, Sect. 3.9 */
     991           6 :         phdr = wpabuf_put(msg, sizeof(*phdr));
     992           6 :         phdr->next_payload = next_payload;
     993           6 :         phdr->flags = 0;
     994           6 :         wpabuf_put_data(msg, data->r_nonce, data->r_nonce_len);
     995           6 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
     996           6 :         WPA_PUT_BE16(phdr->payload_length, plen);
     997           6 :         return 0;
     998             : }
     999             : 
    1000             : 
    1001          11 : static int ikev2_build_idr(struct ikev2_responder_data *data,
    1002             :                            struct wpabuf *msg, u8 next_payload)
    1003             : {
    1004             :         struct ikev2_payload_hdr *phdr;
    1005             :         size_t plen;
    1006             : 
    1007          11 :         wpa_printf(MSG_DEBUG, "IKEV2: Adding IDr payload");
    1008             : 
    1009          11 :         if (data->IDr == NULL) {
    1010           0 :                 wpa_printf(MSG_INFO, "IKEV2: No IDr available");
    1011           0 :                 return -1;
    1012             :         }
    1013             : 
    1014             :         /* IDr - RFC 4306, Sect. 3.5 */
    1015          11 :         phdr = wpabuf_put(msg, sizeof(*phdr));
    1016          11 :         phdr->next_payload = next_payload;
    1017          11 :         phdr->flags = 0;
    1018          11 :         wpabuf_put_u8(msg, ID_KEY_ID);
    1019          11 :         wpabuf_put(msg, 3); /* RESERVED */
    1020          11 :         wpabuf_put_data(msg, data->IDr, data->IDr_len);
    1021          11 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
    1022          11 :         WPA_PUT_BE16(phdr->payload_length, plen);
    1023          11 :         return 0;
    1024             : }
    1025             : 
    1026             : 
    1027           5 : static int ikev2_build_auth(struct ikev2_responder_data *data,
    1028             :                             struct wpabuf *msg, u8 next_payload)
    1029             : {
    1030             :         struct ikev2_payload_hdr *phdr;
    1031             :         size_t plen;
    1032             :         const struct ikev2_prf_alg *prf;
    1033             : 
    1034           5 :         wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload");
    1035             : 
    1036           5 :         prf = ikev2_get_prf(data->proposal.prf);
    1037           5 :         if (prf == NULL)
    1038           0 :                 return -1;
    1039             : 
    1040             :         /* Authentication - RFC 4306, Sect. 3.8 */
    1041           5 :         phdr = wpabuf_put(msg, sizeof(*phdr));
    1042           5 :         phdr->next_payload = next_payload;
    1043           5 :         phdr->flags = 0;
    1044           5 :         wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC);
    1045           5 :         wpabuf_put(msg, 3); /* RESERVED */
    1046             : 
    1047             :         /* msg | Ni | prf(SK_pr,IDr') */
    1048          25 :         if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg,
    1049           5 :                                    data->IDr, data->IDr_len, ID_KEY_ID,
    1050           5 :                                    &data->keys, 0, data->shared_secret,
    1051             :                                    data->shared_secret_len,
    1052           5 :                                    data->i_nonce, data->i_nonce_len,
    1053           5 :                                    data->key_pad, data->key_pad_len,
    1054           5 :                                    wpabuf_put(msg, prf->hash_len)) < 0) {
    1055           0 :                 wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");
    1056           0 :                 return -1;
    1057             :         }
    1058           5 :         wpabuf_free(data->r_sign_msg);
    1059           5 :         data->r_sign_msg = NULL;
    1060             : 
    1061           5 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
    1062           5 :         WPA_PUT_BE16(phdr->payload_length, plen);
    1063           5 :         return 0;
    1064             : }
    1065             : 
    1066             : 
    1067           1 : static int ikev2_build_notification(struct ikev2_responder_data *data,
    1068             :                                     struct wpabuf *msg, u8 next_payload)
    1069             : {
    1070             :         struct ikev2_payload_hdr *phdr;
    1071             :         size_t plen;
    1072             : 
    1073           1 :         wpa_printf(MSG_DEBUG, "IKEV2: Adding Notification payload");
    1074             : 
    1075           1 :         if (data->error_type == 0) {
    1076           0 :                 wpa_printf(MSG_INFO, "IKEV2: No Notify Message Type "
    1077             :                            "available");
    1078           0 :                 return -1;
    1079             :         }
    1080             : 
    1081             :         /* Notify - RFC 4306, Sect. 3.10 */
    1082           1 :         phdr = wpabuf_put(msg, sizeof(*phdr));
    1083           1 :         phdr->next_payload = next_payload;
    1084           1 :         phdr->flags = 0;
    1085             : #ifdef CCNS_PL
    1086             :         wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */
    1087             : #else /* CCNS_PL */
    1088           1 :         wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */
    1089             : #endif /* CCNS_PL */
    1090           1 :         wpabuf_put_u8(msg, 0); /* SPI Size */
    1091           1 :         wpabuf_put_be16(msg, data->error_type);
    1092             : 
    1093           1 :         switch (data->error_type) {
    1094             :         case INVALID_KE_PAYLOAD:
    1095           0 :                 if (data->proposal.dh == -1) {
    1096           0 :                         wpa_printf(MSG_INFO, "IKEV2: No DH Group selected for "
    1097             :                                    "INVALID_KE_PAYLOAD notifications");
    1098           0 :                         return -1;
    1099             :                 }
    1100           0 :                 wpabuf_put_be16(msg, data->proposal.dh);
    1101           0 :                 wpa_printf(MSG_DEBUG, "IKEV2: INVALID_KE_PAYLOAD - request "
    1102             :                            "DH Group #%d", data->proposal.dh);
    1103           0 :                 break;
    1104             :         case AUTHENTICATION_FAILED:
    1105             :                 /* no associated data */
    1106           1 :                 break;
    1107             :         default:
    1108           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported Notify Message Type "
    1109           0 :                            "%d", data->error_type);
    1110           0 :                 return -1;
    1111             :         }
    1112             : 
    1113           1 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
    1114           1 :         WPA_PUT_BE16(phdr->payload_length, plen);
    1115           1 :         return 0;
    1116             : }
    1117             : 
    1118             : 
    1119           6 : static struct wpabuf * ikev2_build_sa_init(struct ikev2_responder_data *data)
    1120             : {
    1121             :         struct wpabuf *msg;
    1122             : 
    1123             :         /* build IKE_SA_INIT: HDR, SAr1, KEr, Nr, [CERTREQ], [SK{IDr}] */
    1124             : 
    1125           6 :         if (os_get_random(data->r_spi, IKEV2_SPI_LEN))
    1126           0 :                 return NULL;
    1127           6 :         wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI",
    1128           6 :                     data->r_spi, IKEV2_SPI_LEN);
    1129             : 
    1130           6 :         data->r_nonce_len = IKEV2_NONCE_MIN_LEN;
    1131           6 :         if (random_get_bytes(data->r_nonce, data->r_nonce_len))
    1132           0 :                 return NULL;
    1133             : #ifdef CCNS_PL
    1134             :         /* Zeros are removed incorrectly from the beginning of the nonces in
    1135             :          * key derivation; as a workaround, make sure Nr does not start with
    1136             :          * zero.. */
    1137             :         if (data->r_nonce[0] == 0)
    1138             :                 data->r_nonce[0] = 1;
    1139             : #endif /* CCNS_PL */
    1140           6 :         wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len);
    1141             : 
    1142           6 :         msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500);
    1143           6 :         if (msg == NULL)
    1144           0 :                 return NULL;
    1145             : 
    1146           6 :         ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0);
    1147          12 :         if (ikev2_build_sar1(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) ||
    1148          12 :             ikev2_build_ker(data, msg, IKEV2_PAYLOAD_NONCE) ||
    1149           6 :             ikev2_build_nr(data, msg, data->peer_auth == PEER_AUTH_SECRET ?
    1150             :                            IKEV2_PAYLOAD_ENCRYPTED :
    1151             :                            IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) {
    1152           0 :                 wpabuf_free(msg);
    1153           0 :                 return NULL;
    1154             :         }
    1155             : 
    1156           6 :         if (ikev2_derive_keys(data)) {
    1157           0 :                 wpabuf_free(msg);
    1158           0 :                 return NULL;
    1159             :         }
    1160             : 
    1161           6 :         if (data->peer_auth == PEER_AUTH_CERT) {
    1162             :                 /* TODO: CERTREQ with SHA-1 hashes of Subject Public Key Info
    1163             :                  * for trust agents */
    1164             :         }
    1165             : 
    1166           6 :         if (data->peer_auth == PEER_AUTH_SECRET) {
    1167           6 :                 struct wpabuf *plain = wpabuf_alloc(data->IDr_len + 1000);
    1168           6 :                 if (plain == NULL) {
    1169           0 :                         wpabuf_free(msg);
    1170           0 :                         return NULL;
    1171             :                 }
    1172           6 :                 if (ikev2_build_idr(data, plain,
    1173           6 :                                     IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
    1174           6 :                     ikev2_build_encrypted(data->proposal.encr,
    1175             :                                           data->proposal.integ,
    1176             :                                           &data->keys, 0, msg, plain,
    1177             :                                           IKEV2_PAYLOAD_IDr)) {
    1178           0 :                         wpabuf_free(plain);
    1179           0 :                         wpabuf_free(msg);
    1180           0 :                         return NULL;
    1181             :                 }
    1182           6 :                 wpabuf_free(plain);
    1183             :         }
    1184             : 
    1185           6 :         ikev2_update_hdr(msg);
    1186             : 
    1187           6 :         wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg);
    1188             : 
    1189           6 :         data->state = SA_AUTH;
    1190             : 
    1191           6 :         wpabuf_free(data->r_sign_msg);
    1192           6 :         data->r_sign_msg = wpabuf_dup(msg);
    1193             : 
    1194           6 :         return msg;
    1195             : }
    1196             : 
    1197             : 
    1198           5 : static struct wpabuf * ikev2_build_sa_auth(struct ikev2_responder_data *data)
    1199             : {
    1200             :         struct wpabuf *msg, *plain;
    1201             : 
    1202             :         /* build IKE_SA_AUTH: HDR, SK {IDr, [CERT,] AUTH} */
    1203             : 
    1204           5 :         msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000);
    1205           5 :         if (msg == NULL)
    1206           0 :                 return NULL;
    1207           5 :         ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1);
    1208             : 
    1209           5 :         plain = wpabuf_alloc(data->IDr_len + 1000);
    1210           5 :         if (plain == NULL) {
    1211           0 :                 wpabuf_free(msg);
    1212           0 :                 return NULL;
    1213             :         }
    1214             : 
    1215          10 :         if (ikev2_build_idr(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) ||
    1216          10 :             ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
    1217           5 :             ikev2_build_encrypted(data->proposal.encr, data->proposal.integ,
    1218             :                                   &data->keys, 0, msg, plain,
    1219             :                                   IKEV2_PAYLOAD_IDr)) {
    1220           0 :                 wpabuf_free(plain);
    1221           0 :                 wpabuf_free(msg);
    1222           0 :                 return NULL;
    1223             :         }
    1224           5 :         wpabuf_free(plain);
    1225             : 
    1226           5 :         wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg);
    1227             : 
    1228           5 :         data->state = IKEV2_DONE;
    1229             : 
    1230           5 :         return msg;
    1231             : }
    1232             : 
    1233             : 
    1234           1 : static struct wpabuf * ikev2_build_notify(struct ikev2_responder_data *data)
    1235             : {
    1236             :         struct wpabuf *msg;
    1237             : 
    1238           1 :         msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000);
    1239           1 :         if (msg == NULL)
    1240           0 :                 return NULL;
    1241           1 :         if (data->last_msg == LAST_MSG_SA_AUTH) {
    1242             :                 /* HDR, SK{N} */
    1243           1 :                 struct wpabuf *plain = wpabuf_alloc(100);
    1244           1 :                 if (plain == NULL) {
    1245           0 :                         wpabuf_free(msg);
    1246           0 :                         return NULL;
    1247             :                 }
    1248           1 :                 ikev2_build_hdr(data, msg, IKE_SA_AUTH,
    1249             :                                 IKEV2_PAYLOAD_ENCRYPTED, 1);
    1250           1 :                 if (ikev2_build_notification(data, plain,
    1251           1 :                                              IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
    1252           1 :                     ikev2_build_encrypted(data->proposal.encr,
    1253             :                                           data->proposal.integ,
    1254             :                                           &data->keys, 0, msg, plain,
    1255             :                                           IKEV2_PAYLOAD_NOTIFICATION)) {
    1256           0 :                         wpabuf_free(plain);
    1257           0 :                         wpabuf_free(msg);
    1258           0 :                         return NULL;
    1259             :                 }
    1260           1 :                 wpabuf_free(plain);
    1261           1 :                 data->state = IKEV2_FAILED;
    1262             :         } else {
    1263             :                 /* HDR, N */
    1264           0 :                 ikev2_build_hdr(data, msg, IKE_SA_INIT,
    1265             :                                 IKEV2_PAYLOAD_NOTIFICATION, 0);
    1266           0 :                 if (ikev2_build_notification(data, msg,
    1267             :                                              IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) {
    1268           0 :                         wpabuf_free(msg);
    1269           0 :                         return NULL;
    1270             :                 }
    1271           0 :                 data->state = SA_INIT;
    1272             :         }
    1273             : 
    1274           1 :         ikev2_update_hdr(msg);
    1275             : 
    1276           1 :         wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (Notification)",
    1277             :                         msg);
    1278             : 
    1279           1 :         return msg;
    1280             : }
    1281             : 
    1282             : 
    1283          12 : struct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data)
    1284             : {
    1285          12 :         switch (data->state) {
    1286             :         case SA_INIT:
    1287           6 :                 return ikev2_build_sa_init(data);
    1288             :         case SA_AUTH:
    1289           5 :                 return ikev2_build_sa_auth(data);
    1290             :         case CHILD_SA:
    1291           0 :                 return NULL;
    1292             :         case NOTIFY:
    1293           1 :                 return ikev2_build_notify(data);
    1294             :         case IKEV2_DONE:
    1295             :         case IKEV2_FAILED:
    1296           0 :                 return NULL;
    1297             :         }
    1298           0 :         return NULL;
    1299             : }

Generated by: LCOV version 1.10