ikev2.c

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

Generated on Sat Nov 21 23:16:52 2009 for hostapd by  doxygen 1.6.1