-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmka.h
More file actions
534 lines (430 loc) · 15.3 KB
/
Copy pathmka.h
File metadata and controls
534 lines (430 loc) · 15.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
/*
* mka.h
*
* Lightweight MACsec stack
* MACsec Key Agreement protocol layer.
* This file contains the MKA protocol logic used to build, parse and process
* MKA-related protocol data structures required for MACsec key management.
*
* Copyright (c) 2026 Michal Sarnovsky
*
* SPDX-License-Identifier: MIT
*
* This file is part of the lightweight MACsec stack.
* See LICENSE file in the project root for full license text.
*/
#ifndef MACSEC_MKA_H
#define MACSEC_MKA_H
#include "macsec_common.h"
#include "mka_crypto.h"
/*
* Platform-provided random number generator.
*/
#include "port/port.h"
#ifdef __cplusplus
extern "C"
{
#endif
/******************************************************************************
* MKA protocol constants
*****************************************************************************/
#define MACSEC_MKA_ETHERTYPE_EAPOL 0x888Eu
#define MACSEC_MKA_EAPOL_TYPE_MKA 5u
#define MACSEC_MKA_EAPOL_VERSION_2010 3u
#define MACSEC_MKA_DST_LEN 6u
#define MACSEC_MKA_SRC_LEN 6u
#define MACSEC_MKA_SCI_LEN 8u
#define MACSEC_MKA_MI_LEN 12u
#define MACSEC_MKA_ICV_LEN 16u
#define MACSEC_MKA_CA_NAME_MAX_LEN 32u
#define MACSEC_MKA_MAX_FRAME_LEN 512u
#define MACSEC_FRAME_MAX_SA 4u
/******************************************************************************
* MKA participant state
*
* This state describes the MKA relationship with the peer. It does not by
* itself guarantee that the SAK has already been installed in frame_crypto.
*****************************************************************************/
typedef enum
{
/*
* Context has not yet completed initialization.
*/
MACSEC_MKA_STATE_INIT = 0,
/*
* Local participant is transmitting MKPDUs, but no valid authenticated
* peer has yet been discovered.
*/
MACSEC_MKA_STATE_WAIT_PEER,
/*
* A valid authenticated peer is known, but mutual peer-list recognition
* is not yet complete.
*/
MACSEC_MKA_STATE_PEER_DISCOVERED,
/*
* Mutual participant recognition is complete and Key Server election
* has a stable result.
*/
MACSEC_MKA_STATE_PEER_LIVE,
/*
* The MKA session has an active SAK confirmed between MKA and the
* MACsec data-plane.
*/
MACSEC_MKA_STATE_OPERATIONAL,
/*
* Unrecoverable protocol, cryptographic or internal state error.
*/
MACSEC_MKA_STATE_ERROR
} macsec_mka_state_t;
/******************************************************************************
* SAK origin and lifecycle
*****************************************************************************/
typedef enum
{
/*
* No SAK origin has been assigned.
*/
MACSEC_MKA_SAK_ORIGIN_NONE = 0,
/*
* SAK was generated locally because this participant is Key Server.
*/
MACSEC_MKA_SAK_ORIGIN_LOCAL_KEY_SERVER,
/*
* SAK was received from the remote Key Server in a Distributed SAK
* Parameter Set.
*/
MACSEC_MKA_SAK_ORIGIN_REMOTE_KEY_SERVER
} macsec_mka_sak_origin_t;
typedef enum
{
/*
* No valid SAK is currently known.
*/
MACSEC_MKA_SAK_STATE_NONE = 0,
/*
* SAK was generated locally or received and successfully unwrapped,
* but has not yet been handed to the MACsec data-plane.
*/
MACSEC_MKA_SAK_STATE_CANDIDATE,
/*
* Local Key Server has a SAK waiting to be included in a Distributed
* SAK Parameter Set.
*/
MACSEC_MKA_SAK_STATE_DISTRIBUTION_PENDING,
/*
* Local Key Server has successfully transmitted at least one MKPDU
* containing this Distributed SAK.
*/
MACSEC_MKA_SAK_STATE_DISTRIBUTED,
/*
* SAK has been handed to macsec.c and is waiting for confirmation that
* it was installed in frame_crypto.
*/
MACSEC_MKA_SAK_STATE_INSTALL_PENDING,
/*
* SAK is installed for all required local RX and TX directions.
*/
MACSEC_MKA_SAK_STATE_ACTIVE,
/*
* Active SAK has also been confirmed by the current peer through
* SAK Use.
*
* A peer identity change invalidates confirmation by that participant.
* When the local participant is Key Server, a replacement SAK is generated
* and the confirmed SAK becomes the old SAK during rekey.
*/
MACSEC_MKA_SAK_STATE_CONFIRMED,
/*
* SAK is retained for receive compatibility during rekey, but is no
* longer the current transmit key. It is removed after the current peer
* confirms use of the replacement latest SAK.
*/
MACSEC_MKA_SAK_STATE_RETIRING
} macsec_mka_sak_state_t;
/******************************************************************************
* MKA event flags
*
* Event flags report one-time protocol changes to macsec.c. Persistent state
* remains stored in macsec_mka_ctx_t and macsec_mka_sak_t.
*****************************************************************************/
typedef uint32_t macsec_mka_event_flags_t;
#define MACSEC_MKA_EVENT_NONE 0x00000000u
/*
* Peer lifecycle events.
*/
#define MACSEC_MKA_EVENT_PEER_DISCOVERED 0x00000001u
#define MACSEC_MKA_EVENT_PEER_LIVE 0x00000002u
#define MACSEC_MKA_EVENT_PEER_LOST 0x00000004u
/*
* Key Server election event.
*/
#define MACSEC_MKA_EVENT_KEY_SERVER_CHANGED 0x00000008u
/*
* SAK lifecycle events.
*/
#define MACSEC_MKA_EVENT_SAK_AVAILABLE 0x00000010u
#define MACSEC_MKA_EVENT_SAK_DISTRIBUTED 0x00000020u
#define MACSEC_MKA_EVENT_SAK_ACTIVE 0x00000040u
#define MACSEC_MKA_EVENT_SAK_CONFIRMED 0x00000080u
#define MACSEC_MKA_EVENT_SAK_RETIRED 0x00000100u
/*
* MKA requests removal of old_sak from the MACsec data-plane.
*
* macsec.c must remove the corresponding RX/TX Secure Association and then
* confirm completion through macsec_mka_notify_sak_retired().
*/
#define MACSEC_MKA_EVENT_SAK_RETIRE_REQUIRED 0x00000200u
/*
* Control-frame scheduling events.
*/
#define MACSEC_MKA_EVENT_TX_INITIAL 0x00001000u
#define MACSEC_MKA_EVENT_TX_PERIODIC 0x00002000u
#define MACSEC_MKA_EVENT_TX_PEER_CHANGE 0x00004000u
#define MACSEC_MKA_EVENT_TX_KEY_SERVER_CHANGE 0x00008000u
#define MACSEC_MKA_EVENT_TX_DISTRIBUTE_SAK 0x00010000u
#define MACSEC_MKA_EVENT_TX_SAK_USE 0x00020000u
/*
* Rekey and error events.
*/
#define MACSEC_MKA_EVENT_REKEY_REQUIRED 0x00100000u
#define MACSEC_MKA_EVENT_ERROR 0x80000000u
/******************************************************************************
* MKA transmit reasons
*
* These flags describe why an MKPDU must be transmitted.
* Individual reasons can be retained or cleared separately.
*****************************************************************************/
typedef uint32_t macsec_mka_tx_reason_flags_t;
#define MACSEC_MKA_TX_REASON_NONE 0x00000000u
#define MACSEC_MKA_TX_REASON_INITIAL 0x00000001u
#define MACSEC_MKA_TX_REASON_PERIODIC 0x00000002u
#define MACSEC_MKA_TX_REASON_PEER_CHANGE 0x00000004u
#define MACSEC_MKA_TX_REASON_KEY_SERVER_CHANGE 0x00000008u
#define MACSEC_MKA_TX_REASON_DISTRIBUTE_SAK 0x00000010u
#define MACSEC_MKA_TX_REASON_SAK_USE 0x00000020u
#define MACSEC_MKA_TX_REASON_REKEY 0x00000040u
/******************************************************************************
* SAK installation directions
*****************************************************************************/
typedef uint8_t macsec_mka_install_directions_t;
#define MACSEC_MKA_INSTALL_NONE 0x00u
#define MACSEC_MKA_INSTALL_RX 0x01u
#define MACSEC_MKA_INSTALL_TX 0x02u
/******************************************************************************
* Parsed MKA Basic Parameter Set
*****************************************************************************/
typedef struct
{
uint8_t dst_mac[MACSEC_MKA_DST_LEN];
uint8_t src_mac[MACSEC_MKA_SRC_LEN];
uint8_t eapol_version;
uint8_t eapol_type;
uint16_t eapol_len;
uint8_t mka_version;
uint8_t key_server_priority;
macsec_bool_t key_server;
macsec_bool_t macsec_desired;
uint8_t macsec_capability;
uint16_t body_len;
uint8_t sci[MACSEC_MKA_SCI_LEN];
uint8_t actor_mi[MACSEC_MKA_MI_LEN];
uint32_t actor_mn;
uint32_t algorithm_agility;
uint8_t cak_name[MACSEC_MKA_CA_NAME_MAX_LEN];
size_t cak_name_len;
uint8_t icv[MACSEC_MKA_ICV_LEN];
} macsec_mka_basic_t;
/******************************************************************************
* MKA peer
*****************************************************************************/
typedef struct
{
macsec_bool_t valid;
uint8_t mac[MACSEC_MKA_SRC_LEN];
uint8_t sci[MACSEC_MKA_SCI_LEN];
uint8_t mi[MACSEC_MKA_MI_LEN];
uint32_t mn;
uint8_t key_server_priority;
macsec_bool_t key_server;
macsec_bool_t macsec_desired;
uint8_t macsec_capability;
uint32_t last_seen_ms;
macsec_bool_t seen_in_peer_list;
macsec_bool_t live;
} macsec_mka_peer_t;
/******************************************************************************
* MKA SAK
*
* SAK validity is represented exclusively by lifecycle_state. A SAK in
* MACSEC_MKA_SAK_STATE_NONE contains no usable key material.
*****************************************************************************/
typedef struct
{
/*
* Secure Association Key.
*
* 16 bytes = AES-128 SAK
* 32 bytes = AES-256 SAK
*/
uint8_t sak[MACSEC_MKA_SAK_MAX_LEN];
size_t sak_len;
/*
* Association Number, valid range 0..3.
*/
uint8_t an;
/*
* MKA Key Number.
*/
uint32_t key_number;
/*
* SAK origin and lifecycle state.
*/
macsec_mka_sak_origin_t origin;
macsec_mka_sak_state_t lifecycle_state;
/*
* Installation state reported by macsec.c.
*/
macsec_bool_t rx_installed;
macsec_bool_t tx_installed;
/*
* Confirmation reported by the current peer through SAK Use.
*
* For latest_sak, these flags describe confirmation of the current key.
* They are cleared when peer identity changes because a replacement
* participant must independently confirm possession and use of the new
* latest SAK.
*
* They are not used as validity flags and do not replace lifecycle_state.
*/
macsec_bool_t peer_rx_confirmed;
macsec_bool_t peer_tx_confirmed;
/*
* Lowest acceptable packet number associated with the active SAK.
*/
uint32_t lowest_pn;
} macsec_mka_sak_t;
/******************************************************************************
* Metadata describing a built MKPDU
*
* The metadata is later passed to macsec_mka_notify_tx_success() or
* macsec_mka_notify_tx_failure().
*****************************************************************************/
typedef struct
{
uint32_t message_number;
macsec_mka_tx_reason_flags_t reasons;
macsec_bool_t contains_peer_list;
macsec_bool_t contains_distributed_sak;
macsec_bool_t contains_sak_use;
uint32_t distributed_key_number;
uint8_t distributed_an;
} macsec_mka_tx_meta_t;
/******************************************************************************
* MKA context
*****************************************************************************/
typedef struct
{
/*
* MKA participant state.
*/
macsec_mka_state_t state;
macsec_mka_crypto_ctx_t crypto;
macsec_mka_peer_t peer;
macsec_mka_basic_t last_basic;
/*
* Current SAK being generated, distributed, installed or actively used.
*
* New control-plane distribution and new protected transmission always
* use latest_sak.
*/
macsec_mka_sak_t latest_sak;
/*
* Previous SAK retained temporarily during rekey.
*
* old_sak may remain installed for RX while latest_sak is distributed,
* installed and confirmed. It must not be distributed as a new SAK and
* must not be selected for new TX after latest_sak becomes active.
*/
macsec_mka_sak_t old_sak;
macsec_bool_t verify_icv;
macsec_bool_t last_icv_valid;
uint8_t mic_work[MACSEC_MKA_MAX_FRAME_LEN];
uint32_t last_rx_ms;
uint8_t local_mac[MACSEC_MKA_SRC_LEN];
uint8_t local_sci[MACSEC_MKA_SCI_LEN];
uint8_t local_mi[MACSEC_MKA_MI_LEN];
uint32_t local_mn;
uint8_t key_server_priority;
macsec_bool_t local_key_server;
macsec_bool_t macsec_desired;
uint8_t macsec_capability;
uint32_t key_server_next_key_number;
uint8_t key_server_next_an;
uint32_t tx_interval_ms;
uint32_t last_tx_ms;
uint32_t last_tick_ms;
macsec_mka_event_flags_t pending_events;
macsec_mka_tx_reason_flags_t tx_reasons;
} macsec_mka_ctx_t;
/******************************************************************************
* MKA protocol API
*****************************************************************************/
int macsec_mka_init(macsec_mka_ctx_t *ctx, const uint8_t *cak, size_t cak_len, const uint8_t *ckn,
size_t ckn_len, const uint8_t local_mac[MACSEC_MKA_SRC_LEN], uint16_t port_id,
uint8_t key_server_priority, uint32_t tx_interval_ms);
void macsec_mka_clear(macsec_mka_ctx_t *ctx);
macsec_mka_state_t macsec_mka_get_state(const macsec_mka_ctx_t *ctx);
int macsec_mka_tick(macsec_mka_ctx_t *ctx, uint32_t now_ms);
macsec_bool_t macsec_mka_is_eapol_mka(const uint8_t *frame, size_t frame_len);
int macsec_mka_parse_basic(const uint8_t *frame, size_t frame_len, macsec_mka_basic_t *out);
int macsec_mka_input(macsec_mka_ctx_t *ctx, const uint8_t *frame, size_t frame_len,
uint32_t now_ms);
int macsec_mka_verify_icv(macsec_mka_ctx_t *ctx, const uint8_t *frame, size_t frame_len,
const macsec_mka_basic_t *basic);
void macsec_mka_print_basic(const macsec_mka_basic_t *basic);
/*
* Return and atomically clear all currently pending MKA events.
*/
macsec_mka_event_flags_t macsec_mka_take_events(macsec_mka_ctx_t *ctx);
/*
* Build an MKPDU without yet committing the transmission as successful.
*/
int macsec_mka_build_tx_frame(macsec_mka_ctx_t *ctx, uint8_t *frame, size_t *frame_len,
size_t frame_max_len, macsec_mka_tx_meta_t *meta);
/*
* Notify MKA that the previously built MKPDU was successfully transmitted.
*/
int macsec_mka_notify_tx_success(macsec_mka_ctx_t *ctx, const macsec_mka_tx_meta_t *meta,
uint32_t now_ms);
/*
* Notify MKA that transmission of the previously built MKPDU failed.
*
* Required TX reasons remain scheduled for a later retry.
*/
void macsec_mka_notify_tx_failure(macsec_mka_ctx_t *ctx, const macsec_mka_tx_meta_t *meta);
/*
* Return a SAK that is ready for installation in the MACsec data-plane.
*
* On the first successful handoff, the lifecycle moves to INSTALL_PENDING.
* A SAK in INSTALL_PENDING may be returned again until all required RX and
* TX installation directions have been confirmed.
*/
int macsec_mka_take_sak_for_install(macsec_mka_ctx_t *ctx, macsec_mka_sak_t *sak);
/*
* Notify MKA which SAK directions were successfully installed in the
* MACsec data-plane.
*/
int macsec_mka_notify_sak_installed(macsec_mka_ctx_t *ctx, uint32_t key_number, uint8_t an,
macsec_mka_install_directions_t installed_directions,
uint32_t lowest_pn);
/*
* Notify MKA that old_sak has been removed from the MACsec data-plane.
*
* key_number and AN must identify the current old_sak. On success, old_sak is
* securely cleared and MACSEC_MKA_EVENT_SAK_RETIRED is raised.
*/
int macsec_mka_notify_sak_retired(macsec_mka_ctx_t *ctx, uint32_t key_number, uint8_t an);
#ifdef __cplusplus
}
#endif
#endif /* MACSEC_MKA_H */