1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP server/peer: EAP-PAX shared routines 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2005, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 18b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/sha1.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_pax_common.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_pax_kdf - PAX Key Derivation Function 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @key: Secret key (X) 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @key_len: Length of the secret key in bytes 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @identifier: Public identifier for the key (Y) 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @entropy: Exchanged entropy to seed the KDF (Z) 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @entropy_len: Length of the entropy in bytes 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @output_len: Output len in bytes (W) 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @output: Buffer for the derived key 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, -1 failed 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 4746, Section 2.6: PAX-KDF-W(X, Y, Z) 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_pax_kdf(u8 mac_id, const u8 *key, size_t key_len, 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *identifier, 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *entropy, size_t entropy_len, 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t output_len, u8 *output) 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 mac[SHA1_MAC_LEN]; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 counter, *pos; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr[3]; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len[3]; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t num_blocks, left; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt num_blocks = (output_len + EAP_PAX_MAC_LEN - 1) / EAP_PAX_MAC_LEN; 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (identifier == NULL || num_blocks >= 255) 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: add support for EAP_PAX_HMAC_SHA256_128 */ 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128) 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[0] = (const u8 *) identifier; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[0] = os_strlen(identifier); 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[1] = entropy; 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[1] = entropy_len; 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[2] = &counter; 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[2] = 1; 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = output; 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left = output_len; 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (counter = 1; counter <= (u8) num_blocks; counter++) { 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t clen = left > EAP_PAX_MAC_LEN ? EAP_PAX_MAC_LEN : left; 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha1_vector(key, key_len, 3, addr, len, mac); 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, mac, clen); 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += clen; 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= clen; 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_pax_mac - EAP-PAX MAC 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @key: Secret key 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @key_len: Length of the secret key in bytes 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data1: Optional data, first block; %NULL if not used 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data1_len: Length of data1 in bytes 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data2: Optional data, second block; %NULL if not used 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data2_len: Length of data2 in bytes 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data3: Optional data, third block; %NULL if not used 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data3_len: Length of data3 in bytes 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @mac: Buffer for the MAC value (EAP_PAX_MAC_LEN = 16 bytes) 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, -1 on failure 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Wrapper function to calculate EAP-PAX MAC. 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_pax_mac(u8 mac_id, const u8 *key, size_t key_len, 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *data1, size_t data1_len, 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *data2, size_t data2_len, 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *data3, size_t data3_len, 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *mac) 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 hash[SHA1_MAC_LEN]; 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr[3]; 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len[3]; 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t count; 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: add support for EAP_PAX_HMAC_SHA256_128 */ 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128) 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[0] = data1; 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[0] = data1_len; 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[1] = data2; 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[1] = data2_len; 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[2] = data3; 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[2] = data3_len; 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count = (data1 ? 1 : 0) + (data2 ? 1 : 0) + (data3 ? 1 : 0); 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha1_vector(key, key_len, count, addr, len, hash); 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(mac, hash, EAP_PAX_MAC_LEN); 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_pax_initial_key_derivation - EAP-PAX initial key derivation 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ak: Authentication Key 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @e: Entropy 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @mk: Buffer for the derived Master Key 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ck: Buffer for the derived Confirmation Key 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ick: Buffer for the derived Integrity Check Key 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, -1 on failure 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_pax_initial_key_derivation(u8 mac_id, const u8 *ak, const u8 *e, 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *mk, u8 *ck, u8 *ick) 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: initial key derivation"); 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_pax_kdf(mac_id, ak, EAP_PAX_AK_LEN, "Master Key", 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_MK_LEN, mk) || 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_pax_kdf(mac_id, mk, EAP_PAX_MK_LEN, "Confirmation Key", 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_CK_LEN, ck) || 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_pax_kdf(mac_id, mk, EAP_PAX_MK_LEN, "Integrity Check Key", 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_ICK_LEN, ick)) 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: AK", ak, EAP_PAX_AK_LEN); 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: MK", mk, EAP_PAX_MK_LEN); 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: CK", ck, EAP_PAX_CK_LEN); 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: ICK", ick, EAP_PAX_ICK_LEN); 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 151