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


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:35