18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP server/peer: EAP-PAX shared routines 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_pax_common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_pax_kdf - PAX Key Derivation Function 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Secret key (X) 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_len: Length of the secret key in bytes 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @identifier: Public identifier for the key (Y) 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @entropy: Exchanged entropy to seed the KDF (Z) 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @entropy_len: Length of the entropy in bytes 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @output_len: Output len in bytes (W) 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @output: Buffer for the derived key 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 failed 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4746, Section 2.6: PAX-KDF-W(X, Y, Z) 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_pax_kdf(u8 mac_id, const u8 *key, size_t key_len, 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *identifier, 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *entropy, size_t entropy_len, 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t output_len, u8 *output) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac[SHA1_MAC_LEN]; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 counter, *pos; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[3]; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[3]; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_blocks, left; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_blocks = (output_len + EAP_PAX_MAC_LEN - 1) / EAP_PAX_MAC_LEN; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identifier == NULL || num_blocks >= 255) 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for EAP_PAX_HMAC_SHA256_128 */ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128) 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (const u8 *) identifier; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = os_strlen(identifier); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = entropy; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = entropy_len; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = &counter; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = 1; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = output; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = output_len; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (counter = 1; counter <= (u8) num_blocks; counter++) { 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t clen = left > EAP_PAX_MAC_LEN ? EAP_PAX_MAC_LEN : left; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(key, key_len, 3, addr, len, mac); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, mac, clen); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += clen; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= clen; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_pax_mac - EAP-PAX MAC 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Secret key 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_len: Length of the secret key in bytes 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data1: Optional data, first block; %NULL if not used 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data1_len: Length of data1 in bytes 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data2: Optional data, second block; %NULL if not used 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data2_len: Length of data2 in bytes 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data3: Optional data, third block; %NULL if not used 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data3_len: Length of data3 in bytes 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac: Buffer for the MAC value (EAP_PAX_MAC_LEN = 16 bytes) 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wrapper function to calculate EAP-PAX MAC. 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_pax_mac(u8 mac_id, const u8 *key, size_t key_len, 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data1, size_t data1_len, 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data2, size_t data2_len, 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data3, size_t data3_len, 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mac) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[3]; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[3]; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t count; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for EAP_PAX_HMAC_SHA256_128 */ 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128) 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = data1; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = data1_len; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = data2; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = data2_len; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = data3; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = data3_len; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = (data1 ? 1 : 0) + (data2 ? 1 : 0) + (data3 ? 1 : 0); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(key, key_len, count, addr, len, hash); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mac, hash, EAP_PAX_MAC_LEN); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_pax_initial_key_derivation - EAP-PAX initial key derivation 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ak: Authentication Key 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @e: Entropy 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mk: Buffer for the derived Master Key 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ck: Buffer for the derived Confirmation Key 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ick: Buffer for the derived Integrity Check Key 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_pax_initial_key_derivation(u8 mac_id, const u8 *ak, const u8 *e, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mk, u8 *ck, u8 *ick) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: initial key derivation"); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_pax_kdf(mac_id, ak, EAP_PAX_AK_LEN, "Master Key", 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_MK_LEN, mk) || 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_kdf(mac_id, mk, EAP_PAX_MK_LEN, "Confirmation Key", 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_CK_LEN, ck) || 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_kdf(mac_id, mk, EAP_PAX_MK_LEN, "Integrity Check Key", 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_ICK_LEN, ick)) 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: AK", ak, EAP_PAX_AK_LEN); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: MK", mk, EAP_PAX_MK_LEN); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: CK", ck, EAP_PAX_CK_LEN); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: ICK", ick, EAP_PAX_ICK_LEN); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 145