32RCSID(
"$Id: 1fe763077bf31b06022d32388b2df92719e33f7f $")
35#include <freeradius-devel/util/misc.h>
37#include <openssl/evp.h>
38#include <openssl/cmac.h>
39#include <openssl/crypto.h>
58 MEM(ctx = EVP_CIPHER_CTX_new());
64 if (EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL) != 1)
goto done;
65 EVP_CIPHER_CTX_set_padding(ctx, 0);
67 if (EVP_EncryptUpdate(ctx,
out, &len,
in, 16) != 1)
goto done;
68 if (EVP_EncryptFinal_ex(ctx,
out + len, &len) != 1)
goto done;
73 EVP_CIPHER_CTX_free(ctx);
100 MEM(ctx = EVP_CIPHER_CTX_new());
102 if (EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, ctr) != 1)
goto done;
104 if (EVP_EncryptUpdate(ctx,
out, &outl,
in, (
int) len) != 1)
goto done;
105 if (EVP_EncryptFinal_ex(ctx,
out + outl, &outl) != 1)
goto done;
110 EVP_CIPHER_CTX_free(ctx);
142 for (i = 1; i <=
count; i++) {
143 memcpy(block,
hash,
sizeof(block));
170 memset(input, 0,
sizeof(input));
237 uint8_t const *seg1,
size_t len1,
238 uint8_t const *seg2,
size_t len2,
239 uint8_t const *seg3,
size_t len3,
240 uint8_t const *seg4,
size_t len4)
246 MEM(ctx = CMAC_CTX_new());
248 if (CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL) != 1)
goto done;
250 if (seg1 && (len1 > 0) && (CMAC_Update(ctx, seg1, len1) != 1))
goto done;
251 if (seg2 && (len2 > 0) && (CMAC_Update(ctx, seg2, len2) != 1))
goto done;
252 if (seg3 && (len3 > 0) && (CMAC_Update(ctx, seg3, len3) != 1))
goto done;
253 if (seg4 && (len4 > 0) && (CMAC_Update(ctx, seg4, len4) != 1))
goto done;
255 if (CMAC_Final(ctx, mac, &maclen) != 1)
goto done;
256 if (maclen != 16)
goto done;
264DIAG_ON(deprecated-declarations)
285 uint8_t const *id_p,
size_t id_p_len,
286 uint8_t const *id_s,
size_t id_s_len,
313 uint8_t const *id_s,
size_t id_s_len,
343 memset(tweak, 0,
sizeof(tweak));
347 tweak,
sizeof(tweak),
363 memset(block, 0, 16);
364 block[12] = (
uint8_t) (nonce >> 24);
365 block[13] = (
uint8_t) (nonce >> 16);
366 block[14] = (
uint8_t) (nonce >> 8);
397 uint8_t const *header,
size_t header_len,
398 uint8_t const *plain,
size_t plain_len)
402 uint8_t n_omac[16], h_omac[16], c_omac[16];
406 if (
eap_psk_omac(n_omac, tek, 0, nonce_block,
sizeof(nonce_block)) < 0)
return -1;
407 if (
eap_psk_omac(h_omac, tek, 1, header, header_len) < 0)
return -1;
409 if ((plain_len > 0) &&
410 (
aes128_ctr(cipher, tek, n_omac, plain, plain_len) < 0))
return -1;
412 if (
eap_psk_omac(c_omac, tek, 2, cipher, plain_len) < 0)
return -1;
415 tag[i] = n_omac[i] ^ h_omac[i] ^ c_omac[i];
441 uint8_t const *header,
size_t header_len,
442 uint8_t const *cipher,
size_t cipher_len,
447 uint8_t n_omac[16], h_omac[16], c_omac[16];
452 if (
eap_psk_omac(n_omac, tek, 0, nonce_block,
sizeof(nonce_block)) < 0)
return -1;
453 if (
eap_psk_omac(h_omac, tek, 1, header, header_len) < 0)
return -1;
454 if (
eap_psk_omac(c_omac, tek, 2, cipher, cipher_len) < 0)
return -1;
457 want[i] = n_omac[i] ^ h_omac[i] ^ c_omac[i];
467 if ((cipher_len > 0) &&
468 (
aes128_ctr(plain, tek, n_omac, cipher, cipher_len) < 0))
return -1;
#define USES_APPLE_DEPRECATED_API
Constants, session state, and crypto declarations for EAP-PSK (RFC 4764)
int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL data.
int eap_psk_derive_keys(uint8_t tek[static EAP_PSK_TEK_LEN], uint8_t msk[static EAP_PSK_MSK_LEN], uint8_t emsk[static EAP_PSK_EMSK_LEN], uint8_t const kdk[static EAP_PSK_KDK_LEN], uint8_t const rand_p[static EAP_PSK_RAND_LEN])
Session-key derivation: expand RAND_P under KDK into nine output blocks.
int eap_psk_mac_s(uint8_t mac_s[static EAP_PSK_MAC_LEN], uint8_t const ak[static EAP_PSK_AK_LEN], uint8_t const *id_s, size_t id_s_len, uint8_t const rand_p[static EAP_PSK_RAND_LEN])
Compute MAC_S = CMAC-AES-128(AK, ID_S || RAND_P)
int eap_psk_pchannel_encrypt(uint8_t *cipher, uint8_t tag[static EAP_PSK_TAG_LEN], uint8_t const tek[static EAP_PSK_TEK_LEN], uint32_t nonce, uint8_t const *header, size_t header_len, uint8_t const *plain, size_t plain_len)
EAX encrypt for the protected channel (RFC 4764 Section 3.3)
static int eap_psk_omac(uint8_t out[static 16], uint8_t const key[static 16], uint8_t t, uint8_t const *data, size_t data_len)
The tweaked OMAC used by EAX: OMAC^t(M) = CMAC(K, [t]_16 || M)
int eap_psk_mac_p(uint8_t mac_p[static EAP_PSK_MAC_LEN], uint8_t const ak[static EAP_PSK_AK_LEN], uint8_t const *id_p, size_t id_p_len, uint8_t const *id_s, size_t id_s_len, uint8_t const rand_s[static EAP_PSK_RAND_LEN], uint8_t const rand_p[static EAP_PSK_RAND_LEN])
Compute MAC_P = CMAC-AES-128(AK, ID_P || ID_S || RAND_S || RAND_P)
static USES_APPLE_DEPRECATED_API int aes128_ecb_block(uint8_t out[static 16], uint8_t const key[static 16], uint8_t const in[static 16])
A single AES-128 ECB block encryption: out = AES-128(key, in)
int eap_psk_derive_ak_kdk(uint8_t ak[static EAP_PSK_AK_LEN], uint8_t kdk[static EAP_PSK_KDK_LEN], uint8_t const psk[static EAP_PSK_PSK_LEN])
Key setup: derive AK (counter 1) and KDK (counter 2) from the PSK.
static int aes128_ctr(uint8_t *out, uint8_t const key[static 16], uint8_t const ctr[static 16], uint8_t const *in, size_t len)
AES-128 in counter mode.
static int eap_psk_cmac(uint8_t mac[static 16], uint8_t const key[static 16], uint8_t const *seg1, size_t len1, uint8_t const *seg2, size_t len2, uint8_t const *seg3, size_t len3, uint8_t const *seg4, size_t len4)
AES-128 CMAC over one or more concatenated buffers.
int eap_psk_pchannel_decrypt(uint8_t *plain, uint8_t const tek[static EAP_PSK_TEK_LEN], uint32_t nonce, uint8_t const *header, size_t header_len, uint8_t const *cipher, size_t cipher_len, uint8_t const tag[static EAP_PSK_TAG_LEN])
EAX decrypt-and-verify for the protected channel (RFC 4764 Section 3.3)
static int eap_psk_counter_mode(uint8_t *out, uint8_t const key[static 16], uint8_t const input[static 16], size_t count)
The "modified counter mode" of RFC 4764 Sections 3.1 and 3.2.
static void eap_psk_nonce_block(uint8_t block[static 16], uint32_t nonce)
Build the 16-byte EAX nonce block from the 4-byte EAP-PSK Nonce N.
static unsigned int hash(char const *username, unsigned int tablesize)
static size_t char ** out