The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
crypto.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/**
19 * $Id: 9b05bf9aac315a6593bdb0fdde778ea4442f119d $
20 *
21 * @file eap_psk/crypto.h
22 * @brief Constants, session state, and crypto declarations for EAP-PSK (RFC 4764)
23 *
24 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
25 */
26RCSIDH(eap_psk_crypto_h, "$Id: 9b05bf9aac315a6593bdb0fdde778ea4442f119d $")
27
28#include <freeradius-devel/eap/base.h>
29
30/*
31 * EAP-PSK (RFC 4764) is built entirely on AES-128, so every
32 * cryptographic value is 16 bytes.
33 */
34#define EAP_PSK_RAND_LEN 16 /* RAND_S and RAND_P */
35#define EAP_PSK_MAC_LEN 16 /* MAC_P and MAC_S (AES-CMAC tags) */
36#define EAP_PSK_PSK_LEN 16 /* the pre-shared key */
37#define EAP_PSK_AK_LEN 16 /* authentication key */
38#define EAP_PSK_KDK_LEN 16 /* key-derivation key */
39#define EAP_PSK_TEK_LEN 16 /* transient EAP key */
40#define EAP_PSK_MSK_LEN 64
41#define EAP_PSK_EMSK_LEN 64
42#define EAP_PSK_NONCE_LEN 4 /* the PCHANNEL nonce/counter, on the wire */
43#define EAP_PSK_TAG_LEN 16 /* EAX authentication tag */
44
45/*
46 * Flags field. The 2-bit T subfield (the message number) is in the two
47 * high-order bits.
48 */
49#define EAP_PSK_T_MASK 0xc0
50#define EAP_PSK_FLAGS_FIRST 0x00 /* T=0, first message (server -> peer) */
51#define EAP_PSK_FLAGS_SECOND 0x40 /* T=1, second message (peer -> server) */
52#define EAP_PSK_FLAGS_THIRD 0x80 /* T=2, third message (server -> peer) */
53#define EAP_PSK_FLAGS_FOURTH 0xc0 /* T=3, fourth message (peer -> server) */
54
55/*
56 * Protected result indication (R), the two high-order bits of the
57 * (encrypted) PCHANNEL payload byte. E (the extension bit) is the next
58 * bit; EAP-PSK standard authentication always sets E=0.
59 */
60#define EAP_PSK_R_CONT 1
61#define EAP_PSK_R_DONE_SUCCESS 2
62#define EAP_PSK_R_DONE_FAILURE 3
63
64#define EAP_PSK_R(_b) (((_b) >> 6) & 0x03)
65#define EAP_PSK_PAYLOAD(_r) (uint8_t)(((_r) & 0x03) << 6) /* R, E=0, Reserved=0 */
66
67/*
68 * The PCHANNEL for standard authentication: a 4-byte nonce, a 16-byte
69 * tag, and a single encrypted payload byte (R || E || Reserved).
70 */
71#define EAP_PSK_PCHANNEL_LEN (EAP_PSK_NONCE_LEN + EAP_PSK_TAG_LEN + 1)
72
73/*
74 * The EAX header authenticated by the protected channel is the first 22
75 * bytes of the EAP packet: the 4-byte EAP header, the 1-byte EAP Type,
76 * the 1-byte EAP-PSK Flags, and the 16-byte RAND_S.
77 */
78#define EAP_PSK_HEADER_LEN (4 + 1 + 1 + EAP_PSK_RAND_LEN)
79
80/*
81 * RFC 4764 Section 5.2 bounds ID_P (an NAI) at 966 bytes.
82 */
83#define EAP_PSK_MAX_ID_P_LEN 966
84
85typedef enum {
86 EAP_PSK_STATE_INIT = 0, /* nothing sent yet */
87 EAP_PSK_STATE_IDENTITY_REQUEST_SENT, /* first message sent, expecting the second */
88 EAP_PSK_STATE_RESULT_INDICATION_SENT, /* third message sent, expecting the fourth */
89 EAP_PSK_STATE_DONE, /* mutual authentication complete */
90 EAP_PSK_STATE_FAILED /* authentication failed */
92
93/*
94 * Kept in eap_session->opaque for the whole conversation. Allocated
95 * and written by the eap_psk process module; the rlm_eap_psk submodule
96 * only reads 'state' to derive the next Packet-Type.
97 */
98typedef struct {
100 unlang_result_t section_result; //!< Result of the last policy section.
101
102 char *id_s; //!< ID_S actually sent in the first message.
103 uint8_t *id_p; //!< ID_P the peer asserted in the second message.
104 size_t id_p_len;
105
108 uint8_t mac_p[EAP_PSK_MAC_LEN]; //!< As received, verified once the PSK is known.
109
110 uint8_t tek[EAP_PSK_TEK_LEN]; /* valid once the second message is processed */
114
115/*
116 * Key setup and session-key derivation (crypto.c). All return 0 on
117 * success, < 0 on (OpenSSL) failure.
118 */
120 uint8_t const psk[static EAP_PSK_PSK_LEN]);
121
123 uint8_t msk[static EAP_PSK_MSK_LEN],
124 uint8_t emsk[static EAP_PSK_EMSK_LEN],
125 uint8_t const kdk[static EAP_PSK_KDK_LEN],
126 uint8_t const rand_p[static EAP_PSK_RAND_LEN]);
127
128/*
129 * MAC_P = CMAC-AES-128(AK, ID_P || ID_S || RAND_S || RAND_P)
130 * MAC_S = CMAC-AES-128(AK, ID_S || RAND_P)
131 */
132int eap_psk_mac_p(uint8_t mac_p[static EAP_PSK_MAC_LEN],
133 uint8_t const ak[static EAP_PSK_AK_LEN],
134 uint8_t const *id_p, size_t id_p_len,
135 uint8_t const *id_s, size_t id_s_len,
136 uint8_t const rand_s[static EAP_PSK_RAND_LEN],
137 uint8_t const rand_p[static EAP_PSK_RAND_LEN]);
138
139int eap_psk_mac_s(uint8_t mac_s[static EAP_PSK_MAC_LEN],
140 uint8_t const ak[static EAP_PSK_AK_LEN],
141 uint8_t const *id_s, size_t id_s_len,
142 uint8_t const rand_p[static EAP_PSK_RAND_LEN]);
143
144/*
145 * The protected channel (EAX mode with AES-128, keyed with TEK). The
146 * nonce is the 4-byte counter (0 for the third message, 1 for the
147 * fourth); it is zero-padded to 16 bytes inside these functions.
148 * _decrypt() verifies the tag before decrypting, and returns < 0 if the
149 * tag is invalid.
150 */
152 uint8_t const tek[static EAP_PSK_TEK_LEN], uint32_t nonce,
153 uint8_t const *header, size_t header_len,
154 uint8_t const *plain, size_t plain_len);
155
157 uint8_t const tek[static EAP_PSK_TEK_LEN], uint32_t nonce,
158 uint8_t const *header, size_t header_len,
159 uint8_t const *cipher, size_t cipher_len,
160 uint8_t const tag[static EAP_PSK_TAG_LEN]);
#define RCSIDH(h, id)
Definition build.h:513
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.
Definition crypto.c:194
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)
Definition crypto.c:311
eap_psk_state_t
Definition crypto.h:85
@ EAP_PSK_STATE_FAILED
Definition crypto.h:90
@ EAP_PSK_STATE_INIT
Definition crypto.h:86
@ EAP_PSK_STATE_RESULT_INDICATION_SENT
Definition crypto.h:88
@ EAP_PSK_STATE_DONE
Definition crypto.h:89
@ EAP_PSK_STATE_IDENTITY_REQUEST_SENT
Definition crypto.h:87
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)
Definition crypto.c:395
#define EAP_PSK_TAG_LEN
Definition crypto.h:43
#define EAP_PSK_MAC_LEN
Definition crypto.h:35
#define EAP_PSK_TEK_LEN
Definition crypto.h:39
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)
Definition crypto.c:283
eap_psk_state_t state
Definition crypto.h:99
char * id_s
ID_S actually sent in the first message.
Definition crypto.h:102
#define EAP_PSK_PSK_LEN
Definition crypto.h:36
#define EAP_PSK_AK_LEN
Definition crypto.h:37
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.
Definition crypto.c:164
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)
Definition crypto.c:439
#define EAP_PSK_EMSK_LEN
Definition crypto.h:41
uint8_t * id_p
ID_P the peer asserted in the second message.
Definition crypto.h:103
#define EAP_PSK_MSK_LEN
Definition crypto.h:40
#define EAP_PSK_RAND_LEN
Definition crypto.h:34
unlang_result_t section_result
Result of the last policy section.
Definition crypto.h:100
size_t id_p_len
Definition crypto.h:104
#define EAP_PSK_KDK_LEN
Definition crypto.h:38
unsigned int uint32_t
unsigned char uint8_t