50#define LOG_MODULE "EDHOC"
51#define LOG_LEVEL LOG_LEVEL_EDHOC
55decrypt_ciphertext_3(edhoc_context_t *ctx,
const uint8_t *ciphertext,
56 uint16_t ciphertext_size, uint8_t *plaintext)
58 uint8_t alg = ctx->config.aead_alg;
62 if(key_len == 0 || iv_len == 0 || tag_len == 0) {
67 LOG_ERR(
"CIPHERTEXT_3 size (%u) exceeds max buffer (%d)\n",
73 uint8_t key[COSE_MAX_KEY_LEN];
74 int16_t err =
edhoc_kdf(ctx->state.prk_3e2m, K_3_LABEL, ctx->state.th,
75 HASH_LEN, key_len, key);
77 LOG_ERR(
"Failed to derive K_3\n");
80 LOG_DBG(
"K_3 (%d bytes): ", key_len);
81 LOG_DBG_BYTES(key, key_len);
85 uint8_t nonce[COSE_MAX_IV_LEN];
86 err =
edhoc_kdf(ctx->state.prk_3e2m, IV_3_LABEL, ctx->state.th, HASH_LEN,
89 LOG_ERR(
"Failed to derive IV_3\n");
92 LOG_DBG(
"IV_3 (%d bytes): ", iv_len);
93 LOG_DBG_BYTES(nonce, iv_len);
98 memcpy(aead_buf, ciphertext, ciphertext_size);
100 ctx->state.th, HASH_LEN,
101 aead_buf, ciphertext_size);
102 if(plaintext_sz == 0) {
103 LOG_ERR(
"CIPHERTEXT_3 decryption failed\n");
107 memcpy(plaintext, aead_buf, plaintext_sz);
108 return (uint16_t)plaintext_sz;
112set_rx_cid(edhoc_context_t *ctx,
const uint8_t *received_cid,
size_t received_cid_size)
116 LOG_ERR(
"Invalid CID length: %zu (max %d)\n", received_cid_size,
EDHOC_MAX_CID_LEN);
120 memcpy(ctx->state.cid_rx, received_cid, received_cid_size);
121 ctx->state.cid_rx_len = (uint8_t)received_cid_size;
124 if(ctx->state.cid_rx_len == ctx->state.cid_len &&
125 memcmp(ctx->state.cid_rx, ctx->state.cid, ctx->state.cid_len) == 0) {
129 return EDHOC_SUCCESS;
133check_rx_suite_i(edhoc_context_t *ctx,
134 const uint8_t *received_suites, uint8_t suite_count)
136 if(suite_count == 0) {
140 uint8_t peer_selected_suite = received_suites[suite_count - 1];
143 for(uint8_t i = 0; i < ctx->config.suite_num; i++) {
144 if(ctx->config.suite[i] == peer_selected_suite) {
145 ctx->state.suite_selected = peer_selected_suite;
146 LOG_DBG(
"Selected cipher suite: %d\n", ctx->state.suite_selected);
151 LOG_WARN(
"Cipher suite not supported\n");
158 LOG_WARN(
"Cipher suite not supported\n");
163set_rx_gx(edhoc_context_t *ctx,
const uint8_t *gx)
165 memcpy(ctx->state.gx, gx, ECC_KEY_LEN);
169set_rx_method(edhoc_context_t *ctx, uint8_t method)
175 ctx->config.method = method;
180set_rx_msg(edhoc_context_t *ctx,
const uint8_t *message,
size_t message_size)
186 memcpy(ctx->buffers.msg_rx, message, message_size);
187 ctx->buffers.rx_sz = message_size;
195 edhoc_msg_error_t err;
199 switch(edhoc_msg_error_get_code(&err)) {
200 case EDHOC_MSG_ERR_CODE_UNSPECIFIED_ERROR:
201 LOG_ERR(
"RX MSG %u ERR %u: ", message, edhoc_msg_error_get_code(&err));
202 size_t info_sz = edhoc_msg_error_get_info_sz(&err);
205 LOG_ERR_STRING(edhoc_msg_error_get_info(&err), info_sz);
209 case EDHOC_MSG_ERR_CODE_WRONG_CIPHER_SUITE:
210 LOG_ERR(
"RX MSG %u ERROR WITH SUITE PROPOSE: ", message);
211 LOG_ERR_BYTES(edhoc_msg_error_get_suites(&err),
212 edhoc_msg_error_get_suites_num(&err));
215 case EDHOC_MSG_ERR_CODE_UNKNOWN_CREDENTIAL_SELECTION:
216 LOG_ERR(
"RX MSG %u ERROR: Unknown credential referenced\n", message);
224 return EDHOC_SUCCESS;
229 size_t payload_size, uint8_t *auth_data)
231 edhoc_msg_1_t msg1 = { 0 };
235 err = set_rx_msg(ctx, payload, payload_size);
242 if(error_status != EDHOC_SUCCESS) {
246 LOG_DBG(
"MSG1 (%d bytes): ", (
int)ctx->buffers.rx_sz - 1);
247 LOG_DBG_BYTES((ctx->buffers.msg_rx) + 1, ctx->buffers.rx_sz - 1);
250 ctx->buffers.rx_sz - 1);
252 LOG_ERR(
"MSG1 malformed\n");
257#if EDHOC_EAD_PROCESSING
260 if(msg1.uad.ead_value_sz > 0 || msg1.uad.ead_label != 0) {
262 if(ead_result != EDHOC_SUCCESS) {
263 LOG_ERR(
"EAD processing failed for MSG_1: %d\n", ead_result);
270 err = check_rx_suite_i(ctx, msg1.suites_i, msg1.suites_i_num);
272 LOG_ERR(
"Rx Suite not supported\n");
277 err = set_rx_cid(ctx, msg1.c_i, msg1.c_i_sz);
279 LOG_ERR(
"Not support cid rx\n");
284 err = set_rx_method(ctx, msg1.method);
286 LOG_ERR(
"Rx Method not supported\n");
291 set_rx_gx(ctx, msg1.g_x);
294 LOG_DBG(
"MSG EAD (%d)", (
int)msg1.uad.ead_value_sz);
295 LOG_DBG_STRING((
char *)msg1.uad.ead_value, msg1.uad.ead_value_sz);
298 if(msg1.uad.ead_value_sz != 0) {
300 LOG_ERR(
"EAD value size (%zu) exceeds max AD (%d)\n",
304 memcpy(auth_data, msg1.uad.ead_value, msg1.uad.ead_value_sz);
307 return msg1.uad.ead_value_sz;
312 uint8_t *payload,
size_t payload_size)
315 err = set_rx_msg(ctx, payload, payload_size);
320 if(error_status != EDHOC_SUCCESS) {
325 LOG_ERR(
"MSG2 malformed\n");
330 set_rx_gx(ctx, msg2->gy_ciphertext_2);
336 if(msg2->gy_ciphertext_2_sz <= ECC_KEY_LEN) {
337 LOG_ERR(
"Invalid ciphertext size: %zu <= %d\n", msg2->gy_ciphertext_2_sz, ECC_KEY_LEN);
340 int ciphertext2_sz = msg2->gy_ciphertext_2_sz - ECC_KEY_LEN;
342 LOG_ERR(
"Ciphertext size exceeds maximum buffer: %d > %d\n", ciphertext2_sz,
EDHOC_MAX_BUFFER);
349 memcpy(ctx->buffers.plaintext, msg2->gy_ciphertext_2 + ECC_KEY_LEN,
351 LOG_DBG(
"CIPHERTEXT_2 (%d bytes): ", ciphertext2_sz);
352 LOG_DBG_BYTES(ctx->buffers.plaintext, ciphertext2_sz);
357 ctx->buffers.plaintext,
359 ctx->buffers.plaintext_sz = plaint_sz;
360 LOG_DBG(
"PLAINTEXT_2 (%zu bytes): ", plaint_sz);
361 LOG_DBG_BYTES(ctx->buffers.plaintext, plaint_sz);
366 cbor_init_reader(&cid_reader, ctx->buffers.plaintext, ctx->buffers.plaintext_sz);
367 size_t cid_data_size;
370 LOG_ERR(
"Invalid C_R in plaintext_2: size %zu\n", cid_data_size);
373 err = set_rx_cid(ctx, cid_data, cid_data_size);
377 LOG_DBG(
"cid (%d bytes): ", ctx->state.cid_rx_len);
378 LOG_DBG_BYTES(ctx->state.cid_rx, ctx->state.cid_rx_len);
386 uint8_t *payload,
size_t payload_size)
389 int8_t err = set_rx_msg(ctx, payload, payload_size);
396 if(error_status != EDHOC_SUCCESS) {
402 ctx->buffers.rx_sz - 1);
404 LOG_ERR(
"MSG3 malformed\n");
409 LOG_DBG(
"CIPHERTEXT_3 (%d bytes): ", (
int)msg3->ciphertext_3_sz);
410 LOG_DBG_BYTES(msg3->ciphertext_3, msg3->ciphertext_3_sz);
415 ctx->buffers.plaintext, ctx->buffers.plaintext_sz);
418 uint16_t plaintext_sz = decrypt_ciphertext_3(ctx, msg3->ciphertext_3,
419 msg3->ciphertext_3_sz,
420 ctx->buffers.plaintext);
421 ctx->buffers.plaintext_sz = plaintext_sz;
422 if(plaintext_sz == 0) {
423 LOG_ERR(
"Error in decrypt ciphertext 3\n");
426 LOG_DBG(
"PLAINTEXT_3 (%d): ", (
int)plaintext_sz);
427 LOG_DBG_BYTES(ctx->buffers.plaintext, plaintext_sz);
Public API declarations for COSE (RFC 9052).
edhoc_error_t
Unified error type for EDHOC operations.
@ EDHOC_ERR_CRYPTO_DECRYPT
Decryption operation failed.
@ EDHOC_ERR_CREDENTIAL_NOT_FOUND
Credential not found.
@ EDHOC_ERR_SUITE_NOT_SUPPORTED
Cipher suite not supported.
@ EDHOC_ERR_MSG_MALFORMED
Malformed message received.
@ EDHOC_ERR_CID_INVALID
Invalid connection identifier.
@ EDHOC_ERR_METHOD_NOT_SUPPORTED
EDHOC method not supported.
Declarations for the EDHOC message handlers.
edhoc_error_t edhoc_deserialize_msg_1(edhoc_msg_1_t *msg, unsigned char *buffer, size_t buff_sz)
Deserialize EDHOC message 1 from CBOR data.
void print_msg_3(edhoc_msg_3_t *msg)
Print EDHOC message 3 contents for debugging.
void print_msg_1(edhoc_msg_1_t *msg)
Print EDHOC message 1 contents for debugging.
const uint8_t * edhoc_read_byte_identifier(cbor_reader_state_t *reader, size_t *size)
Read byte identifier from CBOR reader.
void print_msg_2(edhoc_msg_2_t *msg)
Print EDHOC message 2 contents for debugging.
edhoc_error_t edhoc_deserialize_msg_3(edhoc_msg_3_t *msg, unsigned char *buffer, size_t buff_sz)
Deserialize EDHOC message 3 from CBOR data.
edhoc_error_t edhoc_deserialize_msg_2(edhoc_msg_2_t *msg, unsigned char *buffer, size_t buff_sz)
Deserialize EDHOC message 2 from CBOR data.
edhoc_error_t edhoc_process_ead_item(const edhoc_ead_data_t *ead_data)
Process and validate EAD (External Authorization Data) items.
bool edhoc_deserialize_err(edhoc_msg_error_t *msg, const uint8_t *data, size_t data_size)
Deserialize EDHOC error message from CBOR data.
uint8_t cose_get_key_len(uint8_t alg_id)
Get the symmetric key length for a COSE AEAD algorithm.
size_t cose_encrypt0_open(uint8_t alg, const uint8_t *key, const uint8_t *nonce, const uint8_t *external_aad, size_t external_aad_len, uint8_t *buf, size_t ciphertext_len)
AEAD-decrypt a buffer in place as a COSE_Encrypt0.
uint8_t cose_get_iv_len(uint8_t alg_id)
Get the nonce/IV length for a COSE AEAD algorithm.
uint8_t cose_get_tag_len(uint8_t alg_id)
Get the authentication tag length for a COSE AEAD algorithm.
void edhoc_print_session_info(const edhoc_context_t *ctx)
Print current EDHOC session information for debugging.
int8_t edhoc_generate_transcript_hash_2(edhoc_context_t *ctx, const uint8_t *eph_pub, uint8_t *msg, uint16_t msg_sz)
Generate transcript hash TH_2.
int8_t edhoc_set_config_from_suite(edhoc_context_t *ctx, uint8_t suite)
Set EDHOC configuration parameters based on cipher suite.
bool edhoc_generate_prk_2e(edhoc_context_t *ctx)
Generate pseudorandom key PRK_2e.
int16_t edhoc_kdf(const uint8_t *prk, uint8_t info_label, const uint8_t *context, uint8_t context_sz, uint16_t length, uint8_t *result)
EDHOC Key Derivation Function (KDF) based on HMAC-based Expand (RFC 5869).
int16_t edhoc_enc_dec_ciphertext_2(const edhoc_context_t *ctx, const uint8_t *ks_2e, uint8_t *plaintext, uint16_t plaintext_sz)
Encrypt/decrypt ciphertext 2 using XOR with keystream.
uint8_t edhoc_generate_transcript_hash_3(edhoc_context_t *ctx, const uint8_t *cred, uint16_t cred_sz, const uint8_t *plaintext, uint16_t plaintext_sz)
Generate transcript hash TH_3.
int16_t edhoc_generate_keystream_2e(edhoc_context_t *ctx, uint16_t length, uint8_t *ks_2e)
Generate keystream KS_2e for encryption.
void cbor_init_reader(cbor_reader_state_t *state, const uint8_t *cbor, size_t cbor_size)
Prepares for reading CBOR input.
#define EDHOC_METHOD
Set the Authentication method.
int edhoc_handler_msg_3(edhoc_msg_3_t *msg3, edhoc_context_t *ctx, uint8_t *payload, size_t payload_size)
Handle the EDHOC Message 3 received.
#define EDHOC_MAX_AD_SZ
The max length of the Application Data.
int edhoc_handler_msg_1(edhoc_context_t *ctx, uint8_t *payload, size_t payload_size, uint8_t *auth_data)
Handle the EDHOC Message 1 received.
#define EDHOC_MAX_PAYLOAD_LEN
The max length of the EDHOC message.
int edhoc_handler_msg_2(edhoc_msg_2_t *msg2, edhoc_context_t *ctx, uint8_t *payload, size_t payload_size)
Handle the EDHOC Message 2 received.
edhoc_error_t edhoc_check_err_rx_msg(uint8_t message, const uint8_t *data, size_t data_size)
Try to deserialize data as an EDHOC error message.
#define EDHOC_MAX_BUFFER
The max size of the buffers.
#define EDHOC_MAX_CID_LEN
Maximum length of connection identifiers RFC 9528 allows variable-length CIDs including negative inte...
Header file for the logging system.
Structure of the internal state of a CBOR reader.