LCOV - code coverage report
Current view: top level - src/eap_server - ikev2.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 431 617 69.9 %
Date: 2015-09-27 Functions: 26 27 96.3 %

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

Generated by: LCOV version 1.10