ikev2.c
Go to the documentation of this file.
00001 /*
00002  * IKEv2 responder (RFC 4306) for EAP-IKEV2
00003  * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #include "common.h"
00018 #include "crypto/dh_groups.h"
00019 #include "ikev2.h"
00020 
00021 
00022 void ikev2_responder_deinit(struct ikev2_responder_data *data)
00023 {
00024         ikev2_free_keys(&data->keys);
00025         wpabuf_free(data->i_dh_public);
00026         wpabuf_free(data->r_dh_private);
00027         os_free(data->IDi);
00028         os_free(data->IDr);
00029         os_free(data->shared_secret);
00030         wpabuf_free(data->i_sign_msg);
00031         wpabuf_free(data->r_sign_msg);
00032         os_free(data->key_pad);
00033 }
00034 
00035 
00036 static int ikev2_derive_keys(struct ikev2_responder_data *data)
00037 {
00038         u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN];
00039         size_t buf_len, pad_len;
00040         struct wpabuf *shared;
00041         const struct ikev2_integ_alg *integ;
00042         const struct ikev2_prf_alg *prf;
00043         const struct ikev2_encr_alg *encr;
00044         int ret;
00045         const u8 *addr[2];
00046         size_t len[2];
00047 
00048         /* RFC 4306, Sect. 2.14 */
00049 
00050         integ = ikev2_get_integ(data->proposal.integ);
00051         prf = ikev2_get_prf(data->proposal.prf);
00052         encr = ikev2_get_encr(data->proposal.encr);
00053         if (integ == NULL || prf == NULL || encr == NULL) {
00054                 wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal");
00055                 return -1;
00056         }
00057 
00058         shared = dh_derive_shared(data->i_dh_public, data->r_dh_private,
00059                                   data->dh);
00060         if (shared == NULL)
00061                 return -1;
00062 
00063         /* Construct Ni | Nr | SPIi | SPIr */
00064 
00065         buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN;
00066         buf = os_malloc(buf_len);
00067         if (buf == NULL) {
00068                 wpabuf_free(shared);
00069                 return -1;
00070         }
00071 
00072         pos = buf;
00073         os_memcpy(pos, data->i_nonce, data->i_nonce_len);
00074         pos += data->i_nonce_len;
00075         os_memcpy(pos, data->r_nonce, data->r_nonce_len);
00076         pos += data->r_nonce_len;
00077         os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN);
00078         pos += IKEV2_SPI_LEN;
00079         os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN);
00080 #ifdef CCNS_PL
00081 #if __BYTE_ORDER == __LITTLE_ENDIAN
00082         {
00083                 int i;
00084                 u8 *tmp = pos - IKEV2_SPI_LEN;
00085                 /* Incorrect byte re-ordering on little endian hosts.. */
00086                 for (i = 0; i < IKEV2_SPI_LEN; i++)
00087                         *tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i];
00088                 for (i = 0; i < IKEV2_SPI_LEN; i++)
00089                         *tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i];
00090         }
00091 #endif
00092 #endif /* CCNS_PL */
00093 
00094         /* SKEYSEED = prf(Ni | Nr, g^ir) */
00095         /* Use zero-padding per RFC 4306, Sect. 2.14 */
00096         pad_len = data->dh->prime_len - wpabuf_len(shared);
00097 #ifdef CCNS_PL
00098         /* Shared secret is not zero-padded correctly */
00099         pad_len = 0;
00100 #endif /* CCNS_PL */
00101         pad = os_zalloc(pad_len ? pad_len : 1);
00102         if (pad == NULL) {
00103                 wpabuf_free(shared);
00104                 os_free(buf);
00105                 return -1;
00106         }
00107 
00108         addr[0] = pad;
00109         len[0] = pad_len;
00110         addr[1] = wpabuf_head(shared);
00111         len[1] = wpabuf_len(shared);
00112         if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len,
00113                            2, addr, len, skeyseed) < 0) {
00114                 wpabuf_free(shared);
00115                 os_free(buf);
00116                 os_free(pad);
00117                 return -1;
00118         }
00119         os_free(pad);
00120         wpabuf_free(shared);
00121 
00122         /* DH parameters are not needed anymore, so free them */
00123         wpabuf_free(data->i_dh_public);
00124         data->i_dh_public = NULL;
00125         wpabuf_free(data->r_dh_private);
00126         data->r_dh_private = NULL;
00127 
00128         wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED",
00129                         skeyseed, prf->hash_len);
00130 
00131         ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len,
00132                                    &data->keys);
00133         os_free(buf);
00134         return ret;
00135 }
00136 
00137 
00138 static int ikev2_parse_transform(struct ikev2_proposal_data *prop,
00139                                  const u8 *pos, const u8 *end)
00140 {
00141         int transform_len;
00142         const struct ikev2_transform *t;
00143         u16 transform_id;
00144         const u8 *tend;
00145 
00146         if (end - pos < (int) sizeof(*t)) {
00147                 wpa_printf(MSG_INFO, "IKEV2: Too short transform");
00148                 return -1;
00149         }
00150 
00151         t = (const struct ikev2_transform *) pos;
00152         transform_len = WPA_GET_BE16(t->transform_length);
00153         if (transform_len < (int) sizeof(*t) || pos + transform_len > end) {
00154                 wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d",
00155                            transform_len);
00156                 return -1;
00157         }
00158         tend = pos + transform_len;
00159 
00160         transform_id = WPA_GET_BE16(t->transform_id);
00161 
00162         wpa_printf(MSG_DEBUG, "IKEV2:   Transform:");
00163         wpa_printf(MSG_DEBUG, "IKEV2:     Type: %d  Transform Length: %d  "
00164                    "Transform Type: %d  Transform ID: %d",
00165                    t->type, transform_len, t->transform_type, transform_id);
00166 
00167         if (t->type != 0 && t->type != 3) {
00168                 wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type");
00169                 return -1;
00170         }
00171 
00172         pos = (const u8 *) (t + 1);
00173         if (pos < tend) {
00174                 wpa_hexdump(MSG_DEBUG, "IKEV2:     Transform Attributes",
00175                             pos, tend - pos);
00176         }
00177 
00178         switch (t->transform_type) {
00179         case IKEV2_TRANSFORM_ENCR:
00180                 if (ikev2_get_encr(transform_id)) {
00181                         if (transform_id == ENCR_AES_CBC) {
00182                                 if (tend - pos != 4) {
00183                                         wpa_printf(MSG_DEBUG, "IKEV2: No "
00184                                                    "Transform Attr for AES");
00185                                         break;
00186                                 }
00187 #ifdef CCNS_PL
00188                                 if (WPA_GET_BE16(pos) != 0x001d /* ?? */) {
00189                                         wpa_printf(MSG_DEBUG, "IKEV2: Not a "
00190                                                    "Key Size attribute for "
00191                                                    "AES");
00192                                         break;
00193                                 }
00194 #else /* CCNS_PL */
00195                                 if (WPA_GET_BE16(pos) != 0x800e) {
00196                                         wpa_printf(MSG_DEBUG, "IKEV2: Not a "
00197                                                    "Key Size attribute for "
00198                                                    "AES");
00199                                         break;
00200                                 }
00201 #endif /* CCNS_PL */
00202                                 if (WPA_GET_BE16(pos + 2) != 128) {
00203                                         wpa_printf(MSG_DEBUG, "IKEV2: "
00204                                                    "Unsupported AES key size "
00205                                                    "%d bits",
00206                                                    WPA_GET_BE16(pos + 2));
00207                                         break;
00208                                 }
00209                         }
00210                         prop->encr = transform_id;
00211                 }
00212                 break;
00213         case IKEV2_TRANSFORM_PRF:
00214                 if (ikev2_get_prf(transform_id))
00215                         prop->prf = transform_id;
00216                 break;
00217         case IKEV2_TRANSFORM_INTEG:
00218                 if (ikev2_get_integ(transform_id))
00219                         prop->integ = transform_id;
00220                 break;
00221         case IKEV2_TRANSFORM_DH:
00222                 if (dh_groups_get(transform_id))
00223                         prop->dh = transform_id;
00224                 break;
00225         }
00226 
00227         return transform_len;
00228 }
00229 
00230 
00231 static int ikev2_parse_proposal(struct ikev2_proposal_data *prop,
00232                                 const u8 *pos, const u8 *end)
00233 {
00234         const u8 *pend, *ppos;
00235         int proposal_len, i;
00236         const struct ikev2_proposal *p;
00237 
00238         if (end - pos < (int) sizeof(*p)) {
00239                 wpa_printf(MSG_INFO, "IKEV2: Too short proposal");
00240                 return -1;
00241         }
00242 
00243         /* FIX: AND processing if multiple proposals use the same # */
00244 
00245         p = (const struct ikev2_proposal *) pos;
00246         proposal_len = WPA_GET_BE16(p->proposal_length);
00247         if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) {
00248                 wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d",
00249                            proposal_len);
00250                 return -1;
00251         }
00252         wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d",
00253                    p->proposal_num);
00254         wpa_printf(MSG_DEBUG, "IKEV2:   Type: %d  Proposal Length: %d "
00255                    " Protocol ID: %d",
00256                    p->type, proposal_len, p->protocol_id);
00257         wpa_printf(MSG_DEBUG, "IKEV2:   SPI Size: %d  Transforms: %d",
00258                    p->spi_size, p->num_transforms);
00259 
00260         if (p->type != 0 && p->type != 2) {
00261                 wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type");
00262                 return -1;
00263         }
00264 
00265         if (p->protocol_id != IKEV2_PROTOCOL_IKE) {
00266                 wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID "
00267                            "(only IKE allowed for EAP-IKEv2)");
00268                 return -1;
00269         }
00270 
00271         if (p->proposal_num != prop->proposal_num) {
00272                 if (p->proposal_num == prop->proposal_num + 1)
00273                         prop->proposal_num = p->proposal_num;
00274                 else {
00275                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #");
00276                         return -1;
00277                 }
00278         }
00279 
00280         ppos = (const u8 *) (p + 1);
00281         pend = pos + proposal_len;
00282         if (ppos + p->spi_size > pend) {
00283                 wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI "
00284                            "in proposal");
00285                 return -1;
00286         }
00287         if (p->spi_size) {
00288                 wpa_hexdump(MSG_DEBUG, "IKEV2:    SPI",
00289                             ppos, p->spi_size);
00290                 ppos += p->spi_size;
00291         }
00292 
00293         /*
00294          * For initial IKE_SA negotiation, SPI Size MUST be zero; for
00295          * subsequent negotiations, it must be 8 for IKE. We only support
00296          * initial case for now.
00297          */
00298         if (p->spi_size != 0) {
00299                 wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size");
00300                 return -1;
00301         }
00302 
00303         if (p->num_transforms == 0) {
00304                 wpa_printf(MSG_INFO, "IKEV2: At least one transform required");
00305                 return -1;
00306         }
00307 
00308         for (i = 0; i < (int) p->num_transforms; i++) {
00309                 int tlen = ikev2_parse_transform(prop, ppos, pend);
00310                 if (tlen < 0)
00311                         return -1;
00312                 ppos += tlen;
00313         }
00314 
00315         if (ppos != pend) {
00316                 wpa_printf(MSG_INFO, "IKEV2: Unexpected data after "
00317                            "transforms");
00318                 return -1;
00319         }
00320 
00321         return proposal_len;
00322 }
00323 
00324 
00325 static int ikev2_process_sai1(struct ikev2_responder_data *data,
00326                               const u8 *sai1, size_t sai1_len)
00327 {
00328         struct ikev2_proposal_data prop;
00329         const u8 *pos, *end;
00330         int found = 0;
00331 
00332         /* Security Association Payloads: <Proposals> */
00333 
00334         if (sai1 == NULL) {
00335                 wpa_printf(MSG_INFO, "IKEV2: SAi1 not received");
00336                 return -1;
00337         }
00338 
00339         os_memset(&prop, 0, sizeof(prop));
00340         prop.proposal_num = 1;
00341 
00342         pos = sai1;
00343         end = sai1 + sai1_len;
00344 
00345         while (pos < end) {
00346                 int plen;
00347 
00348                 prop.integ = -1;
00349                 prop.prf = -1;
00350                 prop.encr = -1;
00351                 prop.dh = -1;
00352                 plen = ikev2_parse_proposal(&prop, pos, end);
00353                 if (plen < 0)
00354                         return -1;
00355 
00356                 if (!found && prop.integ != -1 && prop.prf != -1 &&
00357                     prop.encr != -1 && prop.dh != -1) {
00358                         os_memcpy(&data->proposal, &prop, sizeof(prop));
00359                         data->dh = dh_groups_get(prop.dh);
00360                         found = 1;
00361                 }
00362 
00363                 pos += plen;
00364         }
00365 
00366         if (pos != end) {
00367                 wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposals");
00368                 return -1;
00369         }
00370 
00371         if (!found) {
00372                 wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found");
00373                 return -1;
00374         }
00375 
00376         wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d "
00377                    "INTEG:%d D-H:%d", data->proposal.proposal_num,
00378                    data->proposal.encr, data->proposal.prf,
00379                    data->proposal.integ, data->proposal.dh);
00380 
00381         return 0;
00382 }
00383 
00384 
00385 static int ikev2_process_kei(struct ikev2_responder_data *data,
00386                              const u8 *kei, size_t kei_len)
00387 {
00388         u16 group;
00389 
00390         /*
00391          * Key Exchange Payload:
00392          * DH Group # (16 bits)
00393          * RESERVED (16 bits)
00394          * Key Exchange Data (Diffie-Hellman public value)
00395          */
00396 
00397         if (kei == NULL) {
00398                 wpa_printf(MSG_INFO, "IKEV2: KEi not received");
00399                 return -1;
00400         }
00401 
00402         if (kei_len < 4 + 96) {
00403                 wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload");
00404                 return -1;
00405         }
00406 
00407         group = WPA_GET_BE16(kei);
00408         wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u", group);
00409 
00410         if (group != data->proposal.dh) {
00411                 wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u does not match "
00412                            "with the selected proposal (%u)",
00413                            group, data->proposal.dh);
00414                 /* Reject message with Notify payload of type
00415                  * INVALID_KE_PAYLOAD (RFC 4306, Sect. 3.4) */
00416                 data->error_type = INVALID_KE_PAYLOAD;
00417                 data->state = NOTIFY;
00418                 return -1;
00419         }
00420 
00421         if (data->dh == NULL) {
00422                 wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group");
00423                 return -1;
00424         }
00425 
00426         /* RFC 4306, Section 3.4:
00427          * The length of DH public value MUST be equal to the lenght of the
00428          * prime modulus.
00429          */
00430         if (kei_len - 4 != data->dh->prime_len) {
00431                 wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length "
00432                            "%ld (expected %ld)",
00433                            (long) (kei_len - 4), (long) data->dh->prime_len);
00434                 return -1;
00435         }
00436 
00437         wpabuf_free(data->i_dh_public);
00438         data->i_dh_public = wpabuf_alloc(kei_len - 4);
00439         if (data->i_dh_public == NULL)
00440                 return -1;
00441         wpabuf_put_data(data->i_dh_public, kei + 4, kei_len - 4);
00442 
00443         wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value",
00444                         data->i_dh_public);
00445         
00446         return 0;
00447 }
00448 
00449 
00450 static int ikev2_process_ni(struct ikev2_responder_data *data,
00451                             const u8 *ni, size_t ni_len)
00452 {
00453         if (ni == NULL) {
00454                 wpa_printf(MSG_INFO, "IKEV2: Ni not received");
00455                 return -1;
00456         }
00457 
00458         if (ni_len < IKEV2_NONCE_MIN_LEN || ni_len > IKEV2_NONCE_MAX_LEN) {
00459                 wpa_printf(MSG_INFO, "IKEV2: Invalid Ni length %ld",
00460                            (long) ni_len);
00461                 return -1;
00462         }
00463 
00464 #ifdef CCNS_PL
00465         /* Zeros are removed incorrectly from the beginning of the nonces */
00466         while (ni_len > 1 && *ni == 0) {
00467                 ni_len--;
00468                 ni++;
00469         }
00470 #endif /* CCNS_PL */
00471 
00472         data->i_nonce_len = ni_len;
00473         os_memcpy(data->i_nonce, ni, ni_len);
00474         wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni",
00475                     data->i_nonce, data->i_nonce_len);
00476 
00477         return 0;
00478 }
00479 
00480 
00481 static int ikev2_process_sa_init(struct ikev2_responder_data *data,
00482                                  const struct ikev2_hdr *hdr,
00483                                  struct ikev2_payloads *pl)
00484 {
00485         if (ikev2_process_sai1(data, pl->sa, pl->sa_len) < 0 ||
00486             ikev2_process_kei(data, pl->ke, pl->ke_len) < 0 ||
00487             ikev2_process_ni(data, pl->nonce, pl->nonce_len) < 0)
00488                 return -1;
00489 
00490         os_memcpy(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN);
00491 
00492         return 0;
00493 }
00494 
00495 
00496 static int ikev2_process_idi(struct ikev2_responder_data *data,
00497                              const u8 *idi, size_t idi_len)
00498 {
00499         u8 id_type;
00500 
00501         if (idi == NULL) {
00502                 wpa_printf(MSG_INFO, "IKEV2: No IDi received");
00503                 return -1;
00504         }
00505 
00506         if (idi_len < 4) {
00507                 wpa_printf(MSG_INFO, "IKEV2: Too short IDi payload");
00508                 return -1;
00509         }
00510 
00511         id_type = idi[0];
00512         idi += 4;
00513         idi_len -= 4;
00514 
00515         wpa_printf(MSG_DEBUG, "IKEV2: IDi ID Type %d", id_type);
00516         wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDi", idi, idi_len);
00517         os_free(data->IDi);
00518         data->IDi = os_malloc(idi_len);
00519         if (data->IDi == NULL)
00520                 return -1;
00521         os_memcpy(data->IDi, idi, idi_len);
00522         data->IDi_len = idi_len;
00523         data->IDi_type = id_type;
00524 
00525         return 0;
00526 }
00527 
00528 
00529 static int ikev2_process_cert(struct ikev2_responder_data *data,
00530                               const u8 *cert, size_t cert_len)
00531 {
00532         u8 cert_encoding;
00533 
00534         if (cert == NULL) {
00535                 if (data->peer_auth == PEER_AUTH_CERT) {
00536                         wpa_printf(MSG_INFO, "IKEV2: No Certificate received");
00537                         return -1;
00538                 }
00539                 return 0;
00540         }
00541 
00542         if (cert_len < 1) {
00543                 wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field");
00544                 return -1;
00545         }
00546 
00547         cert_encoding = cert[0];
00548         cert++;
00549         cert_len--;
00550 
00551         wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding);
00552         wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len);
00553 
00554         /* TODO: validate certificate */
00555 
00556         return 0;
00557 }
00558 
00559 
00560 static int ikev2_process_auth_cert(struct ikev2_responder_data *data,
00561                                    u8 method, const u8 *auth, size_t auth_len)
00562 {
00563         if (method != AUTH_RSA_SIGN) {
00564                 wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "
00565                            "method %d", method);
00566                 return -1;
00567         }
00568 
00569         /* TODO: validate AUTH */
00570         return 0;
00571 }
00572 
00573 
00574 static int ikev2_process_auth_secret(struct ikev2_responder_data *data,
00575                                      u8 method, const u8 *auth,
00576                                      size_t auth_len)
00577 {
00578         u8 auth_data[IKEV2_MAX_HASH_LEN];
00579         const struct ikev2_prf_alg *prf;
00580 
00581         if (method != AUTH_SHARED_KEY_MIC) {
00582                 wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "
00583                            "method %d", method);
00584                 return -1;
00585         }
00586 
00587         /* msg | Nr | prf(SK_pi,IDi') */
00588         if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg,
00589                                    data->IDi, data->IDi_len, data->IDi_type,
00590                                    &data->keys, 1, data->shared_secret,
00591                                    data->shared_secret_len,
00592                                    data->r_nonce, data->r_nonce_len,
00593                                    data->key_pad, data->key_pad_len,
00594                                    auth_data) < 0) {
00595                 wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");
00596                 return -1;
00597         }
00598 
00599         wpabuf_free(data->i_sign_msg);
00600         data->i_sign_msg = NULL;
00601 
00602         prf = ikev2_get_prf(data->proposal.prf);
00603         if (prf == NULL)
00604                 return -1;
00605 
00606         if (auth_len != prf->hash_len ||
00607             os_memcmp(auth, auth_data, auth_len) != 0) {
00608                 wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data");
00609                 wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data",
00610                             auth, auth_len);
00611                 wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data",
00612                             auth_data, prf->hash_len);
00613                 data->error_type = AUTHENTICATION_FAILED;
00614                 data->state = NOTIFY;
00615                 return -1;
00616         }
00617 
00618         wpa_printf(MSG_DEBUG, "IKEV2: Server authenticated successfully "
00619                    "using shared keys");
00620 
00621         return 0;
00622 }
00623 
00624 
00625 static int ikev2_process_auth(struct ikev2_responder_data *data,
00626                               const u8 *auth, size_t auth_len)
00627 {
00628         u8 auth_method;
00629 
00630         if (auth == NULL) {
00631                 wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload");
00632                 return -1;
00633         }
00634 
00635         if (auth_len < 4) {
00636                 wpa_printf(MSG_INFO, "IKEV2: Too short Authentication "
00637                            "Payload");
00638                 return -1;
00639         }
00640 
00641         auth_method = auth[0];
00642         auth += 4;
00643         auth_len -= 4;
00644 
00645         wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method);
00646         wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len);
00647 
00648         switch (data->peer_auth) {
00649         case PEER_AUTH_CERT:
00650                 return ikev2_process_auth_cert(data, auth_method, auth,
00651                                                auth_len);
00652         case PEER_AUTH_SECRET:
00653                 return ikev2_process_auth_secret(data, auth_method, auth,
00654                                                  auth_len);
00655         }
00656 
00657         return -1;
00658 }
00659 
00660 
00661 static int ikev2_process_sa_auth_decrypted(struct ikev2_responder_data *data,
00662                                            u8 next_payload,
00663                                            u8 *payload, size_t payload_len)
00664 {
00665         struct ikev2_payloads pl;
00666 
00667         wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads");
00668 
00669         if (ikev2_parse_payloads(&pl, next_payload, payload, payload +
00670                                  payload_len) < 0) {
00671                 wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted "
00672                            "payloads");
00673                 return -1;
00674         }
00675 
00676         if (ikev2_process_idi(data, pl.idi, pl.idi_len) < 0 ||
00677             ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 ||
00678             ikev2_process_auth(data, pl.auth, pl.auth_len) < 0)
00679                 return -1;
00680 
00681         return 0;
00682 }
00683 
00684 
00685 static int ikev2_process_sa_auth(struct ikev2_responder_data *data,
00686                                  const struct ikev2_hdr *hdr,
00687                                  struct ikev2_payloads *pl)
00688 {
00689         u8 *decrypted;
00690         size_t decrypted_len;
00691         int ret;
00692 
00693         decrypted = ikev2_decrypt_payload(data->proposal.encr,
00694                                           data->proposal.integ,
00695                                           &data->keys, 1, hdr, pl->encrypted,
00696                                           pl->encrypted_len, &decrypted_len);
00697         if (decrypted == NULL)
00698                 return -1;
00699 
00700         ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload,
00701                                               decrypted, decrypted_len);
00702         os_free(decrypted);
00703 
00704         return ret;
00705 }
00706 
00707 
00708 static int ikev2_validate_rx_state(struct ikev2_responder_data *data,
00709                                    u8 exchange_type, u32 message_id)
00710 {
00711         switch (data->state) {
00712         case SA_INIT:
00713                 /* Expect to receive IKE_SA_INIT: HDR, SAi1, KEi, Ni */
00714                 if (exchange_type != IKE_SA_INIT) {
00715                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
00716                                    "%u in SA_INIT state", exchange_type);
00717                         return -1;
00718                 }
00719                 if (message_id != 0) {
00720                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
00721                                    "in SA_INIT state", message_id);
00722                         return -1;
00723                 }
00724                 break;
00725         case SA_AUTH:
00726                 /* Expect to receive IKE_SA_AUTH:
00727                  * HDR, SK {IDi, [CERT,] [CERTREQ,] [IDr,]
00728                  *      AUTH, SAi2, TSi, TSr}
00729                  */
00730                 if (exchange_type != IKE_SA_AUTH) {
00731                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
00732                                    "%u in SA_AUTH state", exchange_type);
00733                         return -1;
00734                 }
00735                 if (message_id != 1) {
00736                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
00737                                    "in SA_AUTH state", message_id);
00738                         return -1;
00739                 }
00740                 break;
00741         case CHILD_SA:
00742                 if (exchange_type != CREATE_CHILD_SA) {
00743                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "
00744                                    "%u in CHILD_SA state", exchange_type);
00745                         return -1;
00746                 }
00747                 if (message_id != 2) {
00748                         wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "
00749                                    "in CHILD_SA state", message_id);
00750                         return -1;
00751                 }
00752                 break;
00753         case NOTIFY:
00754         case IKEV2_DONE:
00755         case IKEV2_FAILED:
00756                 return -1;
00757         }
00758 
00759         return 0;
00760 }
00761 
00762 
00763 int ikev2_responder_process(struct ikev2_responder_data *data,
00764                             const struct wpabuf *buf)
00765 {
00766         const struct ikev2_hdr *hdr;
00767         u32 length, message_id;
00768         const u8 *pos, *end;
00769         struct ikev2_payloads pl;
00770 
00771         wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)",
00772                    (unsigned long) wpabuf_len(buf));
00773 
00774         if (wpabuf_len(buf) < sizeof(*hdr)) {
00775                 wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR");
00776                 return -1;
00777         }
00778 
00779         data->error_type = 0;
00780         hdr = (const struct ikev2_hdr *) wpabuf_head(buf);
00781         end = wpabuf_head_u8(buf) + wpabuf_len(buf);
00782         message_id = WPA_GET_BE32(hdr->message_id);
00783         length = WPA_GET_BE32(hdr->length);
00784 
00785         wpa_hexdump(MSG_DEBUG, "IKEV2:   IKE_SA Initiator's SPI",
00786                     hdr->i_spi, IKEV2_SPI_LEN);
00787         wpa_hexdump(MSG_DEBUG, "IKEV2:   IKE_SA Responder's SPI",
00788                     hdr->r_spi, IKEV2_SPI_LEN);
00789         wpa_printf(MSG_DEBUG, "IKEV2:   Next Payload: %u  Version: 0x%x  "
00790                    "Exchange Type: %u",
00791                    hdr->next_payload, hdr->version, hdr->exchange_type);
00792         wpa_printf(MSG_DEBUG, "IKEV2:   Message ID: %u  Length: %u",
00793                    message_id, length);
00794 
00795         if (hdr->version != IKEV2_VERSION) {
00796                 wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x "
00797                            "(expected 0x%x)", hdr->version, IKEV2_VERSION);
00798                 return -1;
00799         }
00800 
00801         if (length != wpabuf_len(buf)) {
00802                 wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != "
00803                            "RX: %lu)", (unsigned long) length,
00804                            (unsigned long) wpabuf_len(buf));
00805                 return -1;
00806         }
00807 
00808         if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0)
00809                 return -1;
00810 
00811         if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) !=
00812             IKEV2_HDR_INITIATOR) {
00813                 wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x",
00814                            hdr->flags);
00815                 return -1;
00816         }
00817 
00818         if (data->state != SA_INIT) {
00819                 if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) {
00820                         wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "
00821                                    "Initiator's SPI");
00822                         return -1;
00823                 }
00824                 if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) {
00825                         wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "
00826                                    "Responder's SPI");
00827                         return -1;
00828                 }
00829         }
00830 
00831         pos = (const u8 *) (hdr + 1);
00832         if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0)
00833                 return -1;
00834 
00835         if (data->state == SA_INIT) {
00836                 data->last_msg = LAST_MSG_SA_INIT;
00837                 if (ikev2_process_sa_init(data, hdr, &pl) < 0) {
00838                         if (data->state == NOTIFY)
00839                                 return 0;
00840                         return -1;
00841                 }
00842                 wpabuf_free(data->i_sign_msg);
00843                 data->i_sign_msg = wpabuf_dup(buf);
00844         }
00845 
00846         if (data->state == SA_AUTH) {
00847                 data->last_msg = LAST_MSG_SA_AUTH;
00848                 if (ikev2_process_sa_auth(data, hdr, &pl) < 0) {
00849                         if (data->state == NOTIFY)
00850                                 return 0;
00851                         return -1;
00852                 }
00853         }
00854 
00855         return 0;
00856 }
00857 
00858 
00859 static void ikev2_build_hdr(struct ikev2_responder_data *data,
00860                             struct wpabuf *msg, u8 exchange_type,
00861                             u8 next_payload, u32 message_id)
00862 {
00863         struct ikev2_hdr *hdr;
00864 
00865         wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR");
00866 
00867         /* HDR - RFC 4306, Sect. 3.1 */
00868         hdr = wpabuf_put(msg, sizeof(*hdr));
00869         os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN);
00870         os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN);
00871         hdr->next_payload = next_payload;
00872         hdr->version = IKEV2_VERSION;
00873         hdr->exchange_type = exchange_type;
00874         hdr->flags = IKEV2_HDR_RESPONSE;
00875         WPA_PUT_BE32(hdr->message_id, message_id);
00876 }
00877 
00878 
00879 static int ikev2_build_sar1(struct ikev2_responder_data *data,
00880                             struct wpabuf *msg, u8 next_payload)
00881 {
00882         struct ikev2_payload_hdr *phdr;
00883         size_t plen;
00884         struct ikev2_proposal *p;
00885         struct ikev2_transform *t;
00886 
00887         wpa_printf(MSG_DEBUG, "IKEV2: Adding SAr1 payload");
00888 
00889         /* SAr1 - RFC 4306, Sect. 2.7 and 3.3 */
00890         phdr = wpabuf_put(msg, sizeof(*phdr));
00891         phdr->next_payload = next_payload;
00892         phdr->flags = 0;
00893 
00894         p = wpabuf_put(msg, sizeof(*p));
00895 #ifdef CCNS_PL
00896         /* Seems to require that the Proposal # is 1 even though RFC 4306
00897          * Sect 3.3.1 has following requirement "When a proposal is accepted,
00898          * all of the proposal numbers in the SA payload MUST be the same and
00899          * MUST match the number on the proposal sent that was accepted.".
00900          */
00901         p->proposal_num = 1;
00902 #else /* CCNS_PL */
00903         p->proposal_num = data->proposal.proposal_num;
00904 #endif /* CCNS_PL */
00905         p->protocol_id = IKEV2_PROTOCOL_IKE;
00906         p->num_transforms = 4;
00907 
00908         t = wpabuf_put(msg, sizeof(*t));
00909         t->type = 3;
00910         t->transform_type = IKEV2_TRANSFORM_ENCR;
00911         WPA_PUT_BE16(t->transform_id, data->proposal.encr);
00912         if (data->proposal.encr == ENCR_AES_CBC) {
00913                 /* Transform Attribute: Key Len = 128 bits */
00914 #ifdef CCNS_PL
00915                 wpabuf_put_be16(msg, 0x001d); /* ?? */
00916 #else /* CCNS_PL */
00917                 wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */
00918 #endif /* CCNS_PL */
00919                 wpabuf_put_be16(msg, 128); /* 128-bit key */
00920         }
00921         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t;
00922         WPA_PUT_BE16(t->transform_length, plen);
00923 
00924         t = wpabuf_put(msg, sizeof(*t));
00925         t->type = 3;
00926         WPA_PUT_BE16(t->transform_length, sizeof(*t));
00927         t->transform_type = IKEV2_TRANSFORM_PRF;
00928         WPA_PUT_BE16(t->transform_id, data->proposal.prf);
00929 
00930         t = wpabuf_put(msg, sizeof(*t));
00931         t->type = 3;
00932         WPA_PUT_BE16(t->transform_length, sizeof(*t));
00933         t->transform_type = IKEV2_TRANSFORM_INTEG;
00934         WPA_PUT_BE16(t->transform_id, data->proposal.integ);
00935 
00936         t = wpabuf_put(msg, sizeof(*t));
00937         WPA_PUT_BE16(t->transform_length, sizeof(*t));
00938         t->transform_type = IKEV2_TRANSFORM_DH;
00939         WPA_PUT_BE16(t->transform_id, data->proposal.dh);
00940 
00941         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p;
00942         WPA_PUT_BE16(p->proposal_length, plen);
00943 
00944         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
00945         WPA_PUT_BE16(phdr->payload_length, plen);
00946 
00947         return 0;
00948 }
00949 
00950 
00951 static int ikev2_build_ker(struct ikev2_responder_data *data,
00952                            struct wpabuf *msg, u8 next_payload)
00953 {
00954         struct ikev2_payload_hdr *phdr;
00955         size_t plen;
00956         struct wpabuf *pv;
00957 
00958         wpa_printf(MSG_DEBUG, "IKEV2: Adding KEr payload");
00959 
00960         pv = dh_init(data->dh, &data->r_dh_private);
00961         if (pv == NULL) {
00962                 wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH");
00963                 return -1;
00964         }
00965 
00966         /* KEr - RFC 4306, Sect. 3.4 */
00967         phdr = wpabuf_put(msg, sizeof(*phdr));
00968         phdr->next_payload = next_payload;
00969         phdr->flags = 0;
00970 
00971         wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */
00972         wpabuf_put(msg, 2); /* RESERVED */
00973         /*
00974          * RFC 4306, Sect. 3.4: possible zero padding for public value to
00975          * match the length of the prime.
00976          */
00977         wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv));
00978         wpabuf_put_buf(msg, pv);
00979         wpabuf_free(pv);
00980 
00981         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
00982         WPA_PUT_BE16(phdr->payload_length, plen);
00983         return 0;
00984 }
00985 
00986 
00987 static int ikev2_build_nr(struct ikev2_responder_data *data,
00988                           struct wpabuf *msg, u8 next_payload)
00989 {
00990         struct ikev2_payload_hdr *phdr;
00991         size_t plen;
00992 
00993         wpa_printf(MSG_DEBUG, "IKEV2: Adding Nr payload");
00994 
00995         /* Nr - RFC 4306, Sect. 3.9 */
00996         phdr = wpabuf_put(msg, sizeof(*phdr));
00997         phdr->next_payload = next_payload;
00998         phdr->flags = 0;
00999         wpabuf_put_data(msg, data->r_nonce, data->r_nonce_len);
01000         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
01001         WPA_PUT_BE16(phdr->payload_length, plen);
01002         return 0;
01003 }
01004 
01005 
01006 static int ikev2_build_idr(struct ikev2_responder_data *data,
01007                            struct wpabuf *msg, u8 next_payload)
01008 {
01009         struct ikev2_payload_hdr *phdr;
01010         size_t plen;
01011 
01012         wpa_printf(MSG_DEBUG, "IKEV2: Adding IDr payload");
01013 
01014         if (data->IDr == NULL) {
01015                 wpa_printf(MSG_INFO, "IKEV2: No IDr available");
01016                 return -1;
01017         }
01018 
01019         /* IDr - RFC 4306, Sect. 3.5 */
01020         phdr = wpabuf_put(msg, sizeof(*phdr));
01021         phdr->next_payload = next_payload;
01022         phdr->flags = 0;
01023         wpabuf_put_u8(msg, ID_KEY_ID);
01024         wpabuf_put(msg, 3); /* RESERVED */
01025         wpabuf_put_data(msg, data->IDr, data->IDr_len);
01026         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
01027         WPA_PUT_BE16(phdr->payload_length, plen);
01028         return 0;
01029 }
01030 
01031 
01032 static int ikev2_build_auth(struct ikev2_responder_data *data,
01033                             struct wpabuf *msg, u8 next_payload)
01034 {
01035         struct ikev2_payload_hdr *phdr;
01036         size_t plen;
01037         const struct ikev2_prf_alg *prf;
01038 
01039         wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload");
01040 
01041         prf = ikev2_get_prf(data->proposal.prf);
01042         if (prf == NULL)
01043                 return -1;
01044 
01045         /* Authentication - RFC 4306, Sect. 3.8 */
01046         phdr = wpabuf_put(msg, sizeof(*phdr));
01047         phdr->next_payload = next_payload;
01048         phdr->flags = 0;
01049         wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC);
01050         wpabuf_put(msg, 3); /* RESERVED */
01051 
01052         /* msg | Ni | prf(SK_pr,IDr') */
01053         if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg,
01054                                    data->IDr, data->IDr_len, ID_KEY_ID,
01055                                    &data->keys, 0, data->shared_secret,
01056                                    data->shared_secret_len,
01057                                    data->i_nonce, data->i_nonce_len,
01058                                    data->key_pad, data->key_pad_len,
01059                                    wpabuf_put(msg, prf->hash_len)) < 0) {
01060                 wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");
01061                 return -1;
01062         }
01063         wpabuf_free(data->r_sign_msg);
01064         data->r_sign_msg = NULL;
01065 
01066         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
01067         WPA_PUT_BE16(phdr->payload_length, plen);
01068         return 0;
01069 }
01070 
01071 
01072 static int ikev2_build_notification(struct ikev2_responder_data *data,
01073                                     struct wpabuf *msg, u8 next_payload)
01074 {
01075         struct ikev2_payload_hdr *phdr;
01076         size_t plen;
01077 
01078         wpa_printf(MSG_DEBUG, "IKEV2: Adding Notification payload");
01079 
01080         if (data->error_type == 0) {
01081                 wpa_printf(MSG_INFO, "IKEV2: No Notify Message Type "
01082                            "available");
01083                 return -1;
01084         }
01085 
01086         /* Notify - RFC 4306, Sect. 3.10 */
01087         phdr = wpabuf_put(msg, sizeof(*phdr));
01088         phdr->next_payload = next_payload;
01089         phdr->flags = 0;
01090 #ifdef CCNS_PL
01091         wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */
01092 #else /* CCNS_PL */
01093         wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */
01094 #endif /* CCNS_PL */
01095         wpabuf_put_u8(msg, 0); /* SPI Size */
01096         wpabuf_put_be16(msg, data->error_type);
01097 
01098         switch (data->error_type) {
01099         case INVALID_KE_PAYLOAD:
01100                 if (data->proposal.dh == -1) {
01101                         wpa_printf(MSG_INFO, "IKEV2: No DH Group selected for "
01102                                    "INVALID_KE_PAYLOAD notifications");
01103                         return -1;
01104                 }
01105                 wpabuf_put_be16(msg, data->proposal.dh);
01106                 wpa_printf(MSG_DEBUG, "IKEV2: INVALID_KE_PAYLOAD - request "
01107                            "DH Group #%d", data->proposal.dh);
01108                 break;
01109         case AUTHENTICATION_FAILED:
01110                 /* no associated data */
01111                 break;
01112         default:
01113                 wpa_printf(MSG_INFO, "IKEV2: Unsupported Notify Message Type "
01114                            "%d", data->error_type);
01115                 return -1;
01116         }
01117 
01118         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
01119         WPA_PUT_BE16(phdr->payload_length, plen);
01120         return 0;
01121 }
01122 
01123 
01124 static struct wpabuf * ikev2_build_sa_init(struct ikev2_responder_data *data)
01125 {
01126         struct wpabuf *msg;
01127 
01128         /* build IKE_SA_INIT: HDR, SAr1, KEr, Nr, [CERTREQ], [SK{IDr}] */
01129 
01130         if (os_get_random(data->r_spi, IKEV2_SPI_LEN))
01131                 return NULL;
01132         wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI",
01133                     data->r_spi, IKEV2_SPI_LEN);
01134 
01135         data->r_nonce_len = IKEV2_NONCE_MIN_LEN;
01136         if (os_get_random(data->r_nonce, data->r_nonce_len))
01137                 return NULL;
01138 #ifdef CCNS_PL
01139         /* Zeros are removed incorrectly from the beginning of the nonces in
01140          * key derivation; as a workaround, make sure Nr does not start with
01141          * zero.. */
01142         if (data->r_nonce[0] == 0)
01143                 data->r_nonce[0] = 1;
01144 #endif /* CCNS_PL */
01145         wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len);
01146 
01147         msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500);
01148         if (msg == NULL)
01149                 return NULL;
01150 
01151         ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0);
01152         if (ikev2_build_sar1(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) ||
01153             ikev2_build_ker(data, msg, IKEV2_PAYLOAD_NONCE) ||
01154             ikev2_build_nr(data, msg, data->peer_auth == PEER_AUTH_SECRET ?
01155                            IKEV2_PAYLOAD_ENCRYPTED :
01156                            IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) {
01157                 wpabuf_free(msg);
01158                 return NULL;
01159         }
01160 
01161         if (ikev2_derive_keys(data)) {
01162                 wpabuf_free(msg);
01163                 return NULL;
01164         }
01165 
01166         if (data->peer_auth == PEER_AUTH_CERT) {
01167                 /* TODO: CERTREQ with SHA-1 hashes of Subject Public Key Info
01168                  * for trust agents */
01169         }
01170 
01171         if (data->peer_auth == PEER_AUTH_SECRET) {
01172                 struct wpabuf *plain = wpabuf_alloc(data->IDr_len + 1000);
01173                 if (plain == NULL) {
01174                         wpabuf_free(msg);
01175                         return NULL;
01176                 }
01177                 if (ikev2_build_idr(data, plain,
01178                                     IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
01179                     ikev2_build_encrypted(data->proposal.encr,
01180                                           data->proposal.integ,
01181                                           &data->keys, 0, msg, plain,
01182                                           IKEV2_PAYLOAD_IDr)) {
01183                         wpabuf_free(plain);
01184                         wpabuf_free(msg);
01185                         return NULL;
01186                 }
01187                 wpabuf_free(plain);
01188         }
01189 
01190         ikev2_update_hdr(msg);
01191 
01192         wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg);
01193 
01194         data->state = SA_AUTH;
01195 
01196         wpabuf_free(data->r_sign_msg);
01197         data->r_sign_msg = wpabuf_dup(msg);
01198 
01199         return msg;
01200 }
01201 
01202 
01203 static struct wpabuf * ikev2_build_sa_auth(struct ikev2_responder_data *data)
01204 {
01205         struct wpabuf *msg, *plain;
01206 
01207         /* build IKE_SA_AUTH: HDR, SK {IDr, [CERT,] AUTH} */
01208 
01209         msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000);
01210         if (msg == NULL)
01211                 return NULL;
01212         ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1);
01213 
01214         plain = wpabuf_alloc(data->IDr_len + 1000);
01215         if (plain == NULL) {
01216                 wpabuf_free(msg);
01217                 return NULL;
01218         }
01219 
01220         if (ikev2_build_idr(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) ||
01221             ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
01222             ikev2_build_encrypted(data->proposal.encr, data->proposal.integ,
01223                                   &data->keys, 0, msg, plain,
01224                                   IKEV2_PAYLOAD_IDr)) {
01225                 wpabuf_free(plain);
01226                 wpabuf_free(msg);
01227                 return NULL;
01228         }
01229         wpabuf_free(plain);
01230 
01231         wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg);
01232 
01233         data->state = IKEV2_DONE;
01234 
01235         return msg;
01236 }
01237 
01238 
01239 static struct wpabuf * ikev2_build_notify(struct ikev2_responder_data *data)
01240 {
01241         struct wpabuf *msg;
01242 
01243         msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000);
01244         if (msg == NULL)
01245                 return NULL;
01246         if (data->last_msg == LAST_MSG_SA_AUTH) {
01247                 /* HDR, SK{N} */
01248                 struct wpabuf *plain = wpabuf_alloc(100);
01249                 if (plain == NULL) {
01250                         wpabuf_free(msg);
01251                         return NULL;
01252                 }
01253                 ikev2_build_hdr(data, msg, IKE_SA_AUTH,
01254                                 IKEV2_PAYLOAD_ENCRYPTED, 1);
01255                 if (ikev2_build_notification(data, plain,
01256                                              IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||
01257                     ikev2_build_encrypted(data->proposal.encr,
01258                                           data->proposal.integ,
01259                                           &data->keys, 0, msg, plain,
01260                                           IKEV2_PAYLOAD_NOTIFICATION)) {
01261                         wpabuf_free(plain);
01262                         wpabuf_free(msg);
01263                         return NULL;
01264                 }
01265                 data->state = IKEV2_FAILED;
01266         } else {
01267                 /* HDR, N */
01268                 ikev2_build_hdr(data, msg, IKE_SA_INIT,
01269                                 IKEV2_PAYLOAD_NOTIFICATION, 0);
01270                 if (ikev2_build_notification(data, msg,
01271                                              IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) {
01272                         wpabuf_free(msg);
01273                         return NULL;
01274                 }
01275                 data->state = SA_INIT;
01276         }
01277 
01278         ikev2_update_hdr(msg);
01279 
01280         wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (Notification)",
01281                         msg);
01282 
01283         return msg;
01284 }
01285 
01286 
01287 struct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data)
01288 {
01289         switch (data->state) {
01290         case SA_INIT:
01291                 return ikev2_build_sa_init(data);
01292         case SA_AUTH:
01293                 return ikev2_build_sa_auth(data);
01294         case CHILD_SA:
01295                 return NULL;
01296         case NOTIFY:
01297                 return ikev2_build_notify(data);
01298         case IKEV2_DONE:
01299         case IKEV2_FAILED:
01300                 return NULL;
01301         }
01302         return NULL;
01303 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:38