1 /* 2 * IEEE 802.1X-2010 Key Agreement Protocol of PAE state machine 3 * Copyright (c) 2013, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include <time.h> 10 #include "includes.h" 11 #include "common.h" 12 #include "list.h" 13 #include "eloop.h" 14 #include "wpabuf.h" 15 #include "state_machine.h" 16 #include "l2_packet/l2_packet.h" 17 #include "common/eapol_common.h" 18 #include "crypto/aes_wrap.h" 19 #include "ieee802_1x_cp.h" 20 #include "ieee802_1x_key.h" 21 #include "ieee802_1x_kay.h" 22 #include "ieee802_1x_kay_i.h" 23 #include "ieee802_1x_secy_ops.h" 24 25 26 #define DEFAULT_SA_KEY_LEN 16 27 #define DEFAULT_ICV_LEN 16 28 #define MAX_ICV_LEN 32 /* 32 bytes, 256 bits */ 29 30 #define MAX_MISSING_SAK_USE 10 /* Accept up to 10 inbound MKPDUs without 31 * SAK-USE before dropping */ 32 33 #define PENDING_PN_EXHAUSTION 0xC0000000 34 35 #define MKA_ALIGN_LENGTH(len) (((len) + 0x3) & ~0x3) 36 37 /* IEEE Std 802.1X-2010, Table 9-1 - MKA Algorithm Agility */ 38 #define MKA_ALGO_AGILITY_2009 { 0x00, 0x80, 0xC2, 0x01 } 39 static u8 mka_algo_agility[4] = MKA_ALGO_AGILITY_2009; 40 41 /* IEEE802.1AE-2006 Table 14-1 MACsec Cipher Suites */ 42 static struct macsec_ciphersuite cipher_suite_tbl[] = { 43 /* GCM-AES-128 */ 44 { 45 .id = CS_ID_GCM_AES_128, 46 .name = CS_NAME_GCM_AES_128, 47 .capable = MACSEC_CAP_INTEG_AND_CONF_0_30_50, 48 .sak_len = DEFAULT_SA_KEY_LEN, 49 }, 50 /* GCM-AES-256 */ 51 { 52 .id = CS_ID_GCM_AES_256, 53 .name = CS_NAME_GCM_AES_256, 54 .capable = MACSEC_CAP_INTEG_AND_CONF_0_30_50, 55 .sak_len = 32, 56 }, 57 }; 58 #define CS_TABLE_SIZE (ARRAY_SIZE(cipher_suite_tbl)) 59 #define DEFAULT_CS_INDEX 0 60 61 static struct mka_alg mka_alg_tbl[] = { 62 { 63 .parameter = MKA_ALGO_AGILITY_2009, 64 65 .icv_len = DEFAULT_ICV_LEN, 66 67 .cak_trfm = ieee802_1x_cak_aes_cmac, 68 .ckn_trfm = ieee802_1x_ckn_aes_cmac, 69 .kek_trfm = ieee802_1x_kek_aes_cmac, 70 .ick_trfm = ieee802_1x_ick_aes_cmac, 71 .icv_hash = ieee802_1x_icv_aes_cmac, 72 }, 73 }; 74 #define MKA_ALG_TABLE_SIZE (ARRAY_SIZE(mka_alg_tbl)) 75 76 77 static int is_ki_equal(struct ieee802_1x_mka_ki *ki1, 78 struct ieee802_1x_mka_ki *ki2) 79 { 80 return os_memcmp(ki1->mi, ki2->mi, MI_LEN) == 0 && 81 ki1->kn == ki2->kn; 82 } 83 84 85 static void set_mka_param_body_len(void *body, unsigned int len) 86 { 87 struct ieee802_1x_mka_hdr *hdr = body; 88 hdr->length = (len >> 8) & 0x0f; 89 hdr->length1 = len & 0xff; 90 } 91 92 93 static unsigned int get_mka_param_body_len(const void *body) 94 { 95 const struct ieee802_1x_mka_hdr *hdr = body; 96 return (hdr->length << 8) | hdr->length1; 97 } 98 99 100 static u8 get_mka_param_body_type(const void *body) 101 { 102 const struct ieee802_1x_mka_hdr *hdr = body; 103 return hdr->type; 104 } 105 106 107 static const char * mi_txt(const u8 *mi) 108 { 109 static char txt[MI_LEN * 2 + 1]; 110 111 wpa_snprintf_hex(txt, sizeof(txt), mi, MI_LEN); 112 return txt; 113 } 114 115 116 static const char * sci_txt(const struct ieee802_1x_mka_sci *sci) 117 { 118 static char txt[ETH_ALEN * 3 + 1 + 5 + 1]; 119 120 os_snprintf(txt, sizeof(txt), MACSTR "@%u", 121 MAC2STR(sci->addr), be_to_host16(sci->port)); 122 return txt; 123 } 124 125 126 static const char * algo_agility_txt(const u8 *algo_agility) 127 { 128 static char txt[4 * 2 + 1]; 129 130 wpa_snprintf_hex(txt, sizeof(txt), algo_agility, 4); 131 return txt; 132 } 133 134 135 /** 136 * ieee802_1x_mka_dump_basic_body - 137 */ 138 static void 139 ieee802_1x_mka_dump_basic_body(struct ieee802_1x_mka_basic_body *body) 140 { 141 size_t body_len; 142 143 if (!body) 144 return; 145 146 /* IEEE Std 802.1X-2010, Figure 11-8 */ 147 body_len = get_mka_param_body_len(body); 148 wpa_printf(MSG_DEBUG, "MKA Basic Parameter Set"); 149 wpa_printf(MSG_DEBUG, "\tMKA Version Identifier: %d", body->version); 150 wpa_printf(MSG_DEBUG, "\tKey Server Priority: %d", body->priority); 151 wpa_printf(MSG_DEBUG, "\tKey Server: %d", body->key_server); 152 wpa_printf(MSG_DEBUG, "\tMACsec Desired: %d", body->macsec_desired); 153 wpa_printf(MSG_DEBUG, "\tMACsec Capability: %d", 154 body->macsec_capability); 155 wpa_printf(MSG_DEBUG, "\tParameter set body length: %zu", body_len); 156 wpa_printf(MSG_DEBUG, "\tSCI: %s", sci_txt(&body->actor_sci)); 157 wpa_printf(MSG_DEBUG, "\tActor's Member Identifier: %s", 158 mi_txt(body->actor_mi)); 159 wpa_printf(MSG_DEBUG, "\tActor's Message Number: %d", 160 be_to_host32(body->actor_mn)); 161 wpa_printf(MSG_DEBUG, "\tAlgorithm Agility: %s", 162 algo_agility_txt(body->algo_agility)); 163 wpa_hexdump(MSG_DEBUG, "\tCAK Name", body->ckn, 164 body_len + MKA_HDR_LEN - sizeof(*body)); 165 } 166 167 168 /** 169 * ieee802_1x_mka_dump_peer_body - 170 */ 171 static void 172 ieee802_1x_mka_dump_peer_body(struct ieee802_1x_mka_peer_body *body) 173 { 174 size_t body_len; 175 size_t i; 176 u8 *mi; 177 be32 mn; 178 179 if (body == NULL) 180 return; 181 182 /* IEEE Std 802.1X-2010, Figure 11-9 */ 183 body_len = get_mka_param_body_len(body); 184 if (body->type == MKA_LIVE_PEER_LIST) { 185 wpa_printf(MSG_DEBUG, "Live Peer List parameter set"); 186 wpa_printf(MSG_DEBUG, "\tBody Length: %zu", body_len); 187 } else if (body->type == MKA_POTENTIAL_PEER_LIST) { 188 wpa_printf(MSG_DEBUG, "Potential Peer List parameter set"); 189 wpa_printf(MSG_DEBUG, "\tBody Length: %zu", body_len); 190 } 191 192 for (i = 0; i < body_len; i += MI_LEN + sizeof(mn)) { 193 mi = body->peer + i; 194 os_memcpy(&mn, mi + MI_LEN, sizeof(mn)); 195 wpa_printf(MSG_DEBUG, "\tMember Id: %s Message Number: %d", 196 mi_txt(mi), be_to_host32(mn)); 197 } 198 } 199 200 201 /** 202 * ieee802_1x_mka_dump_dist_sak_body - 203 */ 204 static void 205 ieee802_1x_mka_dump_dist_sak_body(struct ieee802_1x_mka_dist_sak_body *body) 206 { 207 size_t body_len; 208 209 if (body == NULL) 210 return; 211 212 /* IEEE Std 802.1X-2010, Figure 11-11 and 11-12 */ 213 body_len = get_mka_param_body_len(body); 214 wpa_printf(MSG_DEBUG, "Distributed SAK parameter set"); 215 wpa_printf(MSG_DEBUG, "\tDistributed AN........: %d", body->dan); 216 wpa_printf(MSG_DEBUG, "\tConfidentiality Offset: %d", 217 body->confid_offset); 218 wpa_printf(MSG_DEBUG, "\tBody Length...........: %zu", body_len); 219 if (!body_len) 220 return; 221 222 wpa_printf(MSG_DEBUG, "\tKey Number............: %d", 223 be_to_host32(body->kn)); 224 /* TODO: Other than GCM-AES-128 case: MACsec Cipher Suite */ 225 wpa_hexdump(MSG_DEBUG, "\tAES Key Wrap of SAK...:", body->sak, 24); 226 } 227 228 229 static const char * yes_no(int val) 230 { 231 return val ? "Yes" : "No"; 232 } 233 234 235 /** 236 * ieee802_1x_mka_dump_sak_use_body - 237 */ 238 static void 239 ieee802_1x_mka_dump_sak_use_body(struct ieee802_1x_mka_sak_use_body *body) 240 { 241 int body_len; 242 243 if (body == NULL) 244 return; 245 246 /* IEEE Std 802.1X-2010, Figure 11-10 */ 247 body_len = get_mka_param_body_len(body); 248 wpa_printf(MSG_DEBUG, "MACsec SAK Use parameter set"); 249 wpa_printf(MSG_DEBUG, "\tLatest Key AN....: %d", body->lan); 250 wpa_printf(MSG_DEBUG, "\tLatest Key Tx....: %s", yes_no(body->ltx)); 251 wpa_printf(MSG_DEBUG, "\tLatest Key Rx....: %s", yes_no(body->lrx)); 252 wpa_printf(MSG_DEBUG, "\tOld Key AN.......: %d", body->oan); 253 wpa_printf(MSG_DEBUG, "\tOld Key Tx.......: %s", yes_no(body->otx)); 254 wpa_printf(MSG_DEBUG, "\tOld Key Rx.......: %s", yes_no(body->orx)); 255 wpa_printf(MSG_DEBUG, "\tPlain Tx.........: %s", yes_no(body->ptx)); 256 wpa_printf(MSG_DEBUG, "\tPlain Rx.........: %s", yes_no(body->prx)); 257 wpa_printf(MSG_DEBUG, "\tDelay Protect....: %s", 258 yes_no(body->delay_protect)); 259 wpa_printf(MSG_DEBUG, "\tBody Length......: %d", body_len); 260 if (!body_len) 261 return; 262 263 wpa_printf(MSG_DEBUG, "\tKey Server MI....: %s", mi_txt(body->lsrv_mi)); 264 wpa_printf(MSG_DEBUG, "\tKey Number.......: %u", 265 be_to_host32(body->lkn)); 266 wpa_printf(MSG_DEBUG, "\tLowest PN........: %u", 267 be_to_host32(body->llpn)); 268 wpa_printf(MSG_DEBUG, "\tOld Key Server MI: %s", mi_txt(body->osrv_mi)); 269 wpa_printf(MSG_DEBUG, "\tOld Key Number...: %u", 270 be_to_host32(body->okn)); 271 wpa_printf(MSG_DEBUG, "\tOld Lowest PN....: %u", 272 be_to_host32(body->olpn)); 273 } 274 275 276 /** 277 * ieee802_1x_kay_get_participant - 278 */ 279 static struct ieee802_1x_mka_participant * 280 ieee802_1x_kay_get_participant(struct ieee802_1x_kay *kay, const u8 *ckn, 281 size_t len) 282 { 283 struct ieee802_1x_mka_participant *participant; 284 285 dl_list_for_each(participant, &kay->participant_list, 286 struct ieee802_1x_mka_participant, list) { 287 if (participant->ckn.len == len && 288 os_memcmp(participant->ckn.name, ckn, 289 participant->ckn.len) == 0) 290 return participant; 291 } 292 293 wpa_printf(MSG_DEBUG, "KaY: participant is not found"); 294 295 return NULL; 296 } 297 298 299 /** 300 * ieee802_1x_kay_get_principal_participant - 301 */ 302 static struct ieee802_1x_mka_participant * 303 ieee802_1x_kay_get_principal_participant(struct ieee802_1x_kay *kay) 304 { 305 struct ieee802_1x_mka_participant *participant; 306 307 dl_list_for_each(participant, &kay->participant_list, 308 struct ieee802_1x_mka_participant, list) { 309 if (participant->principal) 310 return participant; 311 } 312 313 wpa_printf(MSG_DEBUG, "KaY: principal participant is not found"); 314 return NULL; 315 } 316 317 318 static struct ieee802_1x_kay_peer * get_peer_mi(struct dl_list *peers, 319 const u8 *mi) 320 { 321 struct ieee802_1x_kay_peer *peer; 322 323 dl_list_for_each(peer, peers, struct ieee802_1x_kay_peer, list) { 324 if (os_memcmp(peer->mi, mi, MI_LEN) == 0) 325 return peer; 326 } 327 328 return NULL; 329 } 330 331 332 /** 333 * ieee802_1x_kay_get_potential_peer 334 */ 335 static struct ieee802_1x_kay_peer * 336 ieee802_1x_kay_get_potential_peer( 337 struct ieee802_1x_mka_participant *participant, const u8 *mi) 338 { 339 return get_peer_mi(&participant->potential_peers, mi); 340 } 341 342 343 /** 344 * ieee802_1x_kay_get_live_peer 345 */ 346 static struct ieee802_1x_kay_peer * 347 ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant, 348 const u8 *mi) 349 { 350 return get_peer_mi(&participant->live_peers, mi); 351 } 352 353 354 /** 355 * ieee802_1x_kay_is_in_potential_peer 356 */ 357 static Boolean 358 ieee802_1x_kay_is_in_potential_peer( 359 struct ieee802_1x_mka_participant *participant, const u8 *mi) 360 { 361 return ieee802_1x_kay_get_potential_peer(participant, mi) != NULL; 362 } 363 364 365 /** 366 * ieee802_1x_kay_is_in_live_peer 367 */ 368 static Boolean 369 ieee802_1x_kay_is_in_live_peer( 370 struct ieee802_1x_mka_participant *participant, const u8 *mi) 371 { 372 return ieee802_1x_kay_get_live_peer(participant, mi) != NULL; 373 } 374 375 376 /** 377 * ieee802_1x_kay_get_peer 378 */ 379 static struct ieee802_1x_kay_peer * 380 ieee802_1x_kay_get_peer(struct ieee802_1x_mka_participant *participant, 381 const u8 *mi) 382 { 383 struct ieee802_1x_kay_peer *peer; 384 385 peer = ieee802_1x_kay_get_live_peer(participant, mi); 386 if (peer) 387 return peer; 388 389 return ieee802_1x_kay_get_potential_peer(participant, mi); 390 } 391 392 393 /** 394 * ieee802_1x_kay_get_cipher_suite 395 */ 396 static struct macsec_ciphersuite * 397 ieee802_1x_kay_get_cipher_suite(struct ieee802_1x_mka_participant *participant, 398 const u8 *cs_id, unsigned int *idx) 399 { 400 unsigned int i; 401 u64 cs; 402 be64 _cs; 403 404 os_memcpy(&_cs, cs_id, CS_ID_LEN); 405 cs = be_to_host64(_cs); 406 407 for (i = 0; i < CS_TABLE_SIZE; i++) { 408 if (cipher_suite_tbl[i].id == cs) { 409 *idx = i; 410 return &cipher_suite_tbl[i]; 411 } 412 } 413 414 return NULL; 415 } 416 417 418 u64 mka_sci_u64(struct ieee802_1x_mka_sci *sci) 419 { 420 struct ieee802_1x_mka_sci tmp; 421 422 os_memcpy(tmp.addr, sci->addr, ETH_ALEN); 423 tmp.port = sci->port; 424 425 return *((u64 *) &tmp); 426 } 427 428 429 static Boolean sci_equal(const struct ieee802_1x_mka_sci *a, 430 const struct ieee802_1x_mka_sci *b) 431 { 432 return os_memcmp(a, b, sizeof(struct ieee802_1x_mka_sci)) == 0; 433 } 434 435 436 /** 437 * ieee802_1x_kay_get_peer_sci 438 */ 439 static struct ieee802_1x_kay_peer * 440 ieee802_1x_kay_get_peer_sci(struct ieee802_1x_mka_participant *participant, 441 const struct ieee802_1x_mka_sci *sci) 442 { 443 struct ieee802_1x_kay_peer *peer; 444 445 dl_list_for_each(peer, &participant->live_peers, 446 struct ieee802_1x_kay_peer, list) { 447 if (sci_equal(&peer->sci, sci)) 448 return peer; 449 } 450 451 dl_list_for_each(peer, &participant->potential_peers, 452 struct ieee802_1x_kay_peer, list) { 453 if (sci_equal(&peer->sci, sci)) 454 return peer; 455 } 456 457 return NULL; 458 } 459 460 461 static void ieee802_1x_kay_use_data_key(struct data_key *pkey); 462 463 /** 464 * ieee802_1x_kay_init_receive_sa - 465 */ 466 static struct receive_sa * 467 ieee802_1x_kay_init_receive_sa(struct receive_sc *psc, u8 an, u32 lowest_pn, 468 struct data_key *key) 469 { 470 struct receive_sa *psa; 471 472 if (!psc || !key) 473 return NULL; 474 475 psa = os_zalloc(sizeof(*psa)); 476 if (!psa) { 477 wpa_printf(MSG_ERROR, "%s: out of memory", __func__); 478 return NULL; 479 } 480 481 ieee802_1x_kay_use_data_key(key); 482 psa->pkey = key; 483 psa->lowest_pn = lowest_pn; 484 psa->next_pn = lowest_pn; 485 psa->an = an; 486 psa->sc = psc; 487 488 os_get_time(&psa->created_time); 489 psa->in_use = FALSE; 490 491 dl_list_add(&psc->sa_list, &psa->list); 492 wpa_printf(MSG_DEBUG, 493 "KaY: Create receive SA(an: %hhu lowest_pn: %u) of SC", 494 an, lowest_pn); 495 496 return psa; 497 } 498 499 500 static void ieee802_1x_kay_deinit_data_key(struct data_key *pkey); 501 502 /** 503 * ieee802_1x_kay_deinit_receive_sa - 504 */ 505 static void ieee802_1x_kay_deinit_receive_sa(struct receive_sa *psa) 506 { 507 ieee802_1x_kay_deinit_data_key(psa->pkey); 508 psa->pkey = NULL; 509 wpa_printf(MSG_DEBUG, 510 "KaY: Delete receive SA(an: %hhu) of SC", 511 psa->an); 512 dl_list_del(&psa->list); 513 os_free(psa); 514 } 515 516 517 /** 518 * ieee802_1x_kay_init_receive_sc - 519 */ 520 static struct receive_sc * 521 ieee802_1x_kay_init_receive_sc(const struct ieee802_1x_mka_sci *psci) 522 { 523 struct receive_sc *psc; 524 525 if (!psci) 526 return NULL; 527 528 psc = os_zalloc(sizeof(*psc)); 529 if (!psc) { 530 wpa_printf(MSG_ERROR, "%s: out of memory", __func__); 531 return NULL; 532 } 533 534 os_memcpy(&psc->sci, psci, sizeof(psc->sci)); 535 536 os_get_time(&psc->created_time); 537 psc->receiving = FALSE; 538 539 dl_list_init(&psc->sa_list); 540 wpa_printf(MSG_DEBUG, "KaY: Create receive SC: SCI %s", 541 sci_txt(&psc->sci)); 542 543 return psc; 544 } 545 546 547 static void ieee802_1x_delete_receive_sa(struct ieee802_1x_kay *kay, 548 struct receive_sa *sa) 549 { 550 secy_disable_receive_sa(kay, sa); 551 secy_delete_receive_sa(kay, sa); 552 ieee802_1x_kay_deinit_receive_sa(sa); 553 } 554 555 556 /** 557 * ieee802_1x_kay_deinit_receive_sc - 558 **/ 559 static void 560 ieee802_1x_kay_deinit_receive_sc( 561 struct ieee802_1x_mka_participant *participant, struct receive_sc *psc) 562 { 563 struct receive_sa *psa, *pre_sa; 564 565 wpa_printf(MSG_DEBUG, "KaY: Delete receive SC"); 566 dl_list_for_each_safe(psa, pre_sa, &psc->sa_list, struct receive_sa, 567 list) 568 ieee802_1x_delete_receive_sa(participant->kay, psa); 569 570 dl_list_del(&psc->list); 571 secy_delete_receive_sc(participant->kay, psc); 572 os_free(psc); 573 } 574 575 576 static void ieee802_1x_kay_dump_peer(struct ieee802_1x_kay_peer *peer) 577 { 578 wpa_printf(MSG_DEBUG, "\tMI: %s MN: %d SCI: %s", 579 mi_txt(peer->mi), peer->mn, sci_txt(&peer->sci)); 580 } 581 582 583 static struct ieee802_1x_kay_peer * 584 ieee802_1x_kay_create_peer(const u8 *mi, u32 mn) 585 { 586 struct ieee802_1x_kay_peer *peer; 587 588 peer = os_zalloc(sizeof(*peer)); 589 if (!peer) { 590 wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__); 591 return NULL; 592 } 593 594 os_memcpy(peer->mi, mi, MI_LEN); 595 peer->mn = mn; 596 peer->expire = time(NULL) + MKA_LIFE_TIME / 1000; 597 peer->sak_used = FALSE; 598 peer->missing_sak_use_count = 0; 599 600 return peer; 601 } 602 603 604 /** 605 * ieee802_1x_kay_create_live_peer 606 */ 607 static struct ieee802_1x_kay_peer * 608 ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant *participant, 609 const u8 *mi, u32 mn) 610 { 611 struct ieee802_1x_kay_peer *peer; 612 struct receive_sc *rxsc; 613 614 peer = ieee802_1x_kay_create_peer(mi, mn); 615 if (!peer) 616 return NULL; 617 618 os_memcpy(&peer->sci, &participant->current_peer_sci, 619 sizeof(peer->sci)); 620 621 rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci); 622 if (!rxsc) { 623 os_free(peer); 624 return NULL; 625 } 626 627 if (secy_create_receive_sc(participant->kay, rxsc)) { 628 os_free(rxsc); 629 os_free(peer); 630 return NULL; 631 } 632 dl_list_add(&participant->live_peers, &peer->list); 633 dl_list_add(&participant->rxsc_list, &rxsc->list); 634 635 wpa_printf(MSG_DEBUG, "KaY: Live peer created"); 636 ieee802_1x_kay_dump_peer(peer); 637 638 return peer; 639 } 640 641 642 /** 643 * ieee802_1x_kay_create_potential_peer 644 */ 645 static struct ieee802_1x_kay_peer * 646 ieee802_1x_kay_create_potential_peer( 647 struct ieee802_1x_mka_participant *participant, const u8 *mi, u32 mn) 648 { 649 struct ieee802_1x_kay_peer *peer; 650 651 peer = ieee802_1x_kay_create_peer(mi, mn); 652 if (!peer) 653 return NULL; 654 655 dl_list_add(&participant->potential_peers, &peer->list); 656 657 wpa_printf(MSG_DEBUG, "KaY: Potential peer created"); 658 ieee802_1x_kay_dump_peer(peer); 659 660 return peer; 661 } 662 663 664 /** 665 * ieee802_1x_kay_move_live_peer 666 */ 667 static struct ieee802_1x_kay_peer * 668 ieee802_1x_kay_move_live_peer(struct ieee802_1x_mka_participant *participant, 669 u8 *mi, u32 mn) 670 { 671 struct ieee802_1x_kay_peer *peer; 672 struct receive_sc *rxsc; 673 674 peer = ieee802_1x_kay_get_potential_peer(participant, mi); 675 if (!peer) 676 return NULL; 677 678 rxsc = ieee802_1x_kay_init_receive_sc(&participant->current_peer_sci); 679 if (!rxsc) 680 return NULL; 681 682 os_memcpy(&peer->sci, &participant->current_peer_sci, 683 sizeof(peer->sci)); 684 peer->mn = mn; 685 peer->expire = time(NULL) + MKA_LIFE_TIME / 1000; 686 687 wpa_printf(MSG_DEBUG, "KaY: Move potential peer to live peer"); 688 ieee802_1x_kay_dump_peer(peer); 689 690 dl_list_del(&peer->list); 691 if (secy_create_receive_sc(participant->kay, rxsc)) { 692 wpa_printf(MSG_ERROR, "KaY: Can't create SC, discard peer"); 693 os_free(rxsc); 694 os_free(peer); 695 return NULL; 696 } 697 dl_list_add_tail(&participant->live_peers, &peer->list); 698 699 dl_list_add(&participant->rxsc_list, &rxsc->list); 700 701 return peer; 702 } 703 704 705 706 /** 707 * ieee802_1x_mka_basic_body_present - 708 */ 709 static Boolean 710 ieee802_1x_mka_basic_body_present( 711 struct ieee802_1x_mka_participant *participant) 712 { 713 return TRUE; 714 } 715 716 717 /** 718 * ieee802_1x_mka_basic_body_length - 719 */ 720 static int 721 ieee802_1x_mka_basic_body_length(struct ieee802_1x_mka_participant *participant) 722 { 723 int length; 724 725 length = sizeof(struct ieee802_1x_mka_basic_body); 726 length += participant->ckn.len; 727 return MKA_ALIGN_LENGTH(length); 728 } 729 730 731 /** 732 * ieee802_1x_mka_encode_basic_body 733 */ 734 static int 735 ieee802_1x_mka_encode_basic_body( 736 struct ieee802_1x_mka_participant *participant, 737 struct wpabuf *buf) 738 { 739 struct ieee802_1x_mka_basic_body *body; 740 struct ieee802_1x_kay *kay = participant->kay; 741 unsigned int length = sizeof(struct ieee802_1x_mka_basic_body); 742 743 length += participant->ckn.len; 744 body = wpabuf_put(buf, MKA_ALIGN_LENGTH(length)); 745 746 body->version = kay->mka_version; 747 body->priority = kay->actor_priority; 748 /* The Key Server flag is set if and only if the participant has not 749 * decided that another participant is or will be the Key Server. */ 750 if (participant->is_elected) 751 body->key_server = participant->is_key_server; 752 else 753 body->key_server = participant->can_be_key_server; 754 755 body->macsec_desired = kay->macsec_desired; 756 body->macsec_capability = kay->macsec_capable; 757 set_mka_param_body_len(body, length - MKA_HDR_LEN); 758 759 os_memcpy(body->actor_sci.addr, kay->actor_sci.addr, 760 sizeof(kay->actor_sci.addr)); 761 body->actor_sci.port = kay->actor_sci.port; 762 763 os_memcpy(body->actor_mi, participant->mi, sizeof(body->actor_mi)); 764 participant->mn = participant->mn + 1; 765 body->actor_mn = host_to_be32(participant->mn); 766 os_memcpy(body->algo_agility, kay->algo_agility, 767 sizeof(body->algo_agility)); 768 769 os_memcpy(body->ckn, participant->ckn.name, participant->ckn.len); 770 771 ieee802_1x_mka_dump_basic_body(body); 772 773 return 0; 774 } 775 776 777 static Boolean 778 reset_participant_mi(struct ieee802_1x_mka_participant *participant) 779 { 780 if (os_get_random(participant->mi, sizeof(participant->mi)) < 0) 781 return FALSE; 782 participant->mn = 0; 783 784 return TRUE; 785 } 786 787 788 /** 789 * ieee802_1x_mka_decode_basic_body - 790 */ 791 static struct ieee802_1x_mka_participant * 792 ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg, 793 size_t msg_len) 794 { 795 struct ieee802_1x_mka_participant *participant; 796 const struct ieee802_1x_mka_basic_body *body; 797 struct ieee802_1x_kay_peer *peer; 798 size_t ckn_len; 799 size_t body_len; 800 801 body = (const struct ieee802_1x_mka_basic_body *) mka_msg; 802 803 if (body->version > MKA_VERSION_ID) { 804 wpa_printf(MSG_DEBUG, 805 "KaY: Peer's version(%d) greater than MKA current version(%d)", 806 body->version, MKA_VERSION_ID); 807 } 808 if (kay->is_obliged_key_server && body->key_server) { 809 wpa_printf(MSG_DEBUG, "KaY: I must be key server - ignore MKPDU claiming to be from a key server"); 810 return NULL; 811 } 812 813 body_len = get_mka_param_body_len(body); 814 if (body_len < sizeof(struct ieee802_1x_mka_basic_body) - MKA_HDR_LEN) { 815 wpa_printf(MSG_DEBUG, "KaY: Too small body length %zu", 816 body_len); 817 return NULL; 818 } 819 ckn_len = body_len - 820 (sizeof(struct ieee802_1x_mka_basic_body) - MKA_HDR_LEN); 821 participant = ieee802_1x_kay_get_participant(kay, body->ckn, ckn_len); 822 if (!participant) { 823 wpa_printf(MSG_DEBUG, 824 "KaY: Peer is not included in my CA - ignore MKPDU"); 825 return NULL; 826 } 827 828 /* If the peer's MI is my MI, I will choose new MI */ 829 if (os_memcmp(body->actor_mi, participant->mi, MI_LEN) == 0) { 830 if (!reset_participant_mi(participant)) 831 return NULL; 832 wpa_printf(MSG_DEBUG, 833 "KaY: Peer using my MI - selected a new random MI: %s", 834 mi_txt(participant->mi)); 835 } 836 837 os_memcpy(participant->current_peer_id.mi, body->actor_mi, MI_LEN); 838 participant->current_peer_id.mn = body->actor_mn; 839 os_memcpy(participant->current_peer_sci.addr, body->actor_sci.addr, 840 sizeof(participant->current_peer_sci.addr)); 841 participant->current_peer_sci.port = body->actor_sci.port; 842 843 /* handler peer */ 844 peer = ieee802_1x_kay_get_peer(participant, body->actor_mi); 845 if (!peer) { 846 /* Check duplicated SCI 847 * 848 * A duplicated SCI indicates either an active attacker or 849 * a valid peer whose MI is being changed. The latter scenario 850 * is more likely because to have gotten this far the received 851 * MKPDU must have had a valid ICV, indicating the peer holds 852 * the same CAK as our participant. 853 * 854 * Before creating a new peer object for the new MI we must 855 * clean up the resources (SCs and SAs) associated with the 856 * old peer. An easy way to do this is to ignore MKPDUs with 857 * the new MI's for now and just wait for the old peer to 858 * time out and clean itself up (within MKA_LIFE_TIME). 859 * 860 * This method is preferable to deleting the old peer here 861 * and now and continuing on with processing because if this 862 * MKPDU is from an attacker it's better to ignore the MKPDU 863 * than to process it (and delete a valid peer as well). 864 */ 865 peer = ieee802_1x_kay_get_peer_sci(participant, 866 &body->actor_sci); 867 if (peer) { 868 time_t new_expire; 869 870 wpa_printf(MSG_WARNING, 871 "KaY: duplicated SCI detected - maybe active attacker or peer selected new MI - ignore MKPDU"); 872 /* Reduce timeout to speed up this process but left the 873 * chance for old one to prove aliveness. */ 874 new_expire = time(NULL) + MKA_HELLO_TIME * 1.5 / 1000; 875 if (peer->expire > new_expire) 876 peer->expire = new_expire; 877 return NULL; 878 } 879 880 peer = ieee802_1x_kay_create_potential_peer( 881 participant, body->actor_mi, 882 be_to_host32(body->actor_mn)); 883 if (!peer) { 884 wpa_printf(MSG_DEBUG, 885 "KaY: No potential peer entry found - ignore MKPDU"); 886 return NULL; 887 } 888 889 peer->macsec_desired = body->macsec_desired; 890 peer->macsec_capability = body->macsec_capability; 891 peer->is_key_server = (Boolean) body->key_server; 892 peer->key_server_priority = body->priority; 893 } else if (peer->mn < be_to_host32(body->actor_mn)) { 894 peer->mn = be_to_host32(body->actor_mn); 895 peer->macsec_desired = body->macsec_desired; 896 peer->macsec_capability = body->macsec_capability; 897 peer->is_key_server = (Boolean) body->key_server; 898 peer->key_server_priority = body->priority; 899 } else { 900 wpa_printf(MSG_WARNING, 901 "KaY: The peer MN did not increase - ignore MKPDU"); 902 return NULL; 903 } 904 905 return participant; 906 } 907 908 909 /** 910 * ieee802_1x_mka_live_peer_body_present 911 */ 912 static Boolean 913 ieee802_1x_mka_live_peer_body_present( 914 struct ieee802_1x_mka_participant *participant) 915 { 916 return !dl_list_empty(&participant->live_peers); 917 } 918 919 920 /** 921 * ieee802_1x_kay_get_live_peer_length 922 */ 923 static int 924 ieee802_1x_mka_get_live_peer_length( 925 struct ieee802_1x_mka_participant *participant) 926 { 927 int len = MKA_HDR_LEN; 928 struct ieee802_1x_kay_peer *peer; 929 930 dl_list_for_each(peer, &participant->live_peers, 931 struct ieee802_1x_kay_peer, list) 932 len += sizeof(struct ieee802_1x_mka_peer_id); 933 934 return MKA_ALIGN_LENGTH(len); 935 } 936 937 938 /** 939 * ieee802_1x_mka_encode_live_peer_body - 940 */ 941 static int 942 ieee802_1x_mka_encode_live_peer_body( 943 struct ieee802_1x_mka_participant *participant, 944 struct wpabuf *buf) 945 { 946 struct ieee802_1x_mka_peer_body *body; 947 struct ieee802_1x_kay_peer *peer; 948 unsigned int length; 949 struct ieee802_1x_mka_peer_id *body_peer; 950 951 length = ieee802_1x_mka_get_live_peer_length(participant); 952 body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_peer_body)); 953 954 body->type = MKA_LIVE_PEER_LIST; 955 set_mka_param_body_len(body, length - MKA_HDR_LEN); 956 957 dl_list_for_each(peer, &participant->live_peers, 958 struct ieee802_1x_kay_peer, list) { 959 body_peer = wpabuf_put(buf, 960 sizeof(struct ieee802_1x_mka_peer_id)); 961 os_memcpy(body_peer->mi, peer->mi, MI_LEN); 962 body_peer->mn = host_to_be32(peer->mn); 963 } 964 965 ieee802_1x_mka_dump_peer_body(body); 966 return 0; 967 } 968 969 /** 970 * ieee802_1x_mka_potential_peer_body_present 971 */ 972 static Boolean 973 ieee802_1x_mka_potential_peer_body_present( 974 struct ieee802_1x_mka_participant *participant) 975 { 976 return !dl_list_empty(&participant->potential_peers); 977 } 978 979 980 /** 981 * ieee802_1x_kay_get_potential_peer_length 982 */ 983 static int 984 ieee802_1x_mka_get_potential_peer_length( 985 struct ieee802_1x_mka_participant *participant) 986 { 987 int len = MKA_HDR_LEN; 988 struct ieee802_1x_kay_peer *peer; 989 990 dl_list_for_each(peer, &participant->potential_peers, 991 struct ieee802_1x_kay_peer, list) 992 len += sizeof(struct ieee802_1x_mka_peer_id); 993 994 return MKA_ALIGN_LENGTH(len); 995 } 996 997 998 /** 999 * ieee802_1x_mka_encode_potential_peer_body - 1000 */ 1001 static int 1002 ieee802_1x_mka_encode_potential_peer_body( 1003 struct ieee802_1x_mka_participant *participant, 1004 struct wpabuf *buf) 1005 { 1006 struct ieee802_1x_mka_peer_body *body; 1007 struct ieee802_1x_kay_peer *peer; 1008 unsigned int length; 1009 struct ieee802_1x_mka_peer_id *body_peer; 1010 1011 length = ieee802_1x_mka_get_potential_peer_length(participant); 1012 body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_peer_body)); 1013 1014 body->type = MKA_POTENTIAL_PEER_LIST; 1015 set_mka_param_body_len(body, length - MKA_HDR_LEN); 1016 1017 dl_list_for_each(peer, &participant->potential_peers, 1018 struct ieee802_1x_kay_peer, list) { 1019 body_peer = wpabuf_put(buf, 1020 sizeof(struct ieee802_1x_mka_peer_id)); 1021 os_memcpy(body_peer->mi, peer->mi, MI_LEN); 1022 body_peer->mn = host_to_be32(peer->mn); 1023 } 1024 1025 ieee802_1x_mka_dump_peer_body(body); 1026 return 0; 1027 } 1028 1029 1030 /** 1031 * ieee802_1x_mka_i_in_peerlist - 1032 */ 1033 static Boolean 1034 ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant, 1035 const u8 *mka_msg, size_t msg_len) 1036 { 1037 struct ieee802_1x_mka_hdr *hdr; 1038 size_t body_len; 1039 size_t left_len; 1040 u8 body_type; 1041 const u8 *pos; 1042 size_t i; 1043 1044 for (pos = mka_msg, left_len = msg_len; 1045 left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN; 1046 left_len -= MKA_ALIGN_LENGTH(body_len) + MKA_HDR_LEN, 1047 pos += MKA_ALIGN_LENGTH(body_len) + MKA_HDR_LEN) { 1048 hdr = (struct ieee802_1x_mka_hdr *) pos; 1049 body_len = get_mka_param_body_len(hdr); 1050 body_type = get_mka_param_body_type(hdr); 1051 1052 if (left_len < (MKA_HDR_LEN + MKA_ALIGN_LENGTH(body_len) + DEFAULT_ICV_LEN)) { 1053 wpa_printf(MSG_ERROR, 1054 "KaY: MKA Peer Packet Body Length (%zu bytes) is less than the Parameter Set Header Length (%zu bytes) + the Parameter Set Body Length (%zu bytes) + %d bytes of ICV", 1055 left_len, MKA_HDR_LEN, 1056 MKA_ALIGN_LENGTH(body_len), 1057 DEFAULT_ICV_LEN); 1058 return FALSE; 1059 } 1060 1061 if (body_type != MKA_LIVE_PEER_LIST && 1062 body_type != MKA_POTENTIAL_PEER_LIST) 1063 continue; 1064 1065 if ((body_len % 16) != 0) { 1066 wpa_printf(MSG_ERROR, 1067 "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets", 1068 body_len); 1069 continue; 1070 } 1071 1072 ieee802_1x_mka_dump_peer_body( 1073 (struct ieee802_1x_mka_peer_body *)pos); 1074 1075 for (i = 0; i < body_len; 1076 i += sizeof(struct ieee802_1x_mka_peer_id)) { 1077 const struct ieee802_1x_mka_peer_id *peer_mi; 1078 1079 peer_mi = (const struct ieee802_1x_mka_peer_id *) 1080 (pos + MKA_HDR_LEN + i); 1081 if (os_memcmp(peer_mi->mi, participant->mi, 1082 MI_LEN) == 0) { 1083 u32 mn = be_to_host32(peer_mi->mn); 1084 1085 wpa_printf(MSG_DEBUG, 1086 "KaY: My MI - received MN %u, most recently transmitted MN %u", 1087 mn, participant->mn); 1088 if (mn == participant->mn) 1089 return TRUE; 1090 } 1091 } 1092 } 1093 1094 return FALSE; 1095 } 1096 1097 1098 /** 1099 * ieee802_1x_mka_decode_live_peer_body - 1100 */ 1101 static int ieee802_1x_mka_decode_live_peer_body( 1102 struct ieee802_1x_mka_participant *participant, 1103 const u8 *peer_msg, size_t msg_len) 1104 { 1105 const struct ieee802_1x_mka_hdr *hdr; 1106 struct ieee802_1x_kay_peer *peer; 1107 size_t body_len; 1108 size_t i; 1109 Boolean is_included; 1110 1111 is_included = ieee802_1x_kay_is_in_live_peer( 1112 participant, participant->current_peer_id.mi); 1113 1114 hdr = (const struct ieee802_1x_mka_hdr *) peer_msg; 1115 body_len = get_mka_param_body_len(hdr); 1116 if (body_len % 16 != 0) { 1117 wpa_printf(MSG_ERROR, 1118 "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets", 1119 body_len); 1120 return -1; 1121 } 1122 1123 for (i = 0; i < body_len; i += sizeof(struct ieee802_1x_mka_peer_id)) { 1124 const struct ieee802_1x_mka_peer_id *peer_mi; 1125 u32 peer_mn; 1126 1127 peer_mi = (const struct ieee802_1x_mka_peer_id *) 1128 (peer_msg + MKA_HDR_LEN + i); 1129 peer_mn = be_to_host32(peer_mi->mn); 1130 1131 /* it is myself */ 1132 if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) { 1133 /* My message id is used by other participant */ 1134 if (peer_mn > participant->mn && 1135 !reset_participant_mi(participant)) 1136 wpa_printf(MSG_DEBUG, "KaY: Could not update mi"); 1137 continue; 1138 } 1139 1140 if (!is_included) 1141 continue; 1142 1143 peer = ieee802_1x_kay_get_peer(participant, peer_mi->mi); 1144 if (peer) { 1145 peer->mn = peer_mn; 1146 } else if (!ieee802_1x_kay_create_potential_peer( 1147 participant, peer_mi->mi, peer_mn)) { 1148 return -1; 1149 } 1150 } 1151 1152 return 0; 1153 } 1154 1155 1156 /** 1157 * ieee802_1x_mka_decode_potential_peer_body - 1158 */ 1159 static int 1160 ieee802_1x_mka_decode_potential_peer_body( 1161 struct ieee802_1x_mka_participant *participant, 1162 const u8 *peer_msg, size_t msg_len) 1163 { 1164 const struct ieee802_1x_mka_hdr *hdr; 1165 size_t body_len; 1166 size_t i; 1167 1168 hdr = (const struct ieee802_1x_mka_hdr *) peer_msg; 1169 body_len = get_mka_param_body_len(hdr); 1170 if (body_len % 16 != 0) { 1171 wpa_printf(MSG_ERROR, 1172 "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets", 1173 body_len); 1174 return -1; 1175 } 1176 1177 for (i = 0; i < body_len; i += sizeof(struct ieee802_1x_mka_peer_id)) { 1178 const struct ieee802_1x_mka_peer_id *peer_mi; 1179 u32 peer_mn; 1180 1181 peer_mi = (struct ieee802_1x_mka_peer_id *) 1182 (peer_msg + MKA_HDR_LEN + i); 1183 peer_mn = be_to_host32(peer_mi->mn); 1184 1185 /* it is myself */ 1186 if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) { 1187 /* My message id is used by other participant */ 1188 if (peer_mn > participant->mn && 1189 !reset_participant_mi(participant)) 1190 wpa_printf(MSG_DEBUG, "KaY: Could not update mi"); 1191 continue; 1192 } 1193 } 1194 1195 return 0; 1196 } 1197 1198 1199 /** 1200 * ieee802_1x_mka_sak_use_body_present 1201 */ 1202 static Boolean 1203 ieee802_1x_mka_sak_use_body_present( 1204 struct ieee802_1x_mka_participant *participant) 1205 { 1206 return participant->to_use_sak; 1207 } 1208 1209 1210 /** 1211 * ieee802_1x_mka_get_sak_use_length 1212 */ 1213 static int 1214 ieee802_1x_mka_get_sak_use_length( 1215 struct ieee802_1x_mka_participant *participant) 1216 { 1217 int length = MKA_HDR_LEN; 1218 1219 if (participant->kay->macsec_desired && participant->advised_desired) 1220 length = sizeof(struct ieee802_1x_mka_sak_use_body); 1221 1222 return MKA_ALIGN_LENGTH(length); 1223 } 1224 1225 1226 /** 1227 * ieee802_1x_mka_get_lpn 1228 */ 1229 static u32 1230 ieee802_1x_mka_get_lpn(struct ieee802_1x_mka_participant *principal, 1231 struct ieee802_1x_mka_ki *ki) 1232 { 1233 struct transmit_sa *txsa; 1234 u32 lpn = 0; 1235 1236 dl_list_for_each(txsa, &principal->txsc->sa_list, 1237 struct transmit_sa, list) { 1238 if (is_ki_equal(&txsa->pkey->key_identifier, ki)) { 1239 /* Per IEEE Std 802.1X-2010, Clause 9, "Each SecY uses 1240 * MKA to communicate the lowest PN used for 1241 * transmission with the SAK within the last two 1242 * seconds". Achieve this 2 second delay by setting the 1243 * lpn using the transmit next PN (i.e., txsa->next_pn) 1244 * that was read last time here (i.e., mka_hello_time 1245 * 2 seconds ago). 1246 * 1247 * The lowest acceptable PN is the same as the last 1248 * transmitted PN, which is one less than the next 1249 * transmit PN. 1250 * 1251 * NOTE: This method only works if mka_hello_time is 2s. 1252 */ 1253 lpn = (txsa->next_pn > 0) ? (txsa->next_pn - 1) : 0; 1254 1255 /* Now read the current transmit next PN for use next 1256 * time through. */ 1257 secy_get_transmit_next_pn(principal->kay, txsa); 1258 break; 1259 } 1260 } 1261 1262 if (lpn == 0) 1263 lpn = 1; 1264 1265 return lpn; 1266 } 1267 1268 1269 /** 1270 * ieee802_1x_mka_encode_sak_use_body - 1271 */ 1272 static int 1273 ieee802_1x_mka_encode_sak_use_body( 1274 struct ieee802_1x_mka_participant *participant, 1275 struct wpabuf *buf) 1276 { 1277 struct ieee802_1x_mka_sak_use_body *body; 1278 struct ieee802_1x_kay *kay = participant->kay; 1279 unsigned int length; 1280 u32 pn = 1; 1281 1282 length = ieee802_1x_mka_get_sak_use_length(participant); 1283 body = wpabuf_put(buf, length); 1284 1285 body->type = MKA_SAK_USE; 1286 set_mka_param_body_len(body, length - MKA_HDR_LEN); 1287 1288 if (length == MKA_HDR_LEN) { 1289 body->ptx = TRUE; 1290 body->prx = TRUE; 1291 body->lan = 0; 1292 body->lrx = FALSE; 1293 body->ltx = FALSE; 1294 body->delay_protect = FALSE; 1295 return 0; 1296 } 1297 1298 /* data delay protect */ 1299 body->delay_protect = kay->mka_hello_time <= MKA_BOUNDED_HELLO_TIME; 1300 /* lowest accept packet number */ 1301 pn = ieee802_1x_mka_get_lpn(participant, &participant->lki); 1302 if (pn > kay->pn_exhaustion) { 1303 wpa_printf(MSG_WARNING, "KaY: My LPN exhaustion"); 1304 if (participant->is_key_server) 1305 participant->new_sak = TRUE; 1306 } 1307 1308 body->llpn = host_to_be32(pn); 1309 pn = ieee802_1x_mka_get_lpn(participant, &participant->oki); 1310 body->olpn = host_to_be32(pn); 1311 1312 /* plain tx, plain rx */ 1313 body->ptx = !kay->macsec_protect; 1314 body->prx = kay->macsec_validate != Strict; 1315 1316 /* latest key: rx, tx, key server member identifier key number */ 1317 body->lan = participant->lan; 1318 os_memcpy(body->lsrv_mi, participant->lki.mi, sizeof(body->lsrv_mi)); 1319 body->lkn = host_to_be32(participant->lki.kn); 1320 body->lrx = participant->lrx; 1321 body->ltx = participant->ltx; 1322 1323 /* old key: rx, tx, key server member identifier key number */ 1324 body->oan = participant->oan; 1325 if (participant->oki.kn != participant->lki.kn && 1326 participant->oki.kn != 0) { 1327 body->otx = TRUE; 1328 body->orx = TRUE; 1329 os_memcpy(body->osrv_mi, participant->oki.mi, 1330 sizeof(body->osrv_mi)); 1331 body->okn = host_to_be32(participant->oki.kn); 1332 } else { 1333 body->otx = FALSE; 1334 body->orx = FALSE; 1335 } 1336 1337 /* set CP's variable */ 1338 if (body->ltx) { 1339 kay->tx_enable = TRUE; 1340 kay->port_enable = TRUE; 1341 } 1342 if (body->lrx) 1343 kay->rx_enable = TRUE; 1344 1345 ieee802_1x_mka_dump_sak_use_body(body); 1346 return 0; 1347 } 1348 1349 1350 /** 1351 * ieee802_1x_mka_decode_sak_use_body - 1352 */ 1353 static int 1354 ieee802_1x_mka_decode_sak_use_body( 1355 struct ieee802_1x_mka_participant *participant, 1356 const u8 *mka_msg, size_t msg_len) 1357 { 1358 struct ieee802_1x_mka_hdr *hdr; 1359 struct ieee802_1x_mka_sak_use_body *body; 1360 struct ieee802_1x_kay_peer *peer; 1361 struct receive_sc *rxsc; 1362 struct receive_sa *rxsa; 1363 struct data_key *sa_key = NULL; 1364 size_t body_len; 1365 struct ieee802_1x_mka_ki ki; 1366 u32 lpn; 1367 Boolean all_receiving; 1368 Boolean found; 1369 struct ieee802_1x_kay *kay = participant->kay; 1370 1371 if (!participant->principal) { 1372 wpa_printf(MSG_WARNING, "KaY: Participant is not principal"); 1373 return -1; 1374 } 1375 peer = ieee802_1x_kay_get_live_peer(participant, 1376 participant->current_peer_id.mi); 1377 if (!peer) { 1378 wpa_printf(MSG_WARNING, 1379 "KaY: The peer (%s) is not my live peer - ignore MACsec SAK Use parameter set", 1380 mi_txt(participant->current_peer_id.mi)); 1381 return -1; 1382 } 1383 1384 hdr = (struct ieee802_1x_mka_hdr *) mka_msg; 1385 body_len = get_mka_param_body_len(hdr); 1386 body = (struct ieee802_1x_mka_sak_use_body *) mka_msg; 1387 ieee802_1x_mka_dump_sak_use_body(body); 1388 1389 if ((body_len != 0) && (body_len < 40)) { 1390 wpa_printf(MSG_ERROR, 1391 "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 40, or more octets", 1392 body_len); 1393 return -1; 1394 } 1395 1396 /* TODO: what action should I take when peer does not support MACsec */ 1397 if (body_len == 0) { 1398 wpa_printf(MSG_WARNING, "KaY: Peer does not support MACsec"); 1399 return 0; 1400 } 1401 1402 /* TODO: when the plain tx or rx of peer is true, should I change 1403 * the attribute of controlled port 1404 */ 1405 if (body->prx) 1406 wpa_printf(MSG_WARNING, "KaY: peer's plain rx are TRUE"); 1407 1408 if (body->ptx) 1409 wpa_printf(MSG_WARNING, "KaY: peer's plain tx are TRUE"); 1410 1411 /* check latest key is valid */ 1412 if (body->ltx || body->lrx) { 1413 found = FALSE; 1414 os_memcpy(ki.mi, body->lsrv_mi, sizeof(ki.mi)); 1415 ki.kn = be_to_host32(body->lkn); 1416 dl_list_for_each(sa_key, &participant->sak_list, 1417 struct data_key, list) { 1418 if (is_ki_equal(&sa_key->key_identifier, &ki)) { 1419 found = TRUE; 1420 break; 1421 } 1422 } 1423 if (!found) { 1424 wpa_printf(MSG_INFO, "KaY: Latest key is invalid"); 1425 return -1; 1426 } 1427 if (os_memcmp(participant->lki.mi, body->lsrv_mi, 1428 sizeof(participant->lki.mi)) == 0 && 1429 be_to_host32(body->lkn) == participant->lki.kn && 1430 body->lan == participant->lan) { 1431 peer->sak_used = TRUE; 1432 } 1433 if (body->ltx && peer->is_key_server) { 1434 ieee802_1x_cp_set_servertransmitting(kay->cp, TRUE); 1435 ieee802_1x_cp_sm_step(kay->cp); 1436 } 1437 } 1438 1439 /* check old key is valid (but only if we remember our old key) */ 1440 if (participant->oki.kn != 0 && (body->otx || body->orx)) { 1441 if (os_memcmp(participant->oki.mi, body->osrv_mi, 1442 sizeof(participant->oki.mi)) != 0 || 1443 be_to_host32(body->okn) != participant->oki.kn || 1444 body->oan != participant->oan) { 1445 wpa_printf(MSG_WARNING, "KaY: Old key is invalid"); 1446 return -1; 1447 } 1448 } 1449 1450 /* TODO: how to set the MACsec hardware when delay_protect is true */ 1451 if (body->delay_protect && 1452 (!be_to_host32(body->llpn) || !be_to_host32(body->olpn))) { 1453 wpa_printf(MSG_WARNING, 1454 "KaY: Lowest packet number should be greater than 0 when delay_protect is TRUE"); 1455 return -1; 1456 } 1457 1458 /* check all live peer have used the sak for receiving sa */ 1459 all_receiving = TRUE; 1460 dl_list_for_each(peer, &participant->live_peers, 1461 struct ieee802_1x_kay_peer, list) { 1462 if (!peer->sak_used) { 1463 all_receiving = FALSE; 1464 break; 1465 } 1466 } 1467 if (all_receiving) { 1468 participant->to_dist_sak = FALSE; 1469 ieee802_1x_cp_set_allreceiving(kay->cp, TRUE); 1470 ieee802_1x_cp_sm_step(kay->cp); 1471 } 1472 1473 /* if I'm key server, and detects peer member pn exhaustion, rekey. */ 1474 lpn = be_to_host32(body->llpn); 1475 if (lpn > kay->pn_exhaustion) { 1476 if (participant->is_key_server) { 1477 participant->new_sak = TRUE; 1478 wpa_printf(MSG_WARNING, "KaY: Peer LPN exhaustion"); 1479 } 1480 } 1481 1482 if (sa_key) 1483 sa_key->next_pn = lpn; 1484 found = FALSE; 1485 dl_list_for_each(rxsc, &participant->rxsc_list, struct receive_sc, 1486 list) { 1487 dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, 1488 list) { 1489 if (sa_key && rxsa->pkey == sa_key) { 1490 found = TRUE; 1491 break; 1492 } 1493 } 1494 if (found) 1495 break; 1496 } 1497 if (!found) { 1498 wpa_printf(MSG_WARNING, "KaY: Can't find rxsa"); 1499 return -1; 1500 } 1501 1502 if (body->delay_protect) { 1503 secy_get_receive_lowest_pn(participant->kay, rxsa); 1504 if (lpn > rxsa->lowest_pn) { 1505 /* Delay protect window (communicated via MKA) is 1506 * tighter than SecY's current replay protect window, 1507 * so tell SecY the new (and higher) lpn. */ 1508 rxsa->lowest_pn = lpn; 1509 secy_set_receive_lowest_pn(participant->kay, rxsa); 1510 wpa_printf(MSG_DEBUG, "KaY: update lpn =0x%x", lpn); 1511 } 1512 /* FIX: Delay protection for olpn not implemented. 1513 * Note that Old Key is only active for MKA_SAK_RETIRE_TIME 1514 * (3 seconds) and delay protection does allow PN's within 1515 * a 2 seconds window, so olpn would be a lot of work for 1516 * just 1 second's worth of protection. */ 1517 } 1518 1519 return 0; 1520 } 1521 1522 1523 /** 1524 * ieee802_1x_mka_dist_sak_body_present 1525 */ 1526 static Boolean 1527 ieee802_1x_mka_dist_sak_body_present( 1528 struct ieee802_1x_mka_participant *participant) 1529 { 1530 return participant->is_key_server && participant->to_dist_sak && 1531 participant->new_key; 1532 } 1533 1534 1535 /** 1536 * ieee802_1x_kay_get_dist_sak_length 1537 */ 1538 static int 1539 ieee802_1x_mka_get_dist_sak_length( 1540 struct ieee802_1x_mka_participant *participant) 1541 { 1542 int length = MKA_HDR_LEN; 1543 unsigned int cs_index = participant->kay->macsec_csindex; 1544 1545 if (participant->advised_desired && cs_index < CS_TABLE_SIZE) { 1546 length = sizeof(struct ieee802_1x_mka_dist_sak_body); 1547 if (cs_index != DEFAULT_CS_INDEX) 1548 length += CS_ID_LEN; 1549 1550 length += cipher_suite_tbl[cs_index].sak_len + 8; 1551 } 1552 1553 return MKA_ALIGN_LENGTH(length); 1554 } 1555 1556 1557 /** 1558 * ieee802_1x_mka_encode_dist_sak_body - 1559 */ 1560 static int 1561 ieee802_1x_mka_encode_dist_sak_body( 1562 struct ieee802_1x_mka_participant *participant, 1563 struct wpabuf *buf) 1564 { 1565 struct ieee802_1x_mka_dist_sak_body *body; 1566 struct data_key *sak; 1567 unsigned int length; 1568 unsigned int cs_index; 1569 int sak_pos; 1570 1571 length = ieee802_1x_mka_get_dist_sak_length(participant); 1572 body = wpabuf_put(buf, length); 1573 body->type = MKA_DISTRIBUTED_SAK; 1574 set_mka_param_body_len(body, length - MKA_HDR_LEN); 1575 if (length == MKA_HDR_LEN) { 1576 body->confid_offset = 0; 1577 body->dan = 0; 1578 return 0; 1579 } 1580 1581 sak = participant->new_key; 1582 if (!sak) { 1583 wpa_printf(MSG_DEBUG, 1584 "KaY: No SAK available to build Distributed SAK parameter set"); 1585 return -1; 1586 } 1587 body->confid_offset = sak->confidentiality_offset; 1588 body->dan = sak->an; 1589 body->kn = host_to_be32(sak->key_identifier.kn); 1590 cs_index = participant->kay->macsec_csindex; 1591 sak_pos = 0; 1592 if (cs_index >= CS_TABLE_SIZE) 1593 return -1; 1594 if (cs_index != DEFAULT_CS_INDEX) { 1595 be64 cs; 1596 1597 cs = host_to_be64(cipher_suite_tbl[cs_index].id); 1598 os_memcpy(body->sak, &cs, CS_ID_LEN); 1599 sak_pos = CS_ID_LEN; 1600 } 1601 if (aes_wrap(participant->kek.key, participant->kek.len, 1602 cipher_suite_tbl[cs_index].sak_len / 8, 1603 sak->key, body->sak + sak_pos)) { 1604 wpa_printf(MSG_ERROR, "KaY: AES wrap failed"); 1605 return -1; 1606 } 1607 1608 ieee802_1x_mka_dump_dist_sak_body(body); 1609 1610 return 0; 1611 } 1612 1613 1614 /** 1615 * ieee802_1x_kay_init_data_key - 1616 */ 1617 static void ieee802_1x_kay_init_data_key(struct data_key *pkey) 1618 { 1619 pkey->transmits = TRUE; 1620 pkey->receives = TRUE; 1621 os_get_time(&pkey->created_time); 1622 1623 pkey->next_pn = 1; 1624 pkey->user = 1; 1625 } 1626 1627 1628 /** 1629 * ieee802_1x_kay_decode_dist_sak_body - 1630 */ 1631 static int 1632 ieee802_1x_mka_decode_dist_sak_body( 1633 struct ieee802_1x_mka_participant *participant, 1634 const u8 *mka_msg, size_t msg_len) 1635 { 1636 struct ieee802_1x_mka_hdr *hdr; 1637 struct ieee802_1x_mka_dist_sak_body *body; 1638 struct ieee802_1x_kay_peer *peer; 1639 struct macsec_ciphersuite *cs; 1640 size_t body_len; 1641 struct data_key *sa_key = NULL; 1642 int sak_len; 1643 u8 *wrap_sak; 1644 u8 *unwrap_sak; 1645 struct ieee802_1x_kay *kay = participant->kay; 1646 1647 hdr = (struct ieee802_1x_mka_hdr *) mka_msg; 1648 body_len = get_mka_param_body_len(hdr); 1649 if ((body_len != 0) && (body_len != 28) && (body_len < 36)) { 1650 wpa_printf(MSG_ERROR, 1651 "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 28, 36, or more octets", 1652 body_len); 1653 return -1; 1654 } 1655 1656 if (!participant->principal) { 1657 wpa_printf(MSG_ERROR, 1658 "KaY: I can't accept the distributed SAK as I am not principal"); 1659 return -1; 1660 } 1661 if (participant->is_key_server) { 1662 wpa_printf(MSG_ERROR, 1663 "KaY: Reject distributed SAK since I'm a key server"); 1664 return -1; 1665 } 1666 if (!kay->macsec_desired || 1667 kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) { 1668 wpa_printf(MSG_ERROR, 1669 "KaY: I am not MACsec-desired or without MACsec capable"); 1670 return -1; 1671 } 1672 1673 peer = ieee802_1x_kay_get_live_peer(participant, 1674 participant->current_peer_id.mi); 1675 if (!peer) { 1676 wpa_printf(MSG_ERROR, 1677 "KaY: The key server is not in my live peers list"); 1678 return -1; 1679 } 1680 if (!sci_equal(&kay->key_server_sci, &peer->sci)) { 1681 wpa_printf(MSG_ERROR, "KaY: The key server is not elected"); 1682 return -1; 1683 } 1684 1685 if (body_len == 0) { 1686 kay->authenticated = TRUE; 1687 kay->secured = FALSE; 1688 kay->failed = FALSE; 1689 participant->advised_desired = FALSE; 1690 ieee802_1x_cp_connect_authenticated(kay->cp); 1691 ieee802_1x_cp_sm_step(kay->cp); 1692 wpa_printf(MSG_WARNING, "KaY: The Key server advise no MACsec"); 1693 participant->to_use_sak = FALSE; 1694 return 0; 1695 } 1696 1697 participant->advised_desired = TRUE; 1698 kay->authenticated = FALSE; 1699 kay->secured = TRUE; 1700 kay->failed = FALSE; 1701 ieee802_1x_cp_connect_secure(kay->cp); 1702 ieee802_1x_cp_sm_step(kay->cp); 1703 1704 body = (struct ieee802_1x_mka_dist_sak_body *)mka_msg; 1705 ieee802_1x_mka_dump_dist_sak_body(body); 1706 dl_list_for_each(sa_key, &participant->sak_list, struct data_key, list) 1707 { 1708 if (os_memcmp(sa_key->key_identifier.mi, 1709 participant->current_peer_id.mi, MI_LEN) == 0 && 1710 sa_key->key_identifier.kn == be_to_host32(body->kn)) { 1711 wpa_printf(MSG_DEBUG, 1712 "KaY: SAK has already been installed - do not set it again"); 1713 return 0; 1714 } 1715 } 1716 1717 if (body_len == 28) { 1718 sak_len = DEFAULT_SA_KEY_LEN; 1719 wrap_sak = body->sak; 1720 kay->macsec_csindex = DEFAULT_CS_INDEX; 1721 cs = &cipher_suite_tbl[kay->macsec_csindex]; 1722 } else { 1723 unsigned int idx; 1724 1725 cs = ieee802_1x_kay_get_cipher_suite(participant, body->sak, 1726 &idx); 1727 if (!cs) { 1728 wpa_printf(MSG_ERROR, 1729 "KaY: I can't support the Cipher Suite advised by key server"); 1730 return -1; 1731 } 1732 sak_len = cs->sak_len; 1733 wrap_sak = body->sak + CS_ID_LEN; 1734 kay->macsec_csindex = idx; 1735 } 1736 1737 unwrap_sak = os_zalloc(sak_len); 1738 if (!unwrap_sak) { 1739 wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__); 1740 return -1; 1741 } 1742 if (aes_unwrap(participant->kek.key, participant->kek.len, 1743 sak_len >> 3, wrap_sak, unwrap_sak)) { 1744 wpa_printf(MSG_ERROR, "KaY: AES unwrap failed"); 1745 os_free(unwrap_sak); 1746 return -1; 1747 } 1748 wpa_hexdump_key(MSG_DEBUG, "\tAES Key Unwrap of SAK.:", 1749 unwrap_sak, sak_len); 1750 1751 sa_key = os_zalloc(sizeof(*sa_key)); 1752 if (!sa_key) { 1753 os_free(unwrap_sak); 1754 return -1; 1755 } 1756 1757 os_memcpy(&sa_key->key_identifier.mi, &participant->current_peer_id.mi, 1758 MI_LEN); 1759 sa_key->key_identifier.kn = be_to_host32(body->kn); 1760 1761 sa_key->key = unwrap_sak; 1762 sa_key->key_len = sak_len; 1763 1764 sa_key->confidentiality_offset = body->confid_offset; 1765 sa_key->an = body->dan; 1766 ieee802_1x_kay_init_data_key(sa_key); 1767 1768 ieee802_1x_kay_use_data_key(sa_key); 1769 dl_list_add(&participant->sak_list, &sa_key->list); 1770 1771 ieee802_1x_cp_set_ciphersuite(kay->cp, cs->id); 1772 ieee802_1x_cp_sm_step(kay->cp); 1773 ieee802_1x_cp_set_offset(kay->cp, body->confid_offset); 1774 ieee802_1x_cp_sm_step(kay->cp); 1775 ieee802_1x_cp_set_distributedki(kay->cp, &sa_key->key_identifier); 1776 ieee802_1x_cp_set_distributedan(kay->cp, body->dan); 1777 ieee802_1x_cp_signal_newsak(kay->cp); 1778 ieee802_1x_cp_sm_step(kay->cp); 1779 1780 kay->rcvd_keys++; 1781 participant->to_use_sak = TRUE; 1782 1783 return 0; 1784 } 1785 1786 1787 /** 1788 * ieee802_1x_mka_icv_body_present 1789 */ 1790 static Boolean 1791 ieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant *participant) 1792 { 1793 return TRUE; 1794 } 1795 1796 1797 /** 1798 * ieee802_1x_kay_get_icv_length 1799 */ 1800 static int 1801 ieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant *participant) 1802 { 1803 int length; 1804 1805 /* Determine if we need space for the ICV Indicator */ 1806 if (mka_alg_tbl[participant->kay->mka_algindex].icv_len != 1807 DEFAULT_ICV_LEN) 1808 length = sizeof(struct ieee802_1x_mka_icv_body); 1809 else 1810 length = 0; 1811 length += mka_alg_tbl[participant->kay->mka_algindex].icv_len; 1812 1813 return MKA_ALIGN_LENGTH(length); 1814 } 1815 1816 1817 /** 1818 * ieee802_1x_mka_encode_icv_body - 1819 */ 1820 static int 1821 ieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant *participant, 1822 struct wpabuf *buf) 1823 { 1824 struct ieee802_1x_mka_icv_body *body; 1825 unsigned int length; 1826 u8 cmac[MAX_ICV_LEN]; 1827 1828 length = ieee802_1x_mka_get_icv_length(participant); 1829 if (mka_alg_tbl[participant->kay->mka_algindex].icv_len != 1830 DEFAULT_ICV_LEN) { 1831 wpa_printf(MSG_DEBUG, "KaY: ICV Indicator"); 1832 body = wpabuf_put(buf, MKA_HDR_LEN); 1833 body->type = MKA_ICV_INDICATOR; 1834 length -= MKA_HDR_LEN; 1835 set_mka_param_body_len(body, length); 1836 } 1837 1838 if (mka_alg_tbl[participant->kay->mka_algindex].icv_hash( 1839 participant->ick.key, participant->ick.len, 1840 wpabuf_head(buf), wpabuf_len(buf), cmac)) { 1841 wpa_printf(MSG_ERROR, "KaY: failed to calculate ICV"); 1842 return -1; 1843 } 1844 wpa_hexdump(MSG_DEBUG, "KaY: ICV", cmac, length); 1845 1846 os_memcpy(wpabuf_put(buf, length), cmac, length); 1847 1848 return 0; 1849 } 1850 1851 /** 1852 * ieee802_1x_mka_decode_icv_body - 1853 */ 1854 static const u8 * 1855 ieee802_1x_mka_decode_icv_body(struct ieee802_1x_mka_participant *participant, 1856 const u8 *mka_msg, size_t msg_len) 1857 { 1858 const struct ieee802_1x_mka_hdr *hdr; 1859 const struct ieee802_1x_mka_icv_body *body; 1860 size_t body_len; 1861 size_t left_len; 1862 u8 body_type; 1863 const u8 *pos; 1864 1865 pos = mka_msg; 1866 left_len = msg_len; 1867 while (left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN) { 1868 hdr = (const struct ieee802_1x_mka_hdr *) pos; 1869 body_len = MKA_ALIGN_LENGTH(get_mka_param_body_len(hdr)); 1870 body_type = get_mka_param_body_type(hdr); 1871 1872 if (left_len < body_len + MKA_HDR_LEN) 1873 break; 1874 1875 if (body_type != MKA_ICV_INDICATOR) { 1876 left_len -= MKA_HDR_LEN + body_len; 1877 pos += MKA_HDR_LEN + body_len; 1878 continue; 1879 } 1880 1881 body = (const struct ieee802_1x_mka_icv_body *) pos; 1882 if (body_len 1883 < mka_alg_tbl[participant->kay->mka_algindex].icv_len) 1884 return NULL; 1885 1886 return body->icv; 1887 } 1888 1889 return mka_msg + msg_len - DEFAULT_ICV_LEN; 1890 } 1891 1892 1893 /** 1894 * ieee802_1x_mka_decode_dist_cak_body- 1895 */ 1896 static int 1897 ieee802_1x_mka_decode_dist_cak_body( 1898 struct ieee802_1x_mka_participant *participant, 1899 const u8 *mka_msg, size_t msg_len) 1900 { 1901 struct ieee802_1x_mka_hdr *hdr; 1902 size_t body_len; 1903 1904 hdr = (struct ieee802_1x_mka_hdr *) mka_msg; 1905 body_len = get_mka_param_body_len(hdr); 1906 if (body_len < 28) { 1907 wpa_printf(MSG_ERROR, 1908 "KaY: MKA Use CAK Packet Body Length (%zu bytes) should be 28 or more octets", 1909 body_len); 1910 return -1; 1911 } 1912 1913 return 0; 1914 } 1915 1916 1917 /** 1918 * ieee802_1x_mka_decode_kmd_body - 1919 */ 1920 static int 1921 ieee802_1x_mka_decode_kmd_body( 1922 struct ieee802_1x_mka_participant *participant, 1923 const u8 *mka_msg, size_t msg_len) 1924 { 1925 struct ieee802_1x_mka_hdr *hdr; 1926 size_t body_len; 1927 1928 hdr = (struct ieee802_1x_mka_hdr *) mka_msg; 1929 body_len = get_mka_param_body_len(hdr); 1930 if (body_len < 5) { 1931 wpa_printf(MSG_ERROR, 1932 "KaY: MKA Use KMD Packet Body Length (%zu bytes) should be 5 or more octets", 1933 body_len); 1934 return -1; 1935 } 1936 1937 return 0; 1938 } 1939 1940 1941 /** 1942 * ieee802_1x_mka_decode_announce_body - 1943 */ 1944 static int ieee802_1x_mka_decode_announce_body( 1945 struct ieee802_1x_mka_participant *participant, 1946 const u8 *mka_msg, size_t msg_len) 1947 { 1948 return 0; 1949 } 1950 1951 1952 struct mka_param_body_handler { 1953 int (*body_tx)(struct ieee802_1x_mka_participant *participant, 1954 struct wpabuf *buf); 1955 int (*body_rx)(struct ieee802_1x_mka_participant *participant, 1956 const u8 *mka_msg, size_t msg_len); 1957 int (*body_length)(struct ieee802_1x_mka_participant *participant); 1958 Boolean (*body_present)(struct ieee802_1x_mka_participant *participant); 1959 }; 1960 1961 1962 static struct mka_param_body_handler mka_body_handler[] = { 1963 /* Basic parameter set */ 1964 { 1965 .body_tx = ieee802_1x_mka_encode_basic_body, 1966 .body_rx = NULL, 1967 .body_length = ieee802_1x_mka_basic_body_length, 1968 .body_present = ieee802_1x_mka_basic_body_present 1969 }, 1970 1971 /* Live Peer List parameter set */ 1972 { 1973 .body_tx = ieee802_1x_mka_encode_live_peer_body, 1974 .body_rx = ieee802_1x_mka_decode_live_peer_body, 1975 .body_length = ieee802_1x_mka_get_live_peer_length, 1976 .body_present = ieee802_1x_mka_live_peer_body_present 1977 }, 1978 1979 /* Potential Peer List parameter set */ 1980 { 1981 .body_tx = ieee802_1x_mka_encode_potential_peer_body, 1982 .body_rx = ieee802_1x_mka_decode_potential_peer_body, 1983 .body_length = ieee802_1x_mka_get_potential_peer_length, 1984 .body_present = ieee802_1x_mka_potential_peer_body_present 1985 }, 1986 1987 /* MACsec SAK Use parameter set */ 1988 { 1989 .body_tx = ieee802_1x_mka_encode_sak_use_body, 1990 .body_rx = ieee802_1x_mka_decode_sak_use_body, 1991 .body_length = ieee802_1x_mka_get_sak_use_length, 1992 .body_present = ieee802_1x_mka_sak_use_body_present 1993 }, 1994 1995 /* Distributed SAK parameter set */ 1996 { 1997 .body_tx = ieee802_1x_mka_encode_dist_sak_body, 1998 .body_rx = ieee802_1x_mka_decode_dist_sak_body, 1999 .body_length = ieee802_1x_mka_get_dist_sak_length, 2000 .body_present = ieee802_1x_mka_dist_sak_body_present 2001 }, 2002 2003 /* Distribute CAK parameter set */ 2004 { 2005 .body_tx = NULL, 2006 .body_rx = ieee802_1x_mka_decode_dist_cak_body, 2007 .body_length = NULL, 2008 .body_present = NULL 2009 }, 2010 2011 /* KMD parameter set */ 2012 { 2013 .body_tx = NULL, 2014 .body_rx = ieee802_1x_mka_decode_kmd_body, 2015 .body_length = NULL, 2016 .body_present = NULL 2017 }, 2018 2019 /* Announcement parameter set */ 2020 { 2021 .body_tx = NULL, 2022 .body_rx = ieee802_1x_mka_decode_announce_body, 2023 .body_length = NULL, 2024 .body_present = NULL 2025 }, 2026 2027 /* ICV Indicator parameter set */ 2028 { 2029 .body_tx = ieee802_1x_mka_encode_icv_body, 2030 .body_rx = NULL, 2031 .body_length = ieee802_1x_mka_get_icv_length, 2032 .body_present = ieee802_1x_mka_icv_body_present 2033 }, 2034 }; 2035 2036 2037 /** 2038 * ieee802_1x_kay_use_data_key - Take reference on a key 2039 */ 2040 static void ieee802_1x_kay_use_data_key(struct data_key *pkey) 2041 { 2042 pkey->user++; 2043 } 2044 2045 2046 /** 2047 * ieee802_1x_kay_deinit_data_key - Release reference on a key and 2048 * free if there are no remaining users 2049 */ 2050 static void ieee802_1x_kay_deinit_data_key(struct data_key *pkey) 2051 { 2052 if (!pkey) 2053 return; 2054 2055 pkey->user--; 2056 if (pkey->user > 1) 2057 return; 2058 2059 os_free(pkey->key); 2060 os_free(pkey); 2061 } 2062 2063 2064 /** 2065 * ieee802_1x_kay_generate_new_sak - 2066 */ 2067 static int 2068 ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant) 2069 { 2070 struct data_key *sa_key = NULL; 2071 struct ieee802_1x_kay_peer *peer; 2072 struct ieee802_1x_kay *kay = participant->kay; 2073 int ctx_len, ctx_offset; 2074 u8 *context; 2075 unsigned int key_len; 2076 u8 *key; 2077 struct macsec_ciphersuite *cs; 2078 2079 /* check condition for generating a fresh SAK: 2080 * must have one live peer 2081 * and MKA life time elapse since last distribution 2082 * or potential peer is empty 2083 */ 2084 if (dl_list_empty(&participant->live_peers)) { 2085 wpa_printf(MSG_ERROR, 2086 "KaY: Live peers list must not be empty when generating fresh SAK"); 2087 return -1; 2088 } 2089 2090 /* FIXME: A fresh SAK not generated until 2091 * the live peer list contains at least one peer and 2092 * MKA life time has elapsed since the prior SAK was first distributed, 2093 * or the Key server's potential peer is empty 2094 * but I can't understand the second item, so 2095 * here only check first item and ingore 2096 * && (!dl_list_empty(&participant->potential_peers))) { 2097 */ 2098 if ((time(NULL) - kay->dist_time) < MKA_LIFE_TIME / 1000) { 2099 wpa_printf(MSG_ERROR, 2100 "KaY: Life time has not elapsed since prior SAK distributed"); 2101 return -1; 2102 } 2103 2104 cs = &cipher_suite_tbl[kay->macsec_csindex]; 2105 key_len = cs->sak_len; 2106 key = os_zalloc(key_len); 2107 if (!key) { 2108 wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__); 2109 return -1; 2110 } 2111 2112 ctx_len = key_len + sizeof(kay->dist_kn); 2113 dl_list_for_each(peer, &participant->live_peers, 2114 struct ieee802_1x_kay_peer, list) 2115 ctx_len += sizeof(peer->mi); 2116 ctx_len += sizeof(participant->mi); 2117 2118 context = os_zalloc(ctx_len); 2119 if (!context) 2120 goto fail; 2121 2122 ctx_offset = 0; 2123 if (os_get_random(context + ctx_offset, key_len) < 0) 2124 goto fail; 2125 2126 ctx_offset += key_len; 2127 dl_list_for_each(peer, &participant->live_peers, 2128 struct ieee802_1x_kay_peer, list) { 2129 os_memcpy(context + ctx_offset, peer->mi, sizeof(peer->mi)); 2130 ctx_offset += sizeof(peer->mi); 2131 } 2132 os_memcpy(context + ctx_offset, participant->mi, 2133 sizeof(participant->mi)); 2134 ctx_offset += sizeof(participant->mi); 2135 os_memcpy(context + ctx_offset, &kay->dist_kn, sizeof(kay->dist_kn)); 2136 2137 if (key_len == 16 || key_len == 32) { 2138 if (ieee802_1x_sak_aes_cmac(participant->cak.key, 2139 participant->cak.len, 2140 context, ctx_len, 2141 key, key_len)) { 2142 wpa_printf(MSG_ERROR, "KaY: Failed to generate SAK"); 2143 goto fail; 2144 } 2145 } else { 2146 wpa_printf(MSG_ERROR, "KaY: SAK Length(%u) not supported", 2147 key_len); 2148 goto fail; 2149 } 2150 wpa_hexdump_key(MSG_DEBUG, "KaY: generated new SAK", key, key_len); 2151 os_free(context); 2152 context = NULL; 2153 2154 sa_key = os_zalloc(sizeof(*sa_key)); 2155 if (!sa_key) { 2156 wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__); 2157 goto fail; 2158 } 2159 2160 sa_key->key = key; 2161 sa_key->key_len = key_len; 2162 os_memcpy(sa_key->key_identifier.mi, participant->mi, MI_LEN); 2163 sa_key->key_identifier.kn = kay->dist_kn; 2164 2165 sa_key->confidentiality_offset = kay->macsec_confidentiality; 2166 sa_key->an = kay->dist_an; 2167 ieee802_1x_kay_init_data_key(sa_key); 2168 2169 participant->new_key = sa_key; 2170 2171 ieee802_1x_kay_use_data_key(sa_key); 2172 dl_list_add(&participant->sak_list, &sa_key->list); 2173 2174 ieee802_1x_cp_set_ciphersuite(kay->cp, cs->id); 2175 ieee802_1x_cp_sm_step(kay->cp); 2176 ieee802_1x_cp_set_offset(kay->cp, kay->macsec_confidentiality); 2177 ieee802_1x_cp_sm_step(kay->cp); 2178 ieee802_1x_cp_set_distributedki(kay->cp, &sa_key->key_identifier); 2179 ieee802_1x_cp_set_distributedan(kay->cp, sa_key->an); 2180 ieee802_1x_cp_signal_newsak(kay->cp); 2181 ieee802_1x_cp_sm_step(kay->cp); 2182 2183 dl_list_for_each(peer, &participant->live_peers, 2184 struct ieee802_1x_kay_peer, list) 2185 peer->sak_used = FALSE; 2186 2187 kay->dist_kn++; 2188 kay->dist_an++; 2189 if (kay->dist_an > 3) 2190 kay->dist_an = 0; 2191 2192 kay->dist_time = time(NULL); 2193 2194 return 0; 2195 2196 fail: 2197 os_free(key); 2198 os_free(context); 2199 return -1; 2200 } 2201 2202 2203 static int compare_priorities(const struct ieee802_1x_kay_peer *peer, 2204 const struct ieee802_1x_kay_peer *other) 2205 { 2206 if (peer->key_server_priority < other->key_server_priority) 2207 return -1; 2208 if (other->key_server_priority < peer->key_server_priority) 2209 return 1; 2210 2211 return os_memcmp(peer->sci.addr, other->sci.addr, ETH_ALEN); 2212 } 2213 2214 2215 /** 2216 * ieee802_1x_kay_elect_key_server - elect the key server 2217 * when to elect: whenever the live peers list changes 2218 */ 2219 static int 2220 ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) 2221 { 2222 struct ieee802_1x_kay_peer *peer; 2223 struct ieee802_1x_kay_peer *key_server = NULL; 2224 struct ieee802_1x_kay *kay = participant->kay; 2225 Boolean i_is_key_server; 2226 int priority_comparison; 2227 2228 if (participant->is_obliged_key_server) { 2229 participant->new_sak = TRUE; 2230 participant->to_dist_sak = FALSE; 2231 ieee802_1x_cp_set_electedself(kay->cp, TRUE); 2232 return 0; 2233 } 2234 2235 /* elect the key server among the peers */ 2236 dl_list_for_each(peer, &participant->live_peers, 2237 struct ieee802_1x_kay_peer, list) { 2238 if (!peer->is_key_server) 2239 continue; 2240 2241 if (!key_server) { 2242 key_server = peer; 2243 continue; 2244 } 2245 2246 if (compare_priorities(peer, key_server) < 0) 2247 key_server = peer; 2248 } 2249 2250 /* elect the key server between me and the above elected peer */ 2251 i_is_key_server = FALSE; 2252 if (key_server && participant->can_be_key_server) { 2253 struct ieee802_1x_kay_peer tmp; 2254 2255 tmp.key_server_priority = kay->actor_priority; 2256 os_memcpy(&tmp.sci, &kay->actor_sci, sizeof(tmp.sci)); 2257 priority_comparison = compare_priorities(&tmp, key_server); 2258 if (priority_comparison < 0) { 2259 i_is_key_server = TRUE; 2260 } else if (priority_comparison == 0) { 2261 wpa_printf(MSG_WARNING, 2262 "KaY: Cannot elect key server between me and peer, duplicate MAC detected"); 2263 key_server = NULL; 2264 } 2265 } else if (participant->can_be_key_server) { 2266 i_is_key_server = TRUE; 2267 } 2268 2269 if (i_is_key_server) { 2270 ieee802_1x_cp_set_electedself(kay->cp, TRUE); 2271 if (!sci_equal(&kay->key_server_sci, &kay->actor_sci)) { 2272 ieee802_1x_cp_signal_chgdserver(kay->cp); 2273 ieee802_1x_cp_sm_step(kay->cp); 2274 } 2275 2276 participant->is_key_server = TRUE; 2277 participant->principal = TRUE; 2278 participant->new_sak = TRUE; 2279 wpa_printf(MSG_DEBUG, "KaY: I am elected as key server"); 2280 participant->to_dist_sak = FALSE; 2281 participant->is_elected = TRUE; 2282 2283 os_memcpy(&kay->key_server_sci, &kay->actor_sci, 2284 sizeof(kay->key_server_sci)); 2285 kay->key_server_priority = kay->actor_priority; 2286 } else if (key_server) { 2287 wpa_printf(MSG_DEBUG, 2288 "KaY: Peer %s was elected as the key server", 2289 mi_txt(key_server->mi)); 2290 ieee802_1x_cp_set_electedself(kay->cp, FALSE); 2291 if (!sci_equal(&kay->key_server_sci, &key_server->sci)) { 2292 ieee802_1x_cp_signal_chgdserver(kay->cp); 2293 ieee802_1x_cp_sm_step(kay->cp); 2294 } 2295 2296 participant->is_key_server = FALSE; 2297 participant->principal = TRUE; 2298 participant->is_elected = TRUE; 2299 2300 os_memcpy(&kay->key_server_sci, &key_server->sci, 2301 sizeof(kay->key_server_sci)); 2302 kay->key_server_priority = key_server->key_server_priority; 2303 } else { 2304 participant->principal = FALSE; 2305 participant->is_key_server = FALSE; 2306 participant->is_elected = FALSE; 2307 } 2308 2309 return 0; 2310 } 2311 2312 2313 /** 2314 * ieee802_1x_kay_decide_macsec_use - the key server determinate 2315 * how to use MACsec: whether use MACsec and its capability 2316 * protectFrames will be advised if the key server and one of its live peers are 2317 * MACsec capable and one of those request MACsec protection 2318 */ 2319 static int 2320 ieee802_1x_kay_decide_macsec_use( 2321 struct ieee802_1x_mka_participant *participant) 2322 { 2323 struct ieee802_1x_kay *kay = participant->kay; 2324 struct ieee802_1x_kay_peer *peer; 2325 enum macsec_cap less_capability; 2326 Boolean has_peer; 2327 2328 if (!participant->is_key_server) 2329 return -1; 2330 2331 /* key server self is MACsec-desired and requesting MACsec */ 2332 if (!kay->macsec_desired) { 2333 participant->advised_desired = FALSE; 2334 return -1; 2335 } 2336 if (kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) { 2337 participant->advised_desired = FALSE; 2338 return -1; 2339 } 2340 less_capability = kay->macsec_capable; 2341 2342 /* at least one of peers is MACsec-desired and requesting MACsec */ 2343 has_peer = FALSE; 2344 dl_list_for_each(peer, &participant->live_peers, 2345 struct ieee802_1x_kay_peer, list) { 2346 if (!peer->macsec_desired) 2347 continue; 2348 2349 if (peer->macsec_capability == MACSEC_CAP_NOT_IMPLEMENTED) 2350 continue; 2351 2352 less_capability = (less_capability < peer->macsec_capability) ? 2353 less_capability : peer->macsec_capability; 2354 has_peer = TRUE; 2355 } 2356 2357 if (has_peer) { 2358 participant->advised_desired = TRUE; 2359 participant->advised_capability = less_capability; 2360 kay->authenticated = FALSE; 2361 kay->secured = TRUE; 2362 kay->failed = FALSE; 2363 ieee802_1x_cp_connect_secure(kay->cp); 2364 ieee802_1x_cp_sm_step(kay->cp); 2365 } else { 2366 participant->advised_desired = FALSE; 2367 participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED; 2368 participant->to_use_sak = FALSE; 2369 kay->authenticated = TRUE; 2370 kay->secured = FALSE; 2371 kay->failed = FALSE; 2372 kay->ltx_kn = 0; 2373 kay->ltx_an = 0; 2374 kay->lrx_kn = 0; 2375 kay->lrx_an = 0; 2376 kay->otx_kn = 0; 2377 kay->otx_an = 0; 2378 kay->orx_kn = 0; 2379 kay->orx_an = 0; 2380 ieee802_1x_cp_connect_authenticated(kay->cp); 2381 ieee802_1x_cp_sm_step(kay->cp); 2382 } 2383 2384 return 0; 2385 } 2386 2387 static const u8 pae_group_addr[ETH_ALEN] = { 2388 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 2389 }; 2390 2391 2392 /** 2393 * ieee802_1x_kay_encode_mkpdu - 2394 */ 2395 static int 2396 ieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant *participant, 2397 struct wpabuf *pbuf) 2398 { 2399 unsigned int i; 2400 struct ieee8023_hdr *ether_hdr; 2401 struct ieee802_1x_hdr *eapol_hdr; 2402 2403 ether_hdr = wpabuf_put(pbuf, sizeof(*ether_hdr)); 2404 os_memcpy(ether_hdr->dest, pae_group_addr, sizeof(ether_hdr->dest)); 2405 os_memcpy(ether_hdr->src, participant->kay->actor_sci.addr, 2406 sizeof(ether_hdr->dest)); 2407 ether_hdr->ethertype = host_to_be16(ETH_P_EAPOL); 2408 wpa_printf(MSG_DEBUG, "KaY: Ethernet header: DA=" MACSTR " SA=" MACSTR 2409 " Ethertype=0x%x", 2410 MAC2STR(ether_hdr->dest), MAC2STR(ether_hdr->src), 2411 be_to_host16(ether_hdr->ethertype)); 2412 2413 eapol_hdr = wpabuf_put(pbuf, sizeof(*eapol_hdr)); 2414 eapol_hdr->version = EAPOL_VERSION; 2415 eapol_hdr->type = IEEE802_1X_TYPE_EAPOL_MKA; 2416 eapol_hdr->length = host_to_be16(wpabuf_tailroom(pbuf)); 2417 wpa_printf(MSG_DEBUG, 2418 "KaY: Common EAPOL PDU structure: Protocol Version=%u Packet Type=%u Packet Body Length=%u", 2419 eapol_hdr->version, eapol_hdr->type, 2420 be_to_host16(eapol_hdr->length)); 2421 2422 for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) { 2423 if (mka_body_handler[i].body_present && 2424 mka_body_handler[i].body_present(participant)) { 2425 if (mka_body_handler[i].body_tx(participant, pbuf)) 2426 return -1; 2427 } 2428 } 2429 2430 return 0; 2431 } 2432 2433 2434 /** 2435 * ieee802_1x_participant_send_mkpdu - 2436 */ 2437 static int 2438 ieee802_1x_participant_send_mkpdu( 2439 struct ieee802_1x_mka_participant *participant) 2440 { 2441 struct wpabuf *buf; 2442 struct ieee802_1x_kay *kay = participant->kay; 2443 size_t length = 0; 2444 unsigned int i; 2445 2446 wpa_printf(MSG_DEBUG, "KaY: Encode and send an MKPDU (ifname=%s)", 2447 kay->if_name); 2448 length += sizeof(struct ieee802_1x_hdr) + sizeof(struct ieee8023_hdr); 2449 for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) { 2450 if (mka_body_handler[i].body_present && 2451 mka_body_handler[i].body_present(participant)) 2452 length += mka_body_handler[i].body_length(participant); 2453 } 2454 2455 buf = wpabuf_alloc(length); 2456 if (!buf) { 2457 wpa_printf(MSG_ERROR, "KaY: out of memory"); 2458 return -1; 2459 } 2460 2461 if (ieee802_1x_kay_encode_mkpdu(participant, buf)) { 2462 wpa_printf(MSG_ERROR, "KaY: encode mkpdu fail"); 2463 return -1; 2464 } 2465 2466 wpa_hexdump_buf(MSG_MSGDUMP, "KaY: Outgoing MKPDU", buf); 2467 l2_packet_send(kay->l2_mka, NULL, 0, wpabuf_head(buf), wpabuf_len(buf)); 2468 wpabuf_free(buf); 2469 2470 kay->active = TRUE; 2471 participant->active = TRUE; 2472 2473 return 0; 2474 } 2475 2476 2477 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa); 2478 2479 static void ieee802_1x_delete_transmit_sa(struct ieee802_1x_kay *kay, 2480 struct transmit_sa *sa) 2481 { 2482 secy_disable_transmit_sa(kay, sa); 2483 secy_delete_transmit_sa(kay, sa); 2484 ieee802_1x_kay_deinit_transmit_sa(sa); 2485 } 2486 2487 2488 /** 2489 * ieee802_1x_participant_timer - 2490 */ 2491 static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) 2492 { 2493 struct ieee802_1x_mka_participant *participant; 2494 struct ieee802_1x_kay *kay; 2495 struct ieee802_1x_kay_peer *peer, *pre_peer; 2496 time_t now = time(NULL); 2497 Boolean lp_changed; 2498 struct receive_sc *rxsc, *pre_rxsc; 2499 struct transmit_sa *txsa, *pre_txsa; 2500 2501 participant = (struct ieee802_1x_mka_participant *)eloop_ctx; 2502 kay = participant->kay; 2503 wpa_printf(MSG_DEBUG, "KaY: Participant timer (ifname=%s)", 2504 kay->if_name); 2505 if (participant->cak_life) { 2506 if (now > participant->cak_life) 2507 goto delete_mka; 2508 } 2509 2510 /* should delete MKA instance if there are not live peers 2511 * when the MKA life elapsed since its creating */ 2512 if (participant->mka_life) { 2513 if (dl_list_empty(&participant->live_peers)) { 2514 if (now > participant->mka_life) 2515 goto delete_mka; 2516 } else { 2517 participant->mka_life = 0; 2518 } 2519 } 2520 2521 lp_changed = FALSE; 2522 dl_list_for_each_safe(peer, pre_peer, &participant->live_peers, 2523 struct ieee802_1x_kay_peer, list) { 2524 if (now > peer->expire) { 2525 wpa_printf(MSG_DEBUG, "KaY: Live peer removed"); 2526 wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, 2527 sizeof(peer->mi)); 2528 wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn); 2529 dl_list_for_each_safe(rxsc, pre_rxsc, 2530 &participant->rxsc_list, 2531 struct receive_sc, list) { 2532 if (sci_equal(&rxsc->sci, &peer->sci)) { 2533 ieee802_1x_kay_deinit_receive_sc( 2534 participant, rxsc); 2535 } 2536 } 2537 dl_list_del(&peer->list); 2538 os_free(peer); 2539 lp_changed = TRUE; 2540 } 2541 } 2542 2543 if (lp_changed) { 2544 if (dl_list_empty(&participant->live_peers)) { 2545 participant->advised_desired = FALSE; 2546 participant->advised_capability = 2547 MACSEC_CAP_NOT_IMPLEMENTED; 2548 participant->to_use_sak = FALSE; 2549 participant->ltx = FALSE; 2550 participant->lrx = FALSE; 2551 participant->otx = FALSE; 2552 participant->orx = FALSE; 2553 participant->is_key_server = FALSE; 2554 participant->is_elected = FALSE; 2555 kay->authenticated = FALSE; 2556 kay->secured = FALSE; 2557 kay->failed = FALSE; 2558 kay->ltx_kn = 0; 2559 kay->ltx_an = 0; 2560 kay->lrx_kn = 0; 2561 kay->lrx_an = 0; 2562 kay->otx_kn = 0; 2563 kay->otx_an = 0; 2564 kay->orx_kn = 0; 2565 kay->orx_an = 0; 2566 dl_list_for_each_safe(txsa, pre_txsa, 2567 &participant->txsc->sa_list, 2568 struct transmit_sa, list) { 2569 ieee802_1x_delete_transmit_sa(kay, txsa); 2570 } 2571 2572 ieee802_1x_cp_connect_pending(kay->cp); 2573 ieee802_1x_cp_sm_step(kay->cp); 2574 } else { 2575 ieee802_1x_kay_elect_key_server(participant); 2576 ieee802_1x_kay_decide_macsec_use(participant); 2577 } 2578 } 2579 2580 dl_list_for_each_safe(peer, pre_peer, &participant->potential_peers, 2581 struct ieee802_1x_kay_peer, list) { 2582 if (now > peer->expire) { 2583 wpa_printf(MSG_DEBUG, "KaY: Potential peer removed"); 2584 wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, 2585 sizeof(peer->mi)); 2586 wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn); 2587 dl_list_del(&peer->list); 2588 os_free(peer); 2589 } 2590 } 2591 2592 if (participant->new_sak && participant->is_key_server) { 2593 if (!ieee802_1x_kay_generate_new_sak(participant)) 2594 participant->to_dist_sak = TRUE; 2595 2596 participant->new_sak = FALSE; 2597 } 2598 2599 if (participant->retry_count < MAX_RETRY_CNT || 2600 participant->mode == PSK) { 2601 ieee802_1x_participant_send_mkpdu(participant); 2602 participant->retry_count++; 2603 } 2604 2605 eloop_register_timeout(kay->mka_hello_time / 1000, 0, 2606 ieee802_1x_participant_timer, 2607 participant, NULL); 2608 2609 return; 2610 2611 delete_mka: 2612 kay->authenticated = FALSE; 2613 kay->secured = FALSE; 2614 kay->failed = TRUE; 2615 ieee802_1x_kay_delete_mka(kay, &participant->ckn); 2616 } 2617 2618 2619 /** 2620 * ieee802_1x_kay_init_transmit_sa - 2621 */ 2622 static struct transmit_sa * 2623 ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN, 2624 struct data_key *key) 2625 { 2626 struct transmit_sa *psa; 2627 2628 key->tx_latest = TRUE; 2629 key->rx_latest = TRUE; 2630 2631 psa = os_zalloc(sizeof(*psa)); 2632 if (!psa) { 2633 wpa_printf(MSG_ERROR, "%s: out of memory", __func__); 2634 return NULL; 2635 } 2636 2637 if (key->confidentiality_offset >= CONFIDENTIALITY_OFFSET_0 && 2638 key->confidentiality_offset <= CONFIDENTIALITY_OFFSET_50) 2639 psa->confidentiality = TRUE; 2640 else 2641 psa->confidentiality = FALSE; 2642 2643 psa->an = an; 2644 ieee802_1x_kay_use_data_key(key); 2645 psa->pkey = key; 2646 psa->next_pn = next_PN; 2647 psa->sc = psc; 2648 2649 os_get_time(&psa->created_time); 2650 psa->in_use = FALSE; 2651 2652 dl_list_add(&psc->sa_list, &psa->list); 2653 wpa_printf(MSG_DEBUG, 2654 "KaY: Create transmit SA(an: %hhu, next_pn: %u) of SC", 2655 an, next_PN); 2656 2657 return psa; 2658 } 2659 2660 2661 /** 2662 * ieee802_1x_kay_deinit_transmit_sa - 2663 */ 2664 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa) 2665 { 2666 ieee802_1x_kay_deinit_data_key(psa->pkey); 2667 psa->pkey = NULL; 2668 wpa_printf(MSG_DEBUG, 2669 "KaY: Delete transmit SA(an: %hhu) of SC", 2670 psa->an); 2671 dl_list_del(&psa->list); 2672 os_free(psa); 2673 } 2674 2675 2676 /** 2677 * init_transmit_sc - 2678 */ 2679 static struct transmit_sc * 2680 ieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci *sci) 2681 { 2682 struct transmit_sc *psc; 2683 2684 psc = os_zalloc(sizeof(*psc)); 2685 if (!psc) { 2686 wpa_printf(MSG_ERROR, "%s: out of memory", __func__); 2687 return NULL; 2688 } 2689 os_memcpy(&psc->sci, sci, sizeof(psc->sci)); 2690 2691 os_get_time(&psc->created_time); 2692 psc->transmitting = FALSE; 2693 psc->encoding_sa = FALSE; 2694 psc->enciphering_sa = FALSE; 2695 2696 dl_list_init(&psc->sa_list); 2697 wpa_printf(MSG_DEBUG, "KaY: Create transmit SC - SCI: %s", 2698 sci_txt(&psc->sci)); 2699 2700 return psc; 2701 } 2702 2703 2704 /** 2705 * ieee802_1x_kay_deinit_transmit_sc - 2706 */ 2707 static void 2708 ieee802_1x_kay_deinit_transmit_sc( 2709 struct ieee802_1x_mka_participant *participant, struct transmit_sc *psc) 2710 { 2711 struct transmit_sa *psa, *tmp; 2712 2713 wpa_printf(MSG_DEBUG, "KaY: Delete transmit SC"); 2714 dl_list_for_each_safe(psa, tmp, &psc->sa_list, struct transmit_sa, list) 2715 ieee802_1x_delete_transmit_sa(participant->kay, psa); 2716 2717 secy_delete_transmit_sc(participant->kay, psc); 2718 os_free(psc); 2719 } 2720 2721 2722 /****************** Interface between CP and KAY *********************/ 2723 /** 2724 * ieee802_1x_kay_set_latest_sa_attr - 2725 */ 2726 int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay, 2727 struct ieee802_1x_mka_ki *lki, u8 lan, 2728 Boolean ltx, Boolean lrx) 2729 { 2730 struct ieee802_1x_mka_participant *principal; 2731 2732 principal = ieee802_1x_kay_get_principal_participant(kay); 2733 if (!principal) 2734 return -1; 2735 2736 if (!lki) 2737 os_memset(&principal->lki, 0, sizeof(principal->lki)); 2738 else 2739 os_memcpy(&principal->lki, lki, sizeof(principal->lki)); 2740 2741 principal->lan = lan; 2742 principal->ltx = ltx; 2743 principal->lrx = lrx; 2744 if (!lki) { 2745 kay->ltx_kn = 0; 2746 kay->lrx_kn = 0; 2747 } else { 2748 kay->ltx_kn = lki->kn; 2749 kay->lrx_kn = lki->kn; 2750 } 2751 kay->ltx_an = lan; 2752 kay->lrx_an = lan; 2753 2754 return 0; 2755 } 2756 2757 2758 /** 2759 * ieee802_1x_kay_set_old_sa_attr - 2760 */ 2761 int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay, 2762 struct ieee802_1x_mka_ki *oki, 2763 u8 oan, Boolean otx, Boolean orx) 2764 { 2765 struct ieee802_1x_mka_participant *principal; 2766 2767 principal = ieee802_1x_kay_get_principal_participant(kay); 2768 if (!principal) 2769 return -1; 2770 2771 if (!oki) 2772 os_memset(&principal->oki, 0, sizeof(principal->oki)); 2773 else 2774 os_memcpy(&principal->oki, oki, sizeof(principal->oki)); 2775 2776 principal->oan = oan; 2777 principal->otx = otx; 2778 principal->orx = orx; 2779 2780 if (!oki) { 2781 kay->otx_kn = 0; 2782 kay->orx_kn = 0; 2783 } else { 2784 kay->otx_kn = oki->kn; 2785 kay->orx_kn = oki->kn; 2786 } 2787 kay->otx_an = oan; 2788 kay->orx_an = oan; 2789 2790 return 0; 2791 } 2792 2793 2794 static struct transmit_sa * lookup_txsa_by_an(struct transmit_sc *txsc, u8 an) 2795 { 2796 struct transmit_sa *txsa; 2797 2798 dl_list_for_each(txsa, &txsc->sa_list, struct transmit_sa, list) { 2799 if (txsa->an == an) 2800 return txsa; 2801 } 2802 2803 return NULL; 2804 } 2805 2806 2807 static struct receive_sa * lookup_rxsa_by_an(struct receive_sc *rxsc, u8 an) 2808 { 2809 struct receive_sa *rxsa; 2810 2811 dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) { 2812 if (rxsa->an == an) 2813 return rxsa; 2814 } 2815 2816 return NULL; 2817 } 2818 2819 2820 /** 2821 * ieee802_1x_kay_create_sas - 2822 */ 2823 int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay, 2824 struct ieee802_1x_mka_ki *lki) 2825 { 2826 struct data_key *sa_key, *latest_sak; 2827 struct ieee802_1x_mka_participant *principal; 2828 struct receive_sc *rxsc; 2829 struct receive_sa *rxsa; 2830 struct transmit_sa *txsa; 2831 2832 principal = ieee802_1x_kay_get_principal_participant(kay); 2833 if (!principal) 2834 return -1; 2835 2836 latest_sak = NULL; 2837 dl_list_for_each(sa_key, &principal->sak_list, struct data_key, list) { 2838 if (is_ki_equal(&sa_key->key_identifier, lki)) { 2839 sa_key->rx_latest = TRUE; 2840 sa_key->tx_latest = TRUE; 2841 latest_sak = sa_key; 2842 principal->to_use_sak = TRUE; 2843 } else { 2844 sa_key->rx_latest = FALSE; 2845 sa_key->tx_latest = FALSE; 2846 } 2847 } 2848 if (!latest_sak) { 2849 wpa_printf(MSG_ERROR, "KaY: lki related sak not found"); 2850 return -1; 2851 } 2852 2853 dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) { 2854 while ((rxsa = lookup_rxsa_by_an(rxsc, latest_sak->an)) != NULL) 2855 ieee802_1x_delete_receive_sa(kay, rxsa); 2856 2857 rxsa = ieee802_1x_kay_init_receive_sa(rxsc, latest_sak->an, 1, 2858 latest_sak); 2859 if (!rxsa) 2860 return -1; 2861 2862 secy_create_receive_sa(kay, rxsa); 2863 } 2864 2865 while ((txsa = lookup_txsa_by_an(principal->txsc, latest_sak->an)) != 2866 NULL) 2867 ieee802_1x_delete_transmit_sa(kay, txsa); 2868 2869 txsa = ieee802_1x_kay_init_transmit_sa(principal->txsc, latest_sak->an, 2870 latest_sak->next_pn ? 2871 latest_sak->next_pn : 1, 2872 latest_sak); 2873 if (!txsa) 2874 return -1; 2875 2876 secy_create_transmit_sa(kay, txsa); 2877 2878 2879 2880 return 0; 2881 } 2882 2883 2884 /** 2885 * ieee802_1x_kay_delete_sas - 2886 */ 2887 int ieee802_1x_kay_delete_sas(struct ieee802_1x_kay *kay, 2888 struct ieee802_1x_mka_ki *ki) 2889 { 2890 struct data_key *sa_key, *pre_key; 2891 struct transmit_sa *txsa, *pre_txsa; 2892 struct receive_sa *rxsa, *pre_rxsa; 2893 struct receive_sc *rxsc; 2894 struct ieee802_1x_mka_participant *principal; 2895 2896 wpa_printf(MSG_DEBUG, "KaY: Entry into %s", __func__); 2897 principal = ieee802_1x_kay_get_principal_participant(kay); 2898 if (!principal) 2899 return -1; 2900 2901 /* remove the transmit sa */ 2902 dl_list_for_each_safe(txsa, pre_txsa, &principal->txsc->sa_list, 2903 struct transmit_sa, list) { 2904 if (is_ki_equal(&txsa->pkey->key_identifier, ki)) 2905 ieee802_1x_delete_transmit_sa(kay, txsa); 2906 } 2907 2908 /* remove the receive sa */ 2909 dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) { 2910 dl_list_for_each_safe(rxsa, pre_rxsa, &rxsc->sa_list, 2911 struct receive_sa, list) { 2912 if (is_ki_equal(&rxsa->pkey->key_identifier, ki)) 2913 ieee802_1x_delete_receive_sa(kay, rxsa); 2914 } 2915 } 2916 2917 /* remove the sak */ 2918 dl_list_for_each_safe(sa_key, pre_key, &principal->sak_list, 2919 struct data_key, list) { 2920 if (is_ki_equal(&sa_key->key_identifier, ki)) { 2921 if (principal->new_key == sa_key) 2922 principal->new_key = NULL; 2923 dl_list_del(&sa_key->list); 2924 ieee802_1x_kay_deinit_data_key(sa_key); 2925 break; 2926 } 2927 } 2928 2929 return 0; 2930 } 2931 2932 2933 /** 2934 * ieee802_1x_kay_enable_tx_sas - 2935 */ 2936 int ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay *kay, 2937 struct ieee802_1x_mka_ki *lki) 2938 { 2939 struct ieee802_1x_mka_participant *principal; 2940 struct transmit_sa *txsa; 2941 2942 principal = ieee802_1x_kay_get_principal_participant(kay); 2943 if (!principal) 2944 return -1; 2945 2946 dl_list_for_each(txsa, &principal->txsc->sa_list, struct transmit_sa, 2947 list) { 2948 if (is_ki_equal(&txsa->pkey->key_identifier, lki)) { 2949 txsa->in_use = TRUE; 2950 secy_enable_transmit_sa(kay, txsa); 2951 ieee802_1x_cp_set_usingtransmitas( 2952 principal->kay->cp, TRUE); 2953 ieee802_1x_cp_sm_step(principal->kay->cp); 2954 } 2955 } 2956 2957 return 0; 2958 } 2959 2960 2961 /** 2962 * ieee802_1x_kay_enable_rx_sas - 2963 */ 2964 int ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay *kay, 2965 struct ieee802_1x_mka_ki *lki) 2966 { 2967 struct ieee802_1x_mka_participant *principal; 2968 struct receive_sa *rxsa; 2969 struct receive_sc *rxsc; 2970 2971 principal = ieee802_1x_kay_get_principal_participant(kay); 2972 if (!principal) 2973 return -1; 2974 2975 dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) { 2976 dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) 2977 { 2978 if (is_ki_equal(&rxsa->pkey->key_identifier, lki)) { 2979 rxsa->in_use = TRUE; 2980 secy_enable_receive_sa(kay, rxsa); 2981 ieee802_1x_cp_set_usingreceivesas( 2982 principal->kay->cp, TRUE); 2983 ieee802_1x_cp_sm_step(principal->kay->cp); 2984 } 2985 } 2986 } 2987 2988 return 0; 2989 } 2990 2991 2992 /** 2993 * ieee802_1x_kay_enable_new_info - 2994 */ 2995 int ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay *kay) 2996 { 2997 struct ieee802_1x_mka_participant *principal; 2998 2999 principal = ieee802_1x_kay_get_principal_participant(kay); 3000 if (!principal) 3001 return -1; 3002 3003 if (principal->retry_count < MAX_RETRY_CNT || principal->mode == PSK) { 3004 ieee802_1x_participant_send_mkpdu(principal); 3005 principal->retry_count++; 3006 } 3007 3008 return 0; 3009 } 3010 3011 3012 /** 3013 * ieee802_1x_kay_mkpdu_sanity_check - 3014 * Sanity checks specified in IEEE Std 802.1X-2010, 11.11.2 (Validation of 3015 * MKPDUs) 3016 */ 3017 static int ieee802_1x_kay_mkpdu_sanity_check(struct ieee802_1x_kay *kay, 3018 const u8 *buf, size_t len) 3019 { 3020 struct ieee8023_hdr *eth_hdr; 3021 struct ieee802_1x_hdr *eapol_hdr; 3022 struct ieee802_1x_mka_hdr *mka_hdr; 3023 struct ieee802_1x_mka_basic_body *body; 3024 size_t mka_msg_len; 3025 struct ieee802_1x_mka_participant *participant; 3026 size_t body_len; 3027 size_t ckn_len; 3028 u8 icv[MAX_ICV_LEN]; 3029 const u8 *msg_icv; 3030 3031 /* len > eth+eapol header already verified in kay_l2_receive(); 3032 * likewise, eapol_hdr->length validated there */ 3033 eth_hdr = (struct ieee8023_hdr *) buf; 3034 eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1); 3035 mka_hdr = (struct ieee802_1x_mka_hdr *) (eapol_hdr + 1); 3036 3037 wpa_printf(MSG_DEBUG, "KaY: Ethernet header: DA=" MACSTR " SA=" MACSTR 3038 " Ethertype=0x%x", 3039 MAC2STR(eth_hdr->dest), MAC2STR(eth_hdr->src), 3040 be_to_host16(eth_hdr->ethertype)); 3041 3042 /* the destination address shall not be an individual address */ 3043 if (os_memcmp(eth_hdr->dest, pae_group_addr, ETH_ALEN) != 0) { 3044 wpa_printf(MSG_DEBUG, 3045 "KaY: ethernet destination address is not PAE group address"); 3046 return -1; 3047 } 3048 3049 wpa_printf(MSG_DEBUG, 3050 "KaY: Common EAPOL PDU structure: Protocol Version=%u Packet Type=%u Packet Body Length=%u", 3051 eapol_hdr->version, eapol_hdr->type, 3052 be_to_host16(eapol_hdr->length)); 3053 3054 /* MKPDU shall not be less than 32 octets */ 3055 mka_msg_len = be_to_host16(eapol_hdr->length); 3056 if (mka_msg_len < 32) { 3057 wpa_printf(MSG_DEBUG, "KaY: MKPDU is less than 32 octets"); 3058 return -1; 3059 } 3060 /* MKPDU shall be a multiple of 4 octets */ 3061 if ((mka_msg_len % 4) != 0) { 3062 wpa_printf(MSG_DEBUG, 3063 "KaY: MKPDU is not multiple of 4 octets"); 3064 return -1; 3065 } 3066 3067 wpa_hexdump(MSG_MSGDUMP, "KaY: EAPOL-MKA Packet Body (MKPDU)", 3068 mka_hdr, mka_msg_len); 3069 3070 /* Room for body_len already verified in kay_l2_receive() */ 3071 body = (struct ieee802_1x_mka_basic_body *) mka_hdr; 3072 body_len = get_mka_param_body_len(body); 3073 /* EAPOL-MKA body should comprise basic parameter set and ICV */ 3074 if (mka_msg_len < MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN) { 3075 wpa_printf(MSG_ERROR, 3076 "KaY: Received EAPOL-MKA Packet Body Length (%zu bytes) is less than the Basic Parameter Set Header Length (%zu bytes) + the Basic Parameter Set Body Length (%zu bytes) + %d bytes of ICV", 3077 mka_msg_len, MKA_HDR_LEN, 3078 body_len, DEFAULT_ICV_LEN); 3079 return -1; 3080 } 3081 3082 if (body_len < sizeof(struct ieee802_1x_mka_basic_body) - MKA_HDR_LEN) { 3083 wpa_printf(MSG_DEBUG, "KaY: Too small body length %zu", 3084 body_len); 3085 return -1; 3086 } 3087 ckn_len = body_len - 3088 (sizeof(struct ieee802_1x_mka_basic_body) - MKA_HDR_LEN); 3089 if (ckn_len < 1 || ckn_len > MAX_CKN_LEN) { 3090 wpa_printf(MSG_WARNING, 3091 "KaY: Received EAPOL-MKA CKN Length (%zu bytes) is out of range (<= %u bytes)", 3092 ckn_len, MAX_CKN_LEN); 3093 return -1; 3094 } 3095 3096 ieee802_1x_mka_dump_basic_body(body); 3097 3098 /* CKN should be owned by I */ 3099 participant = ieee802_1x_kay_get_participant(kay, body->ckn, ckn_len); 3100 if (!participant) { 3101 wpa_printf(MSG_DEBUG, "KaY: CKN is not included in my CA"); 3102 return -1; 3103 } 3104 3105 /* algorithm agility check */ 3106 if (os_memcmp(body->algo_agility, mka_algo_agility, 3107 sizeof(body->algo_agility)) != 0) { 3108 wpa_printf(MSG_INFO, 3109 "KaY: Peer's algorithm agility (%s) not supported", 3110 algo_agility_txt(body->algo_agility)); 3111 return -1; 3112 } 3113 3114 /* ICV check */ 3115 /* 3116 * The ICV will comprise the final octets of the packet body, whatever 3117 * its size, not the fixed length 16 octets, indicated by the EAPOL 3118 * packet body length. 3119 */ 3120 if (len < mka_alg_tbl[kay->mka_algindex].icv_len || 3121 mka_alg_tbl[kay->mka_algindex].icv_hash( 3122 participant->ick.key, participant->ick.len, 3123 buf, len - mka_alg_tbl[kay->mka_algindex].icv_len, icv)) { 3124 wpa_printf(MSG_ERROR, "KaY: Failed to calculate ICV"); 3125 return -1; 3126 } 3127 3128 msg_icv = ieee802_1x_mka_decode_icv_body(participant, 3129 (const u8 *) mka_hdr, 3130 mka_msg_len); 3131 if (!msg_icv) { 3132 wpa_printf(MSG_WARNING, "KaY: No ICV in MKPDU - ignore it"); 3133 return -1; 3134 } 3135 wpa_hexdump(MSG_DEBUG, "KaY: Received ICV", 3136 msg_icv, mka_alg_tbl[kay->mka_algindex].icv_len); 3137 if (os_memcmp_const(msg_icv, icv, 3138 mka_alg_tbl[kay->mka_algindex].icv_len) != 0) { 3139 wpa_printf(MSG_WARNING, 3140 "KaY: Computed ICV is not equal to Received ICV"); 3141 wpa_hexdump(MSG_DEBUG, "KaY: Calculated ICV", 3142 icv, mka_alg_tbl[kay->mka_algindex].icv_len); 3143 return -1; 3144 } 3145 3146 return 0; 3147 } 3148 3149 3150 /** 3151 * ieee802_1x_kay_decode_mkpdu - 3152 */ 3153 static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, 3154 const u8 *buf, size_t len) 3155 { 3156 struct ieee802_1x_mka_participant *participant; 3157 struct ieee802_1x_mka_hdr *hdr; 3158 struct ieee802_1x_kay_peer *peer; 3159 size_t body_len; 3160 size_t left_len; 3161 u8 body_type; 3162 int i; 3163 const u8 *pos; 3164 Boolean handled[256]; 3165 Boolean bad_sak_use = FALSE; /* Error detected while processing SAK Use 3166 * parameter set */ 3167 Boolean i_in_peerlist, is_in_live_peer, is_in_potential_peer; 3168 3169 wpa_printf(MSG_DEBUG, "KaY: Decode received MKPDU (ifname=%s)", 3170 kay->if_name); 3171 if (ieee802_1x_kay_mkpdu_sanity_check(kay, buf, len)) 3172 return -1; 3173 3174 /* handle basic parameter set */ 3175 pos = buf + sizeof(struct ieee8023_hdr) + sizeof(struct ieee802_1x_hdr); 3176 left_len = len - sizeof(struct ieee8023_hdr) - 3177 sizeof(struct ieee802_1x_hdr); 3178 participant = ieee802_1x_mka_decode_basic_body(kay, pos, left_len); 3179 if (!participant) 3180 return -1; 3181 3182 /* to skip basic parameter set */ 3183 hdr = (struct ieee802_1x_mka_hdr *) pos; 3184 body_len = MKA_ALIGN_LENGTH(get_mka_param_body_len(hdr)); 3185 if (left_len < body_len + MKA_HDR_LEN) 3186 return -1; 3187 pos += body_len + MKA_HDR_LEN; 3188 left_len -= body_len + MKA_HDR_LEN; 3189 3190 /* check i am in the peer's peer list */ 3191 i_in_peerlist = ieee802_1x_mka_i_in_peerlist(participant, pos, 3192 left_len); 3193 is_in_live_peer = ieee802_1x_kay_is_in_live_peer( 3194 participant, participant->current_peer_id.mi); 3195 wpa_printf(MSG_DEBUG, "KaY: i_in_peerlist=%s is_in_live_peer=%s", 3196 yes_no(i_in_peerlist), yes_no(is_in_live_peer)); 3197 if (i_in_peerlist && !is_in_live_peer) { 3198 /* accept the peer as live peer */ 3199 is_in_potential_peer = ieee802_1x_kay_is_in_potential_peer( 3200 participant, participant->current_peer_id.mi); 3201 if (is_in_potential_peer) { 3202 if (!ieee802_1x_kay_move_live_peer( 3203 participant, 3204 participant->current_peer_id.mi, 3205 be_to_host32(participant-> 3206 current_peer_id.mn))) 3207 return -1; 3208 } else if (!ieee802_1x_kay_create_live_peer( 3209 participant, participant->current_peer_id.mi, 3210 be_to_host32(participant-> 3211 current_peer_id.mn))) { 3212 return -1; 3213 } 3214 3215 ieee802_1x_kay_elect_key_server(participant); 3216 ieee802_1x_kay_decide_macsec_use(participant); 3217 } 3218 3219 /* 3220 * Handle other parameter set than basic parameter set. 3221 * Each parameter set should be present only once. 3222 */ 3223 for (i = 0; i < 256; i++) 3224 handled[i] = FALSE; 3225 3226 handled[0] = TRUE; 3227 for (; left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN; 3228 pos += body_len + MKA_HDR_LEN, 3229 left_len -= body_len + MKA_HDR_LEN) { 3230 hdr = (struct ieee802_1x_mka_hdr *) pos; 3231 body_len = MKA_ALIGN_LENGTH(get_mka_param_body_len(hdr)); 3232 body_type = get_mka_param_body_type(hdr); 3233 3234 if (body_type == MKA_ICV_INDICATOR) 3235 return 0; 3236 3237 if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) { 3238 wpa_printf(MSG_ERROR, 3239 "KaY: MKA Peer Packet Body Length (%zu bytes) is less than the Parameter Set Header Length (%zu bytes) + the Parameter Set Body Length (%zu bytes) + %d bytes of ICV", 3240 left_len, MKA_HDR_LEN, 3241 body_len, DEFAULT_ICV_LEN); 3242 return -1; 3243 } 3244 3245 if (handled[body_type]) { 3246 wpa_printf(MSG_DEBUG, 3247 "KaY: Ignore duplicated body type %u", 3248 body_type); 3249 continue; 3250 } 3251 3252 handled[body_type] = TRUE; 3253 if (body_type < ARRAY_SIZE(mka_body_handler) && 3254 mka_body_handler[body_type].body_rx) { 3255 if (mka_body_handler[body_type].body_rx 3256 (participant, pos, left_len) != 0) { 3257 /* Handle parameter set failure */ 3258 if (body_type != MKA_SAK_USE) { 3259 wpa_printf(MSG_INFO, 3260 "KaY: Discarding Rx MKPDU: decode of parameter set type (%d) failed", 3261 body_type); 3262 return -1; 3263 } 3264 3265 /* Ideally DIST-SAK should be processed before 3266 * SAK-USE. Unfortunately IEEE Std 802.1X-2010, 3267 * 11.11.3 (Encoding MKPDUs) states SAK-USE(3) 3268 * must always be encoded before DIST-SAK(4). 3269 * Rather than redesigning mka_body_handler so 3270 * that it somehow processes DIST-SAK before 3271 * SAK-USE, just ignore SAK-USE failures if 3272 * DIST-SAK is also present in this MKPDU. */ 3273 bad_sak_use = TRUE; 3274 } 3275 } else { 3276 wpa_printf(MSG_ERROR, 3277 "KaY: The body type %d is not supported in this MKA version %d", 3278 body_type, MKA_VERSION_ID); 3279 } 3280 } 3281 3282 if (bad_sak_use && !handled[MKA_DISTRIBUTED_SAK]) { 3283 wpa_printf(MSG_INFO, 3284 "KaY: Discarding Rx MKPDU: decode of parameter set type (%d) failed", 3285 MKA_SAK_USE); 3286 if (!reset_participant_mi(participant)) 3287 wpa_printf(MSG_DEBUG, "KaY: Could not update mi"); 3288 else 3289 wpa_printf(MSG_DEBUG, 3290 "KaY: Selected a new random MI: %s", 3291 mi_txt(participant->mi)); 3292 return -1; 3293 } 3294 3295 /* Detect missing parameter sets */ 3296 peer = ieee802_1x_kay_get_live_peer(participant, 3297 participant->current_peer_id.mi); 3298 if (peer) { 3299 /* MKPDU is from live peer */ 3300 if (!handled[MKA_SAK_USE]) { 3301 /* Once a live peer starts sending SAK-USE, it should be 3302 * sent every time. */ 3303 if (peer->sak_used) { 3304 wpa_printf(MSG_INFO, 3305 "KaY: Discarding Rx MKPDU: Live Peer stopped sending SAK-USE"); 3306 return -1; 3307 } 3308 3309 /* Live peer is probably hung if it hasn't sent SAK-USE 3310 * after a reasonable number of MKPDUs. Drop the MKPDU, 3311 * which will eventually force an timeout. */ 3312 if (++peer->missing_sak_use_count > 3313 MAX_MISSING_SAK_USE) { 3314 wpa_printf(MSG_INFO, 3315 "KaY: Discarding Rx MKPDU: Live Peer not sending SAK-USE"); 3316 return -1; 3317 } 3318 } else { 3319 peer->missing_sak_use_count = 0; 3320 3321 /* Only update live peer watchdog after successful 3322 * decode of all parameter sets */ 3323 peer->expire = time(NULL) + MKA_LIFE_TIME / 1000; 3324 } 3325 } else { 3326 /* MKPDU is from new or potential peer */ 3327 peer = ieee802_1x_kay_get_peer(participant, 3328 participant->current_peer_id.mi); 3329 if (!peer) { 3330 wpa_printf(MSG_DEBUG, "KaY: No peer entry found"); 3331 return -1; 3332 } 3333 3334 /* Do not update potential peer watchdog. Per IEEE Std 3335 * 802.1X-2010, 9.4.3, potential peers need to show liveness by 3336 * including our MI/MN in their transmitted MKPDU (within 3337 * potential or live parameter sets). Whena potential peer does 3338 * include our MI/MN in an MKPDU, we respond by moving the peer 3339 * from 'potential_peers' to 'live_peers'. */ 3340 } 3341 3342 kay->active = TRUE; 3343 participant->retry_count = 0; 3344 participant->active = TRUE; 3345 3346 return 0; 3347 } 3348 3349 3350 3351 static void kay_l2_receive(void *ctx, const u8 *src_addr, const u8 *buf, 3352 size_t len) 3353 { 3354 struct ieee802_1x_kay *kay = ctx; 3355 struct ieee8023_hdr *eth_hdr; 3356 struct ieee802_1x_hdr *eapol_hdr; 3357 size_t calc_len; 3358 3359 /* IEEE Std 802.1X-2010, 11.4 (Validation of received EAPOL PDUs) */ 3360 3361 /* must contain at least ieee8023_hdr + ieee802_1x_hdr */ 3362 if (len < sizeof(*eth_hdr) + sizeof(*eapol_hdr)) { 3363 wpa_printf(MSG_MSGDUMP, "KaY: EAPOL frame too short (%lu)", 3364 (unsigned long) len); 3365 return; 3366 } 3367 3368 eth_hdr = (struct ieee8023_hdr *) buf; 3369 eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1); 3370 calc_len = sizeof(*eth_hdr) + sizeof(*eapol_hdr) + 3371 be_to_host16(eapol_hdr->length); 3372 if (len < calc_len) { 3373 wpa_printf(MSG_MSGDUMP, "KaY: EAPOL MPDU is invalid: (received len %lu, calculated len %lu, EAPOL length %u)", 3374 (unsigned long) len, 3375 (unsigned long) calc_len, 3376 be_to_host16(eapol_hdr->length)); 3377 return; 3378 } 3379 if (len > calc_len) { 3380 wpa_hexdump(MSG_DEBUG, 3381 "KaY: Ignore extra octets following the Packey Body field", 3382 &buf[calc_len], len - calc_len); 3383 len = calc_len; 3384 } 3385 3386 if (eapol_hdr->version < EAPOL_VERSION) { 3387 wpa_printf(MSG_MSGDUMP, "KaY: version %d does not support MKA", 3388 eapol_hdr->version); 3389 return; 3390 } 3391 if (be_to_host16(eth_hdr->ethertype) != ETH_P_PAE || 3392 eapol_hdr->type != IEEE802_1X_TYPE_EAPOL_MKA) 3393 return; /* ignore other EAPOL types silently here */ 3394 3395 wpa_hexdump(MSG_DEBUG, "KaY: RX EAPOL-MKA", buf, len); 3396 if (dl_list_empty(&kay->participant_list)) { 3397 wpa_printf(MSG_ERROR, 3398 "KaY: No MKA participant instance - ignore EAPOL-MKA"); 3399 return; 3400 } 3401 3402 ieee802_1x_kay_decode_mkpdu(kay, buf, len); 3403 } 3404 3405 3406 /** 3407 * ieee802_1x_kay_init - 3408 */ 3409 struct ieee802_1x_kay * 3410 ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, 3411 Boolean macsec_replay_protect, u32 macsec_replay_window, 3412 u16 port, u8 priority, const char *ifname, const u8 *addr) 3413 { 3414 struct ieee802_1x_kay *kay; 3415 3416 wpa_printf(MSG_DEBUG, "KaY: Initialize - ifname=%s addr=" MACSTR 3417 " port=%u priority=%u", 3418 ifname, MAC2STR(addr), port, priority); 3419 kay = os_zalloc(sizeof(*kay)); 3420 if (!kay) { 3421 wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__); 3422 os_free(ctx); 3423 return NULL; 3424 } 3425 3426 kay->ctx = ctx; 3427 3428 kay->enable = TRUE; 3429 kay->active = FALSE; 3430 3431 kay->authenticated = FALSE; 3432 kay->secured = FALSE; 3433 kay->failed = FALSE; 3434 kay->policy = policy; 3435 3436 os_strlcpy(kay->if_name, ifname, IFNAMSIZ); 3437 os_memcpy(kay->actor_sci.addr, addr, ETH_ALEN); 3438 kay->actor_sci.port = host_to_be16(port ? port : 0x0001); 3439 wpa_printf(MSG_DEBUG, "KaY: Generated SCI: %s", 3440 sci_txt(&kay->actor_sci)); 3441 kay->actor_priority = priority; 3442 3443 /* While actor acts as a key server, shall distribute sakey */ 3444 kay->dist_kn = 1; 3445 kay->dist_an = 0; 3446 kay->dist_time = 0; 3447 3448 kay->pn_exhaustion = PENDING_PN_EXHAUSTION; 3449 kay->macsec_csindex = DEFAULT_CS_INDEX; 3450 kay->mka_algindex = DEFAULT_MKA_ALG_INDEX; 3451 kay->mka_version = MKA_VERSION_ID; 3452 3453 os_memcpy(kay->algo_agility, mka_algo_agility, 3454 sizeof(kay->algo_agility)); 3455 3456 dl_list_init(&kay->participant_list); 3457 3458 if (policy != DO_NOT_SECURE && 3459 secy_get_capability(kay, &kay->macsec_capable) < 0) 3460 goto error; 3461 3462 if (policy == DO_NOT_SECURE || 3463 kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) { 3464 kay->macsec_capable = MACSEC_CAP_NOT_IMPLEMENTED; 3465 kay->macsec_desired = FALSE; 3466 kay->macsec_protect = FALSE; 3467 kay->macsec_encrypt = FALSE; 3468 kay->macsec_validate = Disabled; 3469 kay->macsec_replay_protect = FALSE; 3470 kay->macsec_replay_window = 0; 3471 kay->macsec_confidentiality = CONFIDENTIALITY_NONE; 3472 kay->mka_hello_time = MKA_HELLO_TIME; 3473 } else { 3474 kay->macsec_desired = TRUE; 3475 kay->macsec_protect = TRUE; 3476 if (kay->macsec_capable >= MACSEC_CAP_INTEG_AND_CONF && 3477 policy == SHOULD_ENCRYPT) { 3478 kay->macsec_encrypt = TRUE; 3479 kay->macsec_confidentiality = CONFIDENTIALITY_OFFSET_0; 3480 } else { /* SHOULD_SECURE */ 3481 kay->macsec_encrypt = FALSE; 3482 kay->macsec_confidentiality = CONFIDENTIALITY_NONE; 3483 } 3484 kay->macsec_validate = Strict; 3485 kay->macsec_replay_protect = macsec_replay_protect; 3486 kay->macsec_replay_window = macsec_replay_window; 3487 kay->mka_hello_time = MKA_HELLO_TIME; 3488 } 3489 3490 wpa_printf(MSG_DEBUG, "KaY: state machine created"); 3491 3492 /* Initialize the SecY must be prio to CP, as CP will control SecY */ 3493 if (secy_init_macsec(kay) < 0) { 3494 wpa_printf(MSG_DEBUG, "KaY: Could not initialize MACsec"); 3495 goto error; 3496 } 3497 3498 wpa_printf(MSG_DEBUG, "KaY: secy init macsec done"); 3499 3500 /* init CP */ 3501 kay->cp = ieee802_1x_cp_sm_init(kay); 3502 if (kay->cp == NULL) 3503 goto error; 3504 3505 if (policy == DO_NOT_SECURE) { 3506 ieee802_1x_cp_connect_authenticated(kay->cp); 3507 ieee802_1x_cp_sm_step(kay->cp); 3508 } else { 3509 kay->l2_mka = l2_packet_init(kay->if_name, NULL, ETH_P_PAE, 3510 kay_l2_receive, kay, 1); 3511 if (kay->l2_mka == NULL) { 3512 wpa_printf(MSG_WARNING, 3513 "KaY: Failed to initialize L2 packet processing for MKA packet"); 3514 goto error; 3515 } 3516 } 3517 3518 return kay; 3519 3520 error: 3521 ieee802_1x_kay_deinit(kay); 3522 return NULL; 3523 } 3524 3525 3526 /** 3527 * ieee802_1x_kay_deinit - 3528 */ 3529 void 3530 ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay) 3531 { 3532 struct ieee802_1x_mka_participant *participant; 3533 3534 if (!kay) 3535 return; 3536 3537 wpa_printf(MSG_DEBUG, "KaY: state machine removed"); 3538 3539 while (!dl_list_empty(&kay->participant_list)) { 3540 participant = dl_list_entry(kay->participant_list.next, 3541 struct ieee802_1x_mka_participant, 3542 list); 3543 ieee802_1x_kay_delete_mka(kay, &participant->ckn); 3544 } 3545 3546 ieee802_1x_cp_sm_deinit(kay->cp); 3547 secy_deinit_macsec(kay); 3548 3549 if (kay->l2_mka) { 3550 l2_packet_deinit(kay->l2_mka); 3551 kay->l2_mka = NULL; 3552 } 3553 3554 os_free(kay->ctx); 3555 os_free(kay); 3556 } 3557 3558 3559 static const char * mode_txt(enum mka_created_mode mode) 3560 { 3561 switch (mode) { 3562 case PSK: 3563 return "PSK"; 3564 case EAP_EXCHANGE: 3565 return "EAP"; 3566 } 3567 3568 return "?"; 3569 } 3570 3571 3572 /** 3573 * ieee802_1x_kay_create_mka - 3574 */ 3575 struct ieee802_1x_mka_participant * 3576 ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, 3577 const struct mka_key_name *ckn, 3578 const struct mka_key *cak, u32 life, 3579 enum mka_created_mode mode, Boolean is_authenticator) 3580 { 3581 struct ieee802_1x_mka_participant *participant; 3582 unsigned int usecs; 3583 3584 wpa_printf(MSG_DEBUG, 3585 "KaY: Create MKA (ifname=%s mode=%s authenticator=%s)", 3586 kay->if_name, mode_txt(mode), yes_no(is_authenticator)); 3587 3588 if (!kay || !ckn || !cak) { 3589 wpa_printf(MSG_ERROR, "KaY: ckn or cak is null"); 3590 return NULL; 3591 } 3592 3593 if (cak->len != 16 && cak->len != 32) { 3594 wpa_printf(MSG_ERROR, "KaY: Unexpected CAK length %u", 3595 (unsigned int) cak->len); 3596 return NULL; 3597 } 3598 if (ckn->len > MAX_CKN_LEN) { 3599 wpa_printf(MSG_ERROR, "KaY: CKN is out of range (>32 bytes)"); 3600 return NULL; 3601 } 3602 if (!kay->enable) { 3603 wpa_printf(MSG_ERROR, "KaY: Now is at disable state"); 3604 return NULL; 3605 } 3606 3607 participant = os_zalloc(sizeof(*participant)); 3608 if (!participant) { 3609 wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__); 3610 return NULL; 3611 } 3612 3613 participant->ckn.len = ckn->len; 3614 os_memcpy(participant->ckn.name, ckn->name, ckn->len); 3615 wpa_hexdump(MSG_DEBUG, "KaY: CKN", participant->ckn.name, 3616 participant->ckn.len); 3617 participant->cak.len = cak->len; 3618 os_memcpy(participant->cak.key, cak->key, cak->len); 3619 wpa_hexdump_key(MSG_DEBUG, "KaY: CAK", participant->cak.key, 3620 participant->cak.len); 3621 if (life) 3622 participant->cak_life = life + time(NULL); 3623 3624 switch (mode) { 3625 case EAP_EXCHANGE: 3626 if (is_authenticator) { 3627 participant->is_obliged_key_server = TRUE; 3628 participant->can_be_key_server = TRUE; 3629 participant->is_key_server = TRUE; 3630 participant->principal = TRUE; 3631 3632 os_memcpy(&kay->key_server_sci, &kay->actor_sci, 3633 sizeof(kay->key_server_sci)); 3634 kay->key_server_priority = kay->actor_priority; 3635 participant->is_elected = TRUE; 3636 } else { 3637 participant->is_obliged_key_server = FALSE; 3638 participant->can_be_key_server = FALSE; 3639 participant->is_key_server = FALSE; 3640 participant->is_elected = TRUE; 3641 } 3642 break; 3643 3644 default: 3645 participant->is_obliged_key_server = FALSE; 3646 participant->can_be_key_server = TRUE; 3647 participant->is_key_server = TRUE; 3648 participant->is_elected = FALSE; 3649 break; 3650 } 3651 3652 participant->cached = FALSE; 3653 3654 participant->active = FALSE; 3655 participant->participant = FALSE; 3656 participant->retain = FALSE; 3657 participant->activate = DEFAULT; 3658 3659 if (participant->is_key_server) 3660 participant->principal = TRUE; 3661 3662 dl_list_init(&participant->live_peers); 3663 dl_list_init(&participant->potential_peers); 3664 3665 participant->retry_count = 0; 3666 participant->kay = kay; 3667 3668 if (!reset_participant_mi(participant)) 3669 goto fail; 3670 wpa_printf(MSG_DEBUG, "KaY: Selected random MI: %s", 3671 mi_txt(participant->mi)); 3672 3673 participant->lrx = FALSE; 3674 participant->ltx = FALSE; 3675 participant->orx = FALSE; 3676 participant->otx = FALSE; 3677 participant->to_dist_sak = FALSE; 3678 participant->to_use_sak = FALSE; 3679 participant->new_sak = FALSE; 3680 dl_list_init(&participant->sak_list); 3681 participant->new_key = NULL; 3682 dl_list_init(&participant->rxsc_list); 3683 participant->txsc = ieee802_1x_kay_init_transmit_sc(&kay->actor_sci); 3684 secy_cp_control_protect_frames(kay, kay->macsec_protect); 3685 secy_cp_control_replay(kay, kay->macsec_replay_protect, 3686 kay->macsec_replay_window); 3687 if (secy_create_transmit_sc(kay, participant->txsc)) 3688 goto fail; 3689 3690 /* to derive KEK from CAK and CKN */ 3691 participant->kek.len = participant->cak.len; 3692 if (mka_alg_tbl[kay->mka_algindex].kek_trfm(participant->cak.key, 3693 participant->cak.len, 3694 participant->ckn.name, 3695 participant->ckn.len, 3696 participant->kek.key, 3697 participant->kek.len)) { 3698 wpa_printf(MSG_ERROR, "KaY: KEK derivation failed"); 3699 goto fail; 3700 } 3701 wpa_hexdump_key(MSG_DEBUG, "KaY: Derived KEK", 3702 participant->kek.key, participant->kek.len); 3703 3704 /* to derive ICK from CAK and CKN */ 3705 participant->ick.len = participant->cak.len; 3706 if (mka_alg_tbl[kay->mka_algindex].ick_trfm(participant->cak.key, 3707 participant->cak.len, 3708 participant->ckn.name, 3709 participant->ckn.len, 3710 participant->ick.key, 3711 participant->ick.len)) { 3712 wpa_printf(MSG_ERROR, "KaY: ICK derivation failed"); 3713 goto fail; 3714 } 3715 wpa_hexdump_key(MSG_DEBUG, "KaY: Derived ICK", 3716 participant->ick.key, participant->ick.len); 3717 3718 dl_list_add(&kay->participant_list, &participant->list); 3719 3720 usecs = os_random() % (kay->mka_hello_time * 1000); 3721 eloop_register_timeout(0, usecs, ieee802_1x_participant_timer, 3722 participant, NULL); 3723 3724 /* Disable MKA lifetime for PSK mode. 3725 * The peer(s) can take a long time to come up, because we 3726 * create a "standby" MKA, and we need it to remain live until 3727 * some peer appears. 3728 */ 3729 if (mode != PSK) { 3730 participant->mka_life = MKA_LIFE_TIME / 1000 + time(NULL) + 3731 usecs / 1000000; 3732 } 3733 participant->mode = mode; 3734 3735 return participant; 3736 3737 fail: 3738 os_free(participant->txsc); 3739 os_free(participant); 3740 return NULL; 3741 } 3742 3743 3744 /** 3745 * ieee802_1x_kay_delete_mka - 3746 */ 3747 void 3748 ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn) 3749 { 3750 struct ieee802_1x_mka_participant *participant; 3751 struct ieee802_1x_kay_peer *peer; 3752 struct data_key *sak; 3753 struct receive_sc *rxsc; 3754 3755 if (!kay || !ckn) 3756 return; 3757 3758 wpa_printf(MSG_DEBUG, "KaY: participant removed"); 3759 3760 /* get the participant */ 3761 participant = ieee802_1x_kay_get_participant(kay, ckn->name, ckn->len); 3762 if (!participant) { 3763 wpa_hexdump(MSG_DEBUG, "KaY: participant is not found", 3764 ckn->name, ckn->len); 3765 return; 3766 } 3767 3768 eloop_cancel_timeout(ieee802_1x_participant_timer, participant, NULL); 3769 dl_list_del(&participant->list); 3770 3771 /* remove live peer */ 3772 while (!dl_list_empty(&participant->live_peers)) { 3773 peer = dl_list_entry(participant->live_peers.next, 3774 struct ieee802_1x_kay_peer, list); 3775 dl_list_del(&peer->list); 3776 os_free(peer); 3777 } 3778 3779 /* remove potential peer */ 3780 while (!dl_list_empty(&participant->potential_peers)) { 3781 peer = dl_list_entry(participant->potential_peers.next, 3782 struct ieee802_1x_kay_peer, list); 3783 dl_list_del(&peer->list); 3784 os_free(peer); 3785 } 3786 3787 /* remove sak */ 3788 while (!dl_list_empty(&participant->sak_list)) { 3789 sak = dl_list_entry(participant->sak_list.next, 3790 struct data_key, list); 3791 dl_list_del(&sak->list); 3792 ieee802_1x_kay_deinit_data_key(sak); 3793 } 3794 while (!dl_list_empty(&participant->rxsc_list)) { 3795 rxsc = dl_list_entry(participant->rxsc_list.next, 3796 struct receive_sc, list); 3797 ieee802_1x_kay_deinit_receive_sc(participant, rxsc); 3798 } 3799 ieee802_1x_kay_deinit_transmit_sc(participant, participant->txsc); 3800 3801 os_memset(&participant->cak, 0, sizeof(participant->cak)); 3802 os_memset(&participant->kek, 0, sizeof(participant->kek)); 3803 os_memset(&participant->ick, 0, sizeof(participant->ick)); 3804 os_free(participant); 3805 } 3806 3807 3808 /** 3809 * ieee802_1x_kay_mka_participate - 3810 */ 3811 void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay, 3812 struct mka_key_name *ckn, 3813 Boolean status) 3814 { 3815 struct ieee802_1x_mka_participant *participant; 3816 3817 if (!kay || !ckn) 3818 return; 3819 3820 participant = ieee802_1x_kay_get_participant(kay, ckn->name, ckn->len); 3821 if (!participant) 3822 return; 3823 3824 participant->active = status; 3825 } 3826 3827 3828 /** 3829 * ieee802_1x_kay_new_sak - 3830 */ 3831 int 3832 ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay) 3833 { 3834 struct ieee802_1x_mka_participant *participant; 3835 3836 if (!kay) 3837 return -1; 3838 3839 participant = ieee802_1x_kay_get_principal_participant(kay); 3840 if (!participant) 3841 return -1; 3842 3843 participant->new_sak = TRUE; 3844 wpa_printf(MSG_DEBUG, "KaY: new SAK signal"); 3845 3846 return 0; 3847 } 3848 3849 3850 /** 3851 * ieee802_1x_kay_change_cipher_suite - 3852 */ 3853 int 3854 ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, 3855 unsigned int cs_index) 3856 { 3857 struct ieee802_1x_mka_participant *participant; 3858 enum macsec_cap secy_cap; 3859 3860 if (!kay) 3861 return -1; 3862 3863 if (cs_index >= CS_TABLE_SIZE) { 3864 wpa_printf(MSG_ERROR, 3865 "KaY: Configured cipher suite index is out of range"); 3866 return -1; 3867 } 3868 if (kay->macsec_csindex == cs_index) 3869 return -2; 3870 3871 if (cs_index == 0) 3872 kay->macsec_desired = FALSE; 3873 3874 kay->macsec_csindex = cs_index; 3875 kay->macsec_capable = cipher_suite_tbl[kay->macsec_csindex].capable; 3876 3877 if (secy_get_capability(kay, &secy_cap) < 0) 3878 return -3; 3879 3880 if (kay->macsec_capable > secy_cap) 3881 kay->macsec_capable = secy_cap; 3882 3883 participant = ieee802_1x_kay_get_principal_participant(kay); 3884 if (participant) { 3885 wpa_printf(MSG_INFO, "KaY: Cipher Suite changed"); 3886 participant->new_sak = TRUE; 3887 } 3888 3889 return 0; 3890 } 3891 3892 3893 #ifdef CONFIG_CTRL_IFACE 3894 3895 /** 3896 * ieee802_1x_kay_get_status - Get IEEE 802.1X KaY status details 3897 * @sm: Pointer to KaY allocated with ieee802_1x_kay_init() 3898 * @buf: Buffer for status information 3899 * @buflen: Maximum buffer length 3900 * @verbose: Whether to include verbose status information 3901 * Returns: Number of bytes written to buf. 3902 * 3903 * Query KaY status information. This function fills in a text area with current 3904 * status information. If the buffer (buf) is not large enough, status 3905 * information will be truncated to fit the buffer. 3906 */ 3907 int ieee802_1x_kay_get_status(struct ieee802_1x_kay *kay, char *buf, 3908 size_t buflen) 3909 { 3910 char *pos, *end; 3911 int res, count; 3912 struct ieee802_1x_mka_participant *p; 3913 3914 if (!kay) 3915 return 0; 3916 3917 pos = buf; 3918 end = buf + buflen; 3919 3920 res = os_snprintf(pos, end - pos, 3921 "PAE KaY status=%s\n" 3922 "Authenticated=%s\n" 3923 "Secured=%s\n" 3924 "Failed=%s\n" 3925 "Actor Priority=%u\n" 3926 "Key Server Priority=%u\n" 3927 "Is Key Server=%s\n" 3928 "Number of Keys Distributed=%u\n" 3929 "Number of Keys Received=%u\n" 3930 "MKA Hello Time=%u\n", 3931 kay->active ? "Active" : "Not-Active", 3932 kay->authenticated ? "Yes" : "No", 3933 kay->secured ? "Yes" : "No", 3934 kay->failed ? "Yes" : "No", 3935 kay->actor_priority, 3936 kay->key_server_priority, 3937 kay->is_key_server ? "Yes" : "No", 3938 kay->dist_kn - 1, 3939 kay->rcvd_keys, 3940 kay->mka_hello_time); 3941 if (os_snprintf_error(buflen, res)) 3942 return 0; 3943 pos += res; 3944 3945 res = os_snprintf(pos, end - pos, 3946 "actor_sci=%s\n", sci_txt(&kay->actor_sci)); 3947 if (os_snprintf_error(buflen, res)) 3948 return end - pos; 3949 pos += res; 3950 3951 res = os_snprintf(pos, end - pos, 3952 "key_server_sci=%s\n", sci_txt(&kay->key_server_sci)); 3953 if (os_snprintf_error(buflen, res)) 3954 return end - pos; 3955 pos += res; 3956 3957 count = 0; 3958 dl_list_for_each(p, &kay->participant_list, 3959 struct ieee802_1x_mka_participant, list) { 3960 char *pos2 = pos; 3961 3962 res = os_snprintf(pos2, end - pos2, "participant_idx=%d\nckn=", 3963 count); 3964 if (os_snprintf_error(buflen, res)) 3965 return end - pos; 3966 pos2 += res; 3967 count++; 3968 3969 pos2 += wpa_snprintf_hex(pos2, end - pos2, p->ckn.name, 3970 p->ckn.len); 3971 3972 res = os_snprintf(pos2, end - pos2, 3973 "\nmi=%s\n" 3974 "mn=%u\n" 3975 "active=%s\n" 3976 "participant=%s\n" 3977 "retain=%s\n" 3978 "live_peers=%u\n" 3979 "potential_peers=%u\n" 3980 "is_key_server=%s\n" 3981 "is_elected=%s\n", 3982 mi_txt(p->mi), p->mn, 3983 yes_no(p->active), 3984 yes_no(p->participant), 3985 yes_no(p->retain), 3986 dl_list_len(&p->live_peers), 3987 dl_list_len(&p->potential_peers), 3988 yes_no(p->is_key_server), 3989 yes_no(p->is_elected)); 3990 if (os_snprintf_error(buflen, res)) 3991 return end - pos; 3992 pos2 += res; 3993 pos = pos2; 3994 } 3995 3996 return pos - buf; 3997 } 3998 3999 4000 static const char * true_false(Boolean val) 4001 { 4002 return val ? "true" : "false"; 4003 } 4004 4005 4006 static const char * activate_control_txt(enum activate_ctrl activate) 4007 { 4008 switch (activate) { 4009 case DEFAULT: 4010 return "default"; 4011 case DISABLED: 4012 return "disabled"; 4013 case ON_OPER_UP: 4014 return "onOperUp"; 4015 case ALWAYS: 4016 return "always"; 4017 } 4018 4019 return "?"; 4020 } 4021 4022 4023 static char * mka_mib_peer(struct dl_list *peers, Boolean live, char *buf, 4024 char *end) 4025 { 4026 char *pos = buf; 4027 struct ieee802_1x_kay_peer *p; 4028 int res; 4029 4030 dl_list_for_each(p, peers, struct ieee802_1x_kay_peer, list) { 4031 res = os_snprintf(pos, end - pos, 4032 "ieee8021XKayMkaPeerListMI=%s\n" 4033 "ieee8021XKayMkaPeerListMN=%u\n" 4034 "ieee8021XKayMkaPeerListType=%u\n" 4035 "ieee8021XKayMkaPeerListSCI=%s\n", 4036 mi_txt(p->mi), 4037 p->mn, 4038 live ? 1 : 2, 4039 sci_txt(&p->sci)); 4040 if (os_snprintf_error(end - pos, res)) 4041 return pos; 4042 pos += res; 4043 } 4044 4045 return pos; 4046 } 4047 4048 4049 int ieee802_1x_kay_get_mib(struct ieee802_1x_kay *kay, char *buf, 4050 size_t buflen) 4051 { 4052 char *pos, *end; 4053 int res; 4054 struct ieee802_1x_mka_participant *p; 4055 4056 if (!kay) 4057 return 0; 4058 4059 pos = buf; 4060 end = buf + buflen; 4061 4062 dl_list_for_each(p, &kay->participant_list, 4063 struct ieee802_1x_mka_participant, list) { 4064 char *pos2 = pos; 4065 4066 res = os_snprintf(pos2, end - pos2, "ieee8021XKayMkaPartCKN="); 4067 if (os_snprintf_error(buflen, res)) 4068 return end - pos; 4069 pos2 += res; 4070 4071 pos2 += wpa_snprintf_hex(pos2, end - pos2, p->ckn.name, 4072 p->ckn.len); 4073 4074 res = os_snprintf(pos2, end - pos2, 4075 "\nieee8021XKayMkaPartCached=%s\n" 4076 "ieee8021XKayMkaPartActive=%s\n" 4077 "ieee8021XKayMkaPartRetain=%s\n" 4078 "ieee8021XKayMkaPartActivateControl=%s\n" 4079 "ieee8021XKayMkaPartPrincipal=%s\n", 4080 true_false(p->cached), 4081 true_false(p->active), 4082 true_false(p->retain), 4083 activate_control_txt(p->activate), 4084 true_false(p->principal)); 4085 if (os_snprintf_error(buflen, res)) 4086 return end - pos; 4087 pos2 += res; 4088 pos = pos2; 4089 4090 pos = mka_mib_peer(&p->live_peers, TRUE, pos, end); 4091 pos = mka_mib_peer(&p->potential_peers, FALSE, pos, end); 4092 } 4093 4094 return pos - buf; 4095 } 4096 4097 #endif /* CONFIG_CTRL_IFACE */ 4098