55#define LOG_MODULE "EDHOC"
56#define LOG_LEVEL LOG_LEVEL_EDHOC
58#if HASH_LEN != SHA_256_DIGEST_LENGTH
59#error Only SHA256 supported. Please update HASH_LEN.
64MEMB(edhoc_context_storage, edhoc_context_t, 1);
75 edhoc_context_t *ctx =
memb_alloc(&edhoc_context_storage);
77 memset(ctx, 0,
sizeof(edhoc_context_t));
92 ctx->config.suite_num = 0;
93 if(EDHOC_SUPPORTED_SUITE_4 > -1) {
94 ctx->config.suite[ctx->config.suite_num] = EDHOC_SUPPORTED_SUITE_4;
95 ctx->config.suite_num++;
97 if(EDHOC_SUPPORTED_SUITE_3 > -1) {
98 ctx->config.suite[ctx->config.suite_num] = EDHOC_SUPPORTED_SUITE_3;
99 ctx->config.suite_num++;
101 if(EDHOC_SUPPORTED_SUITE_2 > -1) {
102 ctx->config.suite[ctx->config.suite_num] = EDHOC_SUPPORTED_SUITE_2;
103 ctx->config.suite_num++;
108 ctx->config.suite_num++;
111 if(ctx->config.suite_num == 0) {
119get_edhoc_mac_len(uint8_t ciphersuite_id)
121 switch(ciphersuite_id) {
122 case EDHOC_CIPHERSUITE_1:
123 case EDHOC_CIPHERSUITE_3:
124 case EDHOC_CIPHERSUITE_4:
125 case EDHOC_CIPHERSUITE_5:
126 case EDHOC_CIPHERSUITE_6:
127 case EDHOC_CIPHERSUITE_24:
128 case EDHOC_CIPHERSUITE_25:
129 return EDHOC_MAC_LEN_16;
130 case EDHOC_CIPHERSUITE_0:
131 case EDHOC_CIPHERSUITE_2:
132 return EDHOC_MAC_LEN_8;
134 LOG_ERR(
"Invalid cipher suite for MAC length (%d)\n",
141get_edhoc_aead_enc_alg(uint8_t ciphersuite_id)
143 switch(ciphersuite_id) {
144 case EDHOC_CIPHERSUITE_1:
145 case EDHOC_CIPHERSUITE_3:
146 return COSE_ALG_AES_CCM_16_128_128;
147 case EDHOC_CIPHERSUITE_0:
148 case EDHOC_CIPHERSUITE_2:
149 return COSE_ALG_AES_CCM_16_64_128;
151 LOG_ERR(
"Invalid cipher suite for encryption alg (%d)\n",
158get_edhoc_curve(uint8_t ciphersuite_id)
160 switch(ciphersuite_id) {
161 case EDHOC_CIPHERSUITE_2:
162 case EDHOC_CIPHERSUITE_3:
163 case EDHOC_CIPHERSUITE_5:
164 return EDHOC_CURVE_P256;
172get_edhoc_sign_alg(uint8_t ciphersuite_id)
174 switch(ciphersuite_id) {
175 case EDHOC_CIPHERSUITE_2:
176 case EDHOC_CIPHERSUITE_3:
177 case EDHOC_CIPHERSUITE_5:
178 case EDHOC_CIPHERSUITE_6:
181 LOG_ERR(
"Invalid cipher suite for curve (%d)\n",
190 if((ctx->config.ecdh_curve = get_edhoc_curve(suite)) == 0) {
194 if((ctx->config.mac_len = get_edhoc_mac_len(ctx->state.suite_selected)) == 0) {
198 if((ctx->config.aead_alg = get_edhoc_aead_enc_alg(ctx->state.suite_selected)) == 0) {
202 if((ctx->config.sign_alg = get_edhoc_sign_alg(ctx->state.suite_selected)) == 0) {
244 LOG_DBG(
"kid (%i bytes): ", cose->kid_sz);
245 LOG_DBG_BYTES(cose->kid, cose->kid_sz);
267generate_info(uint8_t info_label,
const uint8_t *context, uint8_t context_sz,
268 uint8_t length, uint8_t *info,
size_t info_sz)
280 uint8_t *msg, uint16_t msg_sz)
283 uint8_t h[CBOR_BYTE_STRING_SIZE(HASH_LEN) + CBOR_BYTE_STRING_SIZE(ECC_KEY_LEN)];
287 uint8_t msg_1_hash[HASH_LEN];
288 sha_256_hash(msg + 1, msg_sz - 1, msg_1_hash);
300 sha_256_hash(h, h_buf_sz, ctx->state.th);
307 const uint8_t *plaintext, uint16_t plaintext_sz)
310 uint16_t required_size = CBOR_BYTE_STRING_SIZE(HASH_LEN) + plaintext_sz + cred_sz;
312 LOG_ERR(
"Buffer sizes exceed maximum allowed\n");
329 sha_256_hash(h, h_sz, ctx->state.th);
336 const uint8_t *plaintext, uint16_t plaintext_sz)
339 uint16_t required_size = CBOR_BYTE_STRING_SIZE(HASH_LEN) + plaintext_sz + cred_sz;
341 LOG_ERR(
"Buffer sizes exceed maximum allowed\n");
360 sha_256_hash(h, h_sz, ctx->state.th);
373edhoc_kdf(
const uint8_t *prk, uint8_t info_label,
const uint8_t *context,
374 uint8_t context_sz, uint16_t length, uint8_t *result)
376 LOG_DBG(
"edhoc_kdf label=%d, length=%d\n", info_label, length);
377 LOG_DBG(
"PRK (%d bytes): ", ECC_KEY_LEN);
378 LOG_DBG_BYTES(prk, ECC_KEY_LEN);
380 if(context && context_sz > 0) {
381 LOG_DBG(
"Context (%d bytes): ", context_sz);
382 LOG_DBG_BYTES(context, context_sz);
386 uint8_t info_buf[CBOR_UNSIGNED_SIZE((
unsigned)info_label)
387 + CBOR_BYTE_STRING_SIZE((
unsigned)context_sz)
388 + CBOR_UNSIGNED_SIZE((
unsigned)length)];
389 uint16_t info_sz = generate_info(info_label, context, context_sz,
390 length, info_buf,
sizeof(info_buf));
392 LOG_ERR(
"Error generating INFO\n");
396 int16_t ret =
edhoc_expand(prk, info_buf, info_sz, length, result);
398 LOG_DBG(
"KDF Result (%d bytes): ", length);
399 LOG_DBG_BYTES(result, length);
407 uint16_t length, uint8_t *result)
409 LOG_DBG(
"INFO for HKDF_Expand (%d bytes): ", info_sz);
410 LOG_DBG_BYTES(info, info_sz);
418 uint8_t mac_len, uint8_t *mac)
420 if(mac_num == EDHOC_MAC_2) {
421 LOG_DBG(
"Calculating MAC_2\n");
424 CBOR_BYTE_STRING_SIZE(HASH_LEN) + ctx->buffers.cred_x_sz];
431 LOG_DBG(
"C_R (%d bytes): ", ctx->state.cid_rx_len);
432 LOG_DBG_BYTES(ctx->state.cid_rx, ctx->state.cid_rx_len);
436 LOG_DBG(
"C_R (%d bytes): ", ctx->state.cid_len);
437 LOG_DBG_BYTES(ctx->state.cid, ctx->state.cid_len);
442 LOG_DBG(
"ID_CRED_X (%zu bytes): ", ctx->buffers.id_cred_x_sz);
443 LOG_DBG_BYTES(ctx->buffers.id_cred_x, ctx->buffers.id_cred_x_sz);
447 LOG_DBG(
"TH_2 for MAC_2 (%d bytes): ", HASH_LEN);
448 LOG_DBG_BYTES(ctx->state.th, HASH_LEN);
452 LOG_DBG(
"CRED_X (%zu bytes): ", ctx->buffers.cred_x_sz);
453 LOG_DBG_BYTES(ctx->buffers.cred_x, ctx->buffers.cred_x_sz);
457 LOG_DBG(
"CONTEXT_2 (%zu bytes): ", context_2_buffer_size);
458 LOG_DBG_BYTES(context_2, context_2_buffer_size);
462 int16_t err =
edhoc_kdf(ctx->state.prk_3e2m, MAC_2_LABEL,
463 context_2, context_2_buffer_size, mac_len, mac);
465 LOG_ERR(
"Failed to expand MAC_2\n");
468 }
else if(mac_num == EDHOC_MAC_3) {
470 uint8_t context_3[ctx->buffers.id_cred_x_sz +
471 CBOR_BYTE_STRING_SIZE(HASH_LEN) + ctx->buffers.cred_x_sz];
479 LOG_DBG(
"CONTEXT_3 (%zu bytes): ", context_3_buffer_size);
480 LOG_DBG_BYTES(context_3, context_3_buffer_size);
484 int16_t err =
edhoc_kdf(ctx->state.prk_4e3m, MAC_3_LABEL,
485 context_3, context_3_buffer_size, mac_len, mac);
487 LOG_ERR(
"Failed to expand MAC_3\n");
491 LOG_ERR(
"Wrong MAC value\n");
498#if (EDHOC_METHOD == EDHOC_METHOD3) || INITIATOR_METHOD1 || RESPONDER_METHOD2
500check_mac(
const edhoc_context_t *ctx,
const uint8_t *received_mac,
501 uint16_t received_mac_sz)
505 mac_num = EDHOC_MAC_2;
507 mac_num = EDHOC_MAC_3;
510 uint8_t edhoc_mac_len = ctx->config.mac_len;
511 uint8_t mac[edhoc_mac_len];
513 LOG_ERR(
"Set MAC error\n");
517 LOG_DBG(
"Received MAC (%d): ", (
int)received_mac_sz);
518 LOG_DBG_BYTES(received_mac, received_mac_sz);
521 LOG_DBG(
"Recalculated MAC (%d): ", (
int)edhoc_mac_len);
522 LOG_DBG_BYTES(mac, edhoc_mac_len);
526 uint16_t mac_sz = edhoc_mac_len;
528 for(
int i = 0; i < edhoc_mac_len; i++) {
529 diff |= (mac[i] ^ received_mac[i]);
544 uint8_t ikm[ECC_KEY_LEN];
547 ctx->creds.ephemeral_key.priv, ikm)) {
548 LOG_ERR(
"Failed to generate shared secret for PRK_2e\n");
553 sha_256_hkdf_extract(ctx->state.th, HASH_LEN, ikm, ECC_KEY_LEN,
563 int err =
edhoc_kdf(ctx->state.prk_2e, KEYSTREAM_2_LABEL,
564 ctx->state.th, HASH_LEN, length, ks_2e);
572#if (EDHOC_METHOD == EDHOC_METHOD3) || INITIATOR_METHOD1 || RESPONDER_METHOD2
576 uint8_t grx[ECC_KEY_LEN];
591 ctx->creds.ephemeral_key.priv,
595 LOG_ERR(
"Failed to generate shared secret for PRK_3e2m\n");
602 uint8_t salt[HASH_LEN];
603 int16_t err =
edhoc_kdf(ctx->state.prk_2e, SALT_3E2M_LABEL, ctx->state.th,
604 HASH_LEN, HASH_LEN, salt);
606 LOG_ERR(
"Error calculating SALT_3e2m (%d)\n", err);
611 sha_256_hkdf_extract(salt, HASH_LEN, grx, ECC_KEY_LEN, ctx->state.prk_3e2m);
617#if (EDHOC_METHOD == EDHOC_METHOD2) || (EDHOC_METHOD == EDHOC_METHOD3) || INITIATOR_METHOD1 || RESPONDER_METHOD2
621 uint8_t giy[ECC_KEY_LEN];
627 ctx->creds.ephemeral_key.priv,
636 LOG_ERR(
"Failed to generate shared secret for PRK_4e3m\n");
639 LOG_DBG(
"G_IY (ECDH shared secret) (%d bytes): ", ECC_KEY_LEN);
640 LOG_DBG_BYTES(giy, ECC_KEY_LEN);
644 uint8_t salt[HASH_LEN];
645 int16_t err =
edhoc_kdf(ctx->state.prk_3e2m, SALT_4E3M_LABEL, ctx->state.th,
646 HASH_LEN, HASH_LEN, salt);
648 LOG_ERR(
"Error calculating SALT_4e3m (%d)\n", err);
651 LOG_DBG(
"SALT_4e3m (%d bytes): ", HASH_LEN);
652 LOG_DBG_BYTES(salt, HASH_LEN);
655 sha_256_hkdf_extract(salt, HASH_LEN, giy, ECC_KEY_LEN, ctx->state.prk_4e3m);
656 LOG_DBG(
"PRK_4e3m (%d bytes): ", HASH_LEN);
657 LOG_DBG_BYTES(ctx->state.prk_4e3m, HASH_LEN);
666 uint8_t *plaintext, uint16_t plaintext_sz)
668 LOG_DBG(
"Cipher/Plaintext (%d bytes): ", plaintext_sz);
669 LOG_DBG_BYTES(plaintext, plaintext_sz);
672 LOG_DBG(
"**** ks_2e in enc func (%d bytes): ", plaintext_sz);
673 LOG_DBG_BYTES(ks_2e, plaintext_sz);
676 for(
int i = 0; i < plaintext_sz; i++) {
677 plaintext[i] = plaintext[i] ^ ks_2e[i];
680 LOG_DBG(
"Plain/Ciphertext (%d bytes): ", plaintext_sz);
681 LOG_DBG_BYTES(plaintext, plaintext_sz);
697 ctx->creds.authen_key = key;
705#ifdef EDHOC_CID_BYTES
708 const uint8_t cid_bytes[] = EDHOC_CID_BYTES;
709 ctx->state.cid_len =
sizeof(cid_bytes);
711 LOG_ERR(
"CID length (%d) exceeds maximum (%d)\n", ctx->state.cid_len,
EDHOC_MAX_CID_LEN);
714 memcpy(ctx->state.cid, cid_bytes, ctx->state.cid_len);
715 LOG_INFO(
"Variable CID initialized: length %d bytes\n", ctx->state.cid_len);
716 LOG_DBG(
"Variable CID bytes: ");
717 for(
int i = 0; i < ctx->state.cid_len; i++) {
718 LOG_DBG_(
"%02x ", ctx->state.cid[i]);
726 LOG_INFO(
"Default CID: 0x%02x (len %d)\n", ctx->state.cid[0], ctx->state.cid_len);
745#ifdef EDHOC_AUTH_SUBJECT_NAME
747 strlen(EDHOC_AUTH_SUBJECT_NAME), key) == EDHOC_SUCCESS) {
751 LOG_ERR(
"Auth key identity not found\n");
757 uint8_t key_id[
sizeof(int)];
758 int kid = EDHOC_AUTH_KID;
759 int quotient = (EDHOC_AUTH_KID) / 256;
760 uint8_t key_id_sz = 1;
761 while(quotient != 0) {
765 memcpy(key_id, (uint8_t *)&kid, key_id_sz);
767 LOG_DBG(
"Looking for auth key KID 0x%02x (sz=%d)\n", key_id[0], key_id_sz);
771 LOG_DBG(
"Auth key found with KID 0x%02x\n", key_id[0]);
774 LOG_ERR(
"Does not contain a key for the key ID 0x%02x\n", key_id[0]);
779 LOG_ERR(
"No matching key found in the storage\n");
785 const edhoc_context_t *ctx, int8_t err)
787 edhoc_msg_error_t msg;
788 memset(&msg, 0,
sizeof(edhoc_msg_error_t));
789 msg.err_code = EDHOC_MSG_ERR_CODE_UNSPECIFIED_ERROR;
792 msg.info.tstr.err_info =
"Unknown error";
795 msg.err_code = EDHOC_MSG_ERR_CODE_WRONG_CIPHER_SUITE;
796 msg.info.suites.suites_num = MIN(
sizeof(msg.info.suites.suites), ctx->config.suite_num);
797 memcpy(msg.info.suites.suites, ctx->config.suite, msg.info.suites.suites_num);
800 msg.info.tstr.err_info =
"Malformed message";
803 msg.info.tstr.err_info =
"Method not supported";
806 msg.info.tstr.err_info =
"Invalid connection ID";
809 msg.info.tstr.err_info =
"Wrong connection ID";
812 msg.info.tstr.err_info =
"Malformed credential ID";
815 msg.info.tstr.err_info =
"Authentication failed";
818 msg.info.tstr.err_info =
"Decryption failed";
821 msg.info.tstr.err_info =
"Internal error";
824 msg.info.tstr.err_info =
"Identity not allowed";
828 msg.err_code = EDHOC_MSG_ERR_CODE_UNKNOWN_CREDENTIAL_SELECTION;
833 msg.info.tstr.err_info =
"Network timeout";
836 msg.info.tstr.err_info =
"Message correlation error";
839 msg.info.tstr.err_info =
"Message sequence error";
842 msg.info.tstr.err_info =
"Buffer overflow";
845 msg.info.tstr.err_info =
"Critical EAD item cannot be processed";
848 LOG_ERR(
"ERR MSG (%d): ", msg.err_code);
849 if(msg.err_code == EDHOC_MSG_ERR_CODE_UNSPECIFIED_ERROR) {
850 msg.info.tstr.err_info_sz = strlen(msg.info.tstr.err_info);
851 LOG_ERR_STRING(msg.info.tstr.err_info, msg.info.tstr.err_info_sz);
852 }
else if(msg.err_code == EDHOC_MSG_ERR_CODE_WRONG_CIPHER_SUITE) {
853 LOG_ERR(
"Wrong cipher suite, proposing %d suites", msg.info.suites.suites_num);
854 }
else if(msg.err_code == EDHOC_MSG_ERR_CODE_UNKNOWN_CREDENTIAL_SELECTION) {
855 LOG_ERR(
"Unknown credential referenced");
860 LOG_DBG(
"ERR MSG CBOR: ");
861 LOG_DBG_BYTES(msg_er, err_sz);
870 uint8_t *plaintext_ptr = NULL;
871 size_t parse_size = ctx->buffers.plaintext_sz;
875 cbor_init_reader(&skip_reader, ctx->buffers.plaintext, ctx->buffers.plaintext_sz);
879 parse_size = ctx->buffers.plaintext_sz - (plaintext_ptr - ctx->buffers.plaintext);
881 plaintext_ptr = ctx->buffers.plaintext;
895 LOG_ERR(
"Failed to parse ID_CRED_X (error: %d)\n", key_result);
900 uint8_t *received_mac = NULL;
901 uint16_t received_mac_sz =
edhoc_get_sign(&reader, &received_mac);
902 if(received_mac_sz == 0) {
903 LOG_ERR(
"Failed to parse signature/MAC: invalid CBOR\n");
912 LOG_WARN(
"Failed to parse additional data\n");
921 sizeof(ctx->buffers.cred_x));
922 LOG_DBG(
"CRED_X auth (%zu): ", ctx->buffers.cred_x_sz);
923 LOG_DBG_BYTES(ctx->buffers.cred_x, ctx->buffers.cred_x_sz);
926 ctx->buffers.id_cred_x_sz =
928 sizeof(ctx->buffers.id_cred_x));
929 LOG_DBG(
"ID_CRED_X auth (%zu): ", ctx->buffers.id_cred_x_sz);
930 LOG_DBG_BYTES(ctx->buffers.id_cred_x, ctx->buffers.id_cred_x_sz);
933#if (EDHOC_METHOD == EDHOC_METHOD3) || INITIATOR_METHOD1 || RESPONDER_METHOD2
941 if(check_mac(ctx, received_mac, received_mac_sz) == 0) {
947#if (EDHOC_METHOD == EDHOC_METHOD0) || INITIATOR_METHOD2 || RESPONDER_METHOD1
950 memcpy(ctx->state.prk_3e2m, ctx->state.prk_2e, HASH_LEN);
953 memcpy(ctx->state.prk_4e3m, ctx->state.prk_3e2m, HASH_LEN);
965 if(external_aad_sz == 0) {
966 LOG_ERR(
"Failed to encode external AAD for COSE_Sign1 verification\n");
971 uint8_t mac_num = msg2 ? EDHOC_MAC_2 : EDHOC_MAC_3;
972 uint8_t mac[HASH_LEN];
974 LOG_DBG(
"MAC_%d (%d bytes): ", msg2 ? 2 : 3, HASH_LEN);
975 LOG_DBG_BYTES(mac, HASH_LEN);
978 uint8_t other_public_key[ECC_KEY_LEN * 2];
979 memcpy(other_public_key, key->ecc.pub.x, ECC_KEY_LEN);
980 memcpy(other_public_key + ECC_KEY_LEN, key->ecc.pub.y, ECC_KEY_LEN);
983 ctx->buffers.id_cred_x, ctx->buffers.id_cred_x_sz,
984 external_aad, external_aad_sz,
986 received_mac, received_mac_sz)) {
987 LOG_ERR(
"COSE_Sign1 signature verification failed\n");
996 ctx->buffers.plaintext, ctx->buffers.plaintext_sz);
1006 LOG_ERR(
"Cannot print config summary: NULL context\n");
1010 LOG_INFO(
"\n=== EDHOC Session Configuration ===\n");
1011 LOG_INFO(
"Role: %s\n", ctx->config.role == EDHOC_INITIATOR ?
"Initiator" :
"Responder");
1012 LOG_INFO(
"Method: %d\n", ctx->config.method);
1013 LOG_INFO(
"Suite Selected: %d\n", ctx->state.suite_selected);
1014 LOG_INFO(
"ECDH Curve: %s\n", ctx->config.ecdh_curve == 1 ?
"P-256" :
"Unknown");
1015 LOG_INFO(
"AEAD Algorithm: %d\n", ctx->config.aead_alg);
1016 LOG_INFO(
"MAC Length: %d\n", ctx->config.mac_len);
1018 if(ctx->creds.authen_key != NULL) {
1019 LOG_INFO(
"Own Authentication Key: KID=%02x, Identity=%.*s\n",
1020 ctx->creds.authen_key->kid[0],
1021 ctx->creds.authen_key->identity_sz,
1022 ctx->creds.authen_key->identity);
1024 LOG_INFO(
"Own Authentication Key: Not set\n");
1027 LOG_INFO(
"Own Connection ID: ");
1028 if(ctx->state.cid_len > 0) {
1029 for(
int i = 0; i < ctx->state.cid_len; i++) {
1030 LOG_INFO_(
"%02x", ctx->state.cid[i]);
1034 LOG_INFO_(
"Not set\n");
1037 LOG_INFO(
"Peer Connection ID: ");
1038 if(ctx->state.cid_rx_len > 0) {
1039 for(
int i = 0; i < ctx->state.cid_rx_len; i++) {
1040 LOG_INFO_(
"%02x", ctx->state.cid_rx[i]);
1044 LOG_INFO_(
"Not set\n");
1047 LOG_INFO(
"===================================\n");
Public API declarations for COSE (RFC 9052).
bool ecdh_generate_ikm(uint8_t curve_id, const uint8_t *peer_x, const uint8_t *private_key, uint8_t *ikm)
Computes an ECDH shared secret.
EDHOC configuration file.
@ EDHOC_ERR_CRYPTO_DECRYPT
Decryption operation failed.
@ EDHOC_ERR_CREDENTIAL_NOT_FOUND
Credential not found.
@ EDHOC_ERR_NETWORK_TIMEOUT
Network operation timeout.
@ EDHOC_ERR_ID_CRED_MALFORMED
Malformed credential identifier.
@ EDHOC_ERR_CRITICAL_EAD_UNSUPPORTED
Critical EAD item cannot be processed (RFC 9528 Section 6).
@ EDHOC_ERR_INTERNAL_ERROR
Internal implementation error.
@ EDHOC_ERR_WRONG_CID
Wrong connection identifier.
@ EDHOC_ERR_CRYPTO_AUTHENTICATION
Authentication failed.
@ EDHOC_ERR_KEY_NOT_FOUND
Key not found in storage.
@ EDHOC_ERR_BUFFER_OVERFLOW
Buffer overflow detected.
@ EDHOC_ERR_SUITE_NOT_SUPPORTED
Cipher suite not supported.
@ EDHOC_ERR_MSG_MALFORMED
Malformed message received.
@ EDHOC_ERR_CORRELATION
Message correlation error.
@ EDHOC_ERR_CID_INVALID
Invalid connection identifier.
@ EDHOC_ERR_NOT_ALLOWED_IDENTITY
Identity not allowed.
@ EDHOC_ERR_METHOD_NOT_SUPPORTED
EDHOC method not supported.
@ EDHOC_ERR_SEQUENCE_ERROR
Message sequence error.
edhoc_error_t edhoc_check_key_list_kid(uint8_t *key_id, uint8_t key_id_size, cose_key_t **authentication_key)
Check in the keys repository for the key with the specific KID.
edhoc_error_t edhoc_check_key_list_identity(char *identity, uint8_t identity_size, cose_key_t **authentication_key)
Check in the keys repository for the key with the specific identity.
struct cose_key cose_key_t
KEY length in bytes.
size_t edhoc_serialize_err(const edhoc_msg_error_t *msg, unsigned char *buffer, size_t buffer_sz)
Serialize EDHOC error message to CBOR format.
const uint8_t * edhoc_read_byte_identifier(cbor_reader_state_t *reader, size_t *size)
Read byte identifier from CBOR reader.
uint8_t edhoc_get_ad(cbor_reader_state_t *reader, uint8_t *ad, size_t ad_buffer_size)
Parse Additional Data (AD) from CBOR reader.
int8_t edhoc_get_key_id_cred_x(cbor_reader_state_t *reader, uint8_t *out_id_cred_x, size_t id_cred_x_buffer_size, cose_key_t *key)
Parse ID_CRED_X from CBOR data and extract authentication key.
uint8_t edhoc_get_sign(cbor_reader_state_t *reader, uint8_t **sign)
Parse signature data from CBOR reader.
EDHOC message serialization and parsing API.
void edhoc_trace_transcript_hash(const char *th_label, const uint8_t *th_data, const uint8_t *input_data, size_t input_len)
Print transcript hash computation.
void edhoc_trace_session_summary(const edhoc_context_t *ctx)
Print session summary at protocol completion.
void edhoc_trace_prk_derivation(const char *prk_label, const uint8_t *prk_data, const uint8_t *salt_data, const uint8_t *ikm_data)
Print PRK derivation step.
EDHOC tracing and logging header.
#define EDHOC_TRACE_VALUE(label, data, len)
Print cryptographic value in RFC 9529 trace format.
#define EDHOC_TRACE_COMPUTE(description)
Print computation step description.
#define EDHOC_DBG_VALUE(label, data, len)
Print detailed debug value (only at DBG level).
An implementation of Ephemeral Diffie-Hellman Over COSE (EDHOC) (RFC9528).
bool cose_sign1_verify(int8_t alg, const uint8_t *public_key, const uint8_t *protected_hdr, size_t protected_hdr_len, const uint8_t *external_aad, size_t external_aad_len, const uint8_t *payload, size_t payload_len, const uint8_t *signature, size_t signature_len)
Verify a COSE_Sign1 signature.
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.
uint8_t edhoc_calc_mac(const edhoc_context_t *ctx, uint8_t mac_num, uint8_t mac_len, uint8_t *mac)
Calculate message authentication code (MAC).
uint8_t edhoc_setup_suites(edhoc_context_t *ctx)
Initialize the EDHOC Context with the defined EDHOC parameters.
size_t edhoc_generate_id_cred_x(const cose_key_t *cose, uint8_t *cred, size_t cred_sz)
Generate credential identifier ID_CRED_X.
bool edhoc_generate_prk_2e(edhoc_context_t *ctx)
Generate pseudorandom key PRK_2e.
uint8_t edhoc_get_own_auth_key(edhoc_context_t *ctx, cose_key_t **key)
Retrieve own authentication key from key storage.
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).
void edhoc_print_config_summary(const edhoc_context_t *ctx)
Print EDHOC session configuration summary.
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.
int16_t edhoc_expand(const uint8_t *prk, const uint8_t *info, uint16_t info_sz, uint16_t length, uint8_t *result)
HMAC-based Key Expansion Function for EDHOC context using HKDF (RFC 5869).
uint8_t edhoc_initialize_context(edhoc_context_t *ctx)
Internal API functions.
int edhoc_authenticate_msg(edhoc_context_t *ctx, uint8_t *ad, bool msg2)
Authenticate the rx message.
edhoc_context_t * edhoc_ctx
EDHOC context struct used in the EDHOC protocol.
void edhoc_storage_init(void)
Reserve memory for the EDHOC context struct.
bool edhoc_generate_prk_4e3m(edhoc_context_t *ctx, const ecc_key_t *auth_key, uint8_t gen)
Generate pseudorandom key PRK_4e3m.
bool edhoc_generate_prk_3e2m(edhoc_context_t *ctx, const ecc_key_t *auth_key, uint8_t gen)
Generate pseudorandom key PRK_3e2m.
uint8_t edhoc_generate_error_message(uint8_t *msg_er, size_t msg_er_sz, const edhoc_context_t *ctx, int8_t err)
Generate the EDHOC ERROR Message.
size_t edhoc_generate_cred_x(const cose_key_t *cose, uint8_t *cred, size_t cred_sz)
Generate CBOR-encoded credential CRED_X.
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 edhoc_finalize(edhoc_context_t *ctx)
Close the EDHOC context.
uint8_t edhoc_generate_transcript_hash_4(edhoc_context_t *ctx, const uint8_t *cred, uint16_t cred_sz, const uint8_t *plaintext, uint16_t plaintext_sz)
Generate transcript hash TH_4.
size_t cbor_end_writer(cbor_writer_state_t *state)
Finishes writing CBOR output.
size_t cbor_get_remaining(cbor_reader_state_t *state)
Gets the remaining bytes in the CBOR buffer.
void cbor_open_map(cbor_writer_state_t *state)
Adds subsequent entries to a map.
void cbor_write_text(cbor_writer_state_t *state, const char *text, size_t text_size)
Appends a text string.
void cbor_write_unsigned(cbor_writer_state_t *state, uint64_t value)
Appends an unsigned integer.
void cbor_close_map(cbor_writer_state_t *state)
Stops adding subsequent entries to the innermost map.
void cbor_write_object(cbor_writer_state_t *state, const void *object, size_t object_size)
Appends an arbitrary CBOR object.
void cbor_init_writer(cbor_writer_state_t *state, uint8_t *buffer, size_t buffer_size)
Prepares for writing CBOR output.
const uint8_t * cbor_get_position(cbor_reader_state_t *state)
Gets the current position in the CBOR buffer.
void cbor_init_reader(cbor_reader_state_t *state, const uint8_t *cbor, size_t cbor_size)
Prepares for reading CBOR input.
void cbor_write_data(cbor_writer_state_t *state, const uint8_t *data, size_t data_size)
Appends a byte string.
void cbor_write_signed(cbor_writer_state_t *state, int64_t value)
Appends a signed integer.
void sha_256_hkdf_expand(const uint8_t *prk, size_t prk_len, const uint8_t *info, size_t info_len, uint8_t *okm, uint_fast16_t okm_len)
Expands a key as per RFC 5869.
#define EDHOC_METHOD
Set the Authentication method.
#define EDHOC_DEFAULT_CID_LEN
Default CID length for backward compatibility.
#define EDHOC_MAX_CRED_LEN
Optimized buffer sizes for credentials based on COSE standard analysis CRED_X: 84-120 bytes typical →...
#define EDHOC_AUTHENT_TYPE
Set the authentication credential type/usage.
#define EDHOC_MAX_AD_SZ
The max length of the Application Data.
#define EDHOC_SUPPORTED_SUITE_1
Set EDHOC cipher suite config.
#define EDHOC_ROLE
Set the EDHOC Protocol role.
#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...
#define EDHOC_CID
Set EDHOC connection identifier.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
#define MEMB(name, structure, num)
Declare a memory block.
Header file for the logging system.
Platform-independent SHA-256 API.
Structure of the internal state of a CBOR reader.
Structure of the internal state of a CBOR writer.