Contiki-NG
Loading...
Searching...
No Matches
edhoc-msg-generators.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024, RISE Research Institutes of Sweden AB
3 * Copyright (c) 2020, Industrial Systems Institute (ISI), Patras, Greece
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holder nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32/**
33 * \file
34 * EDHOC, an implementation of Ephemeral Diffie-Hellman Over COSE (EDHOC) (IETF RFC9528)
35 * \author
36 * Lidia Pocero <pocero@isi.gr>
37 * Peter A Jonsson
38 * Rikard Höglund
39 * Marco Tiloca
40 * Niclas Finne <niclas.finne@ri.se>
41 * Nicolas Tsiftes <nicolas.tsiftes@ri.se>
42 */
43
44#include "contiki.h"
45#include "lib/sha-256.h"
46#include "lib/cbor.h"
47#include "edhoc.h"
48#include "edhoc-config.h"
49#include "edhoc-msgs.h"
51#include "edhoc-error.h"
52#include "cose.h"
53#include <assert.h>
54
55#include "sys/log.h"
56#define LOG_MODULE "EDHOC"
57#define LOG_LEVEL LOG_LEVEL_EDHOC
58
59/*---------------------------------------------------------------------------*/
60static edhoc_error_t
61gen_mac(const edhoc_context_t *ctx, uint8_t mac_len, uint8_t *mac)
62{
63 if(ctx == NULL || mac == NULL) {
65 }
66
67 uint8_t mac_num;
68 if(EDHOC_ROLE == EDHOC_INITIATOR) {
69 mac_num = EDHOC_MAC_3;
70 } else if(EDHOC_ROLE == EDHOC_RESPONDER) {
71 mac_num = EDHOC_MAC_2;
72 } else {
74 }
75
76 if(!edhoc_calc_mac(ctx, mac_num, mac_len, mac)) {
77 LOG_ERR("Set MAC error\n");
79 }
80
81 return EDHOC_SUCCESS;
82}
83/*---------------------------------------------------------------------------*/
84static uint16_t
85gen_plaintext(edhoc_context_t *ctx, const uint8_t *auth_data, size_t auth_data_size,
86 bool msg2, const uint8_t *mac_or_signature,
87 uint8_t mac_or_signature_size,
88 uint8_t *plaintext_buffer, size_t plaintext_buffer_size)
89{
92
93 cbor_init_reader(&reader, ctx->buffers.id_cred_x, sizeof(ctx->buffers.id_cred_x));
94 cbor_init_writer(&writer, plaintext_buffer, plaintext_buffer_size);
95 if(msg2) {
96 edhoc_write_byte_identifier(&writer, ctx->state.cid, ctx->state.cid_len);
97 }
98
99 size_t num = cbor_read_map(&reader);
100 if(num == 1) {
101 uint64_t value;
102 cbor_read_unsigned(&reader, &value);
103 const uint8_t *data = cbor_read_data(&reader, &num);
104 if(!data || !num) {
105 LOG_ERR("error to get bytes\n");
106 return 0;
107 }
108 edhoc_write_byte_identifier(&writer, data, num);
109 } else {
110 cbor_write_object(&writer, ctx->buffers.id_cred_x, ctx->buffers.id_cred_x_sz);
111 }
112
113 cbor_write_data(&writer, mac_or_signature, mac_or_signature_size);
114 if(auth_data_size != 0) {
115 cbor_write_data(&writer, auth_data, auth_data_size);
116 }
117
118 size_t result = cbor_end_writer(&writer);
119 if(result == 0) {
120 LOG_ERR("CBOR encoding failed in plaintext_23 generation\n");
121 }
122 return result;
123}
124/*---------------------------------------------------------------------------*/
125static uint16_t
126gen_ciphertext_3(edhoc_context_t *ctx, const uint8_t *auth_data, uint16_t auth_data_size,
127 const uint8_t *mac_or_signature, uint16_t mac_or_signature_size,
128 uint8_t *ciphertext, size_t ciphertext_buffer_size)
129{
130 uint8_t alg = ctx->config.aead_alg;
131 uint8_t key_len = cose_get_key_len(alg);
132 uint8_t iv_len = cose_get_iv_len(alg);
133 uint8_t tag_len = cose_get_tag_len(alg);
134 if(key_len == 0 || iv_len == 0 || tag_len == 0) {
135 return 0;
136 }
137
138 uint8_t aead_buf[EDHOC_MAX_BUFFER + COSE_MAX_TAG_LEN];
139 uint16_t plaintext_sz = gen_plaintext(ctx, auth_data, auth_data_size, false,
140 mac_or_signature, mac_or_signature_size,
141 aead_buf, EDHOC_MAX_BUFFER);
142 if(plaintext_sz == 0) {
143 return 0;
144 }
145 LOG_DBG("PLAINTEXT_3 (%d bytes): ", (int)plaintext_sz);
146 LOG_DBG_BYTES(aead_buf, plaintext_sz);
147 LOG_DBG_("\n");
148
149 /* Save plaintext_3 for TH_3. */
150 memcpy(ctx->buffers.plaintext, aead_buf, plaintext_sz);
151 ctx->buffers.plaintext_sz = plaintext_sz;
152
153 /* Derive K_3. */
154 uint8_t key[COSE_MAX_KEY_LEN];
155 int16_t err = edhoc_kdf(ctx->state.prk_3e2m, K_3_LABEL, ctx->state.th,
156 HASH_LEN, key_len, key);
157 if(err < 1) {
158 LOG_ERR("Failed to derive K_3\n");
159 return 0;
160 }
161 LOG_DBG("K_3 (%d bytes): ", (int)key_len);
162 LOG_DBG_BYTES(key, key_len);
163 LOG_DBG_("\n");
164
165 /* Derive IV_3. */
166 uint8_t nonce[COSE_MAX_IV_LEN];
167 err = edhoc_kdf(ctx->state.prk_3e2m, IV_3_LABEL, ctx->state.th, HASH_LEN,
168 iv_len, nonce);
169 if(err < 1) {
170 LOG_ERR("Failed to derive IV_3\n");
171 return 0;
172 }
173 LOG_DBG("IV_3 (%d bytes): ", (int)iv_len);
174 LOG_DBG_BYTES(nonce, iv_len);
175 LOG_DBG_("\n");
176
177 /* COSE_Encrypt0: AAD is TH_3, in-place encrypt. */
178 size_t ciphertext_sz = cose_encrypt0_seal(alg, key, nonce,
179 ctx->state.th, HASH_LEN,
180 aead_buf, plaintext_sz,
181 sizeof(aead_buf));
182 if(ciphertext_sz == 0) {
183 LOG_ERR("COSE_Encrypt0 encryption failed\n");
184 return 0;
185 }
186
187 cbor_writer_state_t writer;
188 cbor_init_writer(&writer, ciphertext, ciphertext_buffer_size);
189 cbor_write_data(&writer, aead_buf, ciphertext_sz);
190
191 size_t result = cbor_end_writer(&writer);
192 if(result == 0) {
193 LOG_ERR("CBOR encoding failed in ciphertext_3 generation\n");
194 }
195 return (uint16_t)result;
196}
197/*---------------------------------------------------------------------------*/
199edhoc_generate_message_1(edhoc_context_t *ctx, uint8_t *ad, size_t ad_sz, bool suite_array)
200{
201 if(ctx == NULL) {
203 }
204
205 if(ad_sz > 0 && ad == NULL) {
207 }
208
209 if(ctx->config.suite_num == 0) {
211 }
212
213 /* Generate message 1 */
214 edhoc_msg_1_t msg1 = {
215 .method = ctx->config.method,
216 .suites_i_num = MIN(EDHOC_SUITES_MAX_COUNT, ctx->config.suite_num),
217 .g_x = (uint8_t *)&ctx->creds.ephemeral_key.pub.x,
218 .c_i = ctx->state.cid,
219 .c_i_sz = ctx->state.cid_len,
220 .uad = { .ead_label = 0, .ead_value = ad, .ead_value_sz = ad_sz },
221 };
222 memcpy(msg1.suites_i, ctx->config.suite, msg1.suites_i_num * sizeof(msg1.suites_i[0]));
223
224 /* CBOR encode message in the buffer */
225 size_t size = edhoc_serialize_msg_1(&msg1, (ctx->buffers.msg_tx) + 1,
226 EDHOC_MAX_PAYLOAD_LEN - 1, suite_array);
227 if(!size) {
228 /* Failed to generate message */
230 }
231
232 if(size >= EDHOC_MAX_PAYLOAD_LEN) {
234 }
235
236 ctx->buffers.tx_sz = size + 1;
237 (ctx->buffers.msg_tx)[0] = 0xF5; /* Prepend CBOR true (0xF5) as per EDHOC spec */
238
239 LOG_DBG("C_I chosen by Initiator (%d bytes): 0x", (int)msg1.c_i_sz);
240 LOG_DBG_BYTES(msg1.c_i, msg1.c_i_sz);
241 LOG_DBG_("\n");
242 LOG_DBG("AD_1 (%d bytes): ", (int)ad_sz);
243 LOG_DBG_STRING((char *)ad, ad_sz);
244 LOG_DBG_("\n");
245 for(int i = 0; i < msg1.suites_i_num; ++i) {
246 LOG_DBG("SUITES_I[%d]: %d\n", i, (int)msg1.suites_i[i]);
247 }
248
249 LOG_DBG("message_1 (CBOR Sequence) (%d bytes): ", (int)ctx->buffers.tx_sz);
250 LOG_DBG_BYTES(ctx->buffers.msg_tx, ctx->buffers.tx_sz);
251 LOG_DBG_("\n");
252 LOG_INFO("MSG1 sz: %d\n", (int)ctx->buffers.tx_sz);
253
254 return EDHOC_SUCCESS;
255}
256/*---------------------------------------------------------------------------*/
258edhoc_generate_message_2(edhoc_context_t *ctx, const uint8_t *auth_data, size_t auth_data_size)
259{
260 if(ctx == NULL) {
262 }
263
264 if(auth_data_size > 0 && auth_data == NULL) {
266 }
267
268 int8_t ret = edhoc_generate_transcript_hash_2(ctx, ctx->creds.ephemeral_key.pub.x,
269 ctx->buffers.msg_rx, ctx->buffers.rx_sz);
270 if(ret < 0) {
271 LOG_ERR("Failed to generate TH_2 (%d)\n", ret);
273 }
274
275 /* generate cred_x and id_cred_x */
276 ctx->buffers.cred_x_sz =
277 edhoc_generate_cred_x(ctx->creds.authen_key,
278 ctx->buffers.cred_x,
279 sizeof(ctx->buffers.cred_x));
280 edhoc_print_credential("CRED_R", ctx->buffers.cred_x, ctx->buffers.cred_x_sz);
281
282 ctx->buffers.id_cred_x_sz =
283 edhoc_generate_id_cred_x(ctx->creds.authen_key,
284 ctx->buffers.id_cred_x,
285 sizeof(ctx->buffers.id_cred_x));
286 LOG_DBG("ID_CRED_R (%d bytes): ", (int)ctx->buffers.id_cred_x_sz);
287 LOG_DBG_BYTES(ctx->buffers.id_cred_x, ctx->buffers.id_cred_x_sz);
288 LOG_DBG_("\n");
289
291
292 uint8_t mac_or_signature_sz = -1;
293
294 /* Generate MAC or Signature */
295
296#if (EDHOC_METHOD == EDHOC_METHOD1) || (EDHOC_METHOD == EDHOC_METHOD3)
297 /* generate prk_3e2m */
298 edhoc_generate_prk_3e2m(ctx, &ctx->creds.authen_key->ecc, 1);
299
300 uint8_t edhoc_mac_len = ctx->config.mac_len;
301 uint8_t mac_or_sig[edhoc_mac_len];
302 edhoc_error_t mac_result = gen_mac(ctx, edhoc_mac_len, mac_or_sig);
303 if(mac_result != EDHOC_SUCCESS) {
304 return mac_result;
305 }
306 LOG_DBG("MAC_2 (%d bytes): ", edhoc_mac_len);
307 LOG_DBG_BYTES(mac_or_sig, edhoc_mac_len);
308 LOG_DBG_("\n");
309 mac_or_signature_sz = edhoc_mac_len;
310#endif
311
312#if (EDHOC_METHOD == EDHOC_METHOD0) || (EDHOC_METHOD == EDHOC_METHOD2)
313
314 /* prk_3e2m is prk_2e */
315 memcpy(ctx->state.prk_3e2m, ctx->state.prk_2e, HASH_LEN);
316
317 /* Derive MAC with HASH_LEN size (buf fits later signature) */
318 uint8_t mac_or_sig[EDHOC_MAC_OR_SIG_BUF_LEN];
319 edhoc_error_t mac_result = gen_mac(ctx, HASH_LEN, mac_or_sig);
320 if(mac_result != EDHOC_SUCCESS) {
321 return mac_result;
322 }
323 LOG_DBG("MAC_2 (%d bytes): ", HASH_LEN);
324 LOG_DBG_BYTES(mac_or_sig, HASH_LEN);
325 LOG_DBG_("\n");
326
327 /* Create signature from MAC and other data using COSE_Sign1. */
328
329 /* External AAD (TH_2, CRED_R, ? EAD_2) */
330 uint8_t external_aad[HASH_LEN + EDHOC_MAX_CRED_LEN];
331 cbor_writer_state_t writer_aad;
332 cbor_init_writer(&writer_aad, external_aad, sizeof(external_aad));
333 cbor_write_data(&writer_aad, ctx->state.th, HASH_LEN);
334 cbor_write_object(&writer_aad, ctx->buffers.cred_x, ctx->buffers.cred_x_sz);
335 size_t external_aad_sz = cbor_end_writer(&writer_aad);
336 if(external_aad_sz == 0) {
337 LOG_ERR("Failed to encode external AAD for COSE_Sign1\n");
339 }
340
341 size_t sig_sz = cose_sign1_sign(ctx->config.sign_alg,
342 ctx->creds.authen_key->ecc.priv,
343 ctx->buffers.id_cred_x,
344 ctx->buffers.id_cred_x_sz,
345 external_aad, external_aad_sz,
346 mac_or_sig, HASH_LEN,
347 mac_or_sig);
348 if(sig_sz == 0) {
349 LOG_ERR("COSE_Sign1 signing failed\n");
351 }
352
353 LOG_DBG("Signature from COSE_Sign1 (%zu bytes): ", sig_sz);
354 LOG_DBG_BYTES(mac_or_sig, sig_sz);
355 LOG_DBG_("\n");
356
357 mac_or_signature_sz = sig_sz;
358#endif
359
360 /* Generate and store the plaintext in the session */
361 uint16_t plaint_sz = gen_plaintext(ctx, auth_data, auth_data_size, true, mac_or_sig,
362 mac_or_signature_sz,
363 ctx->buffers.plaintext,
364 sizeof(ctx->buffers.plaintext));
365 LOG_DBG("PLAINTEXT_2 (%d bytes): ", (int)plaint_sz);
366 LOG_DBG_BYTES(ctx->buffers.plaintext, plaint_sz);
367 LOG_DBG_("\n");
368 if(plaint_sz == 0) {
370 }
371 ctx->buffers.plaintext_sz = plaint_sz;
372
373 /* Derive KEYSTREAM_2 */
374 uint8_t ks_2e[plaint_sz];
375 edhoc_generate_keystream_2e(ctx, plaint_sz, ks_2e);
376
377 /* Encrypt the plaintext */
378 uint8_t ciphertext[plaint_sz];
379 memcpy(ciphertext, ctx->buffers.plaintext, plaint_sz);
380 edhoc_enc_dec_ciphertext_2(ctx, ks_2e, ciphertext, plaint_sz);
381 LOG_DBG("CIPHERTEXT_2 (%d bytes): ", (int)plaint_sz);
382 LOG_DBG_BYTES(ciphertext, plaint_sz);
383 LOG_DBG_("\n");
384
385 /* Set x and ciphertext in msg_tx */
386 cbor_writer_state_t writer;
387 cbor_init_writer(&writer, ctx->buffers.msg_tx, sizeof(ctx->buffers.msg_tx));
388
389 /* Write as a single CBOR byte string containing G_Y + CIPHERTEXT_2 */
390 cbor_open_data(&writer);
391 cbor_write_object(&writer, ctx->creds.ephemeral_key.pub.x, ECC_KEY_LEN);
392 cbor_write_object(&writer, ciphertext, plaint_sz);
393 cbor_close_data(&writer);
394
395 ctx->buffers.tx_sz = cbor_end_writer(&writer);
396 if(ctx->buffers.tx_sz == 0) {
398 }
399
400 LOG_INFO("MSG2 sz: %d\n", ctx->buffers.tx_sz);
401
402 return EDHOC_SUCCESS;
403}
404/*---------------------------------------------------------------------------*/
406edhoc_generate_message_3(edhoc_context_t *ctx, const uint8_t *auth_data, size_t auth_data_size)
407{
408 if(ctx == NULL) {
410 }
411
412 if(auth_data_size > 0 && auth_data == NULL) {
414 }
415 /* gen TH_3 */
416 edhoc_generate_transcript_hash_3(ctx, ctx->buffers.cred_x, ctx->buffers.cred_x_sz,
417 ctx->buffers.plaintext, ctx->buffers.plaintext_sz);
418
419 cose_print_key(ctx->creds.authen_key);
420 LOG_DBG("SK_I (Initiator's private auth key) (%d bytes): ",
421 ECC_KEY_LEN);
422 LOG_DBG_BYTES(ctx->creds.authen_key->ecc.priv, ECC_KEY_LEN);
423 LOG_DBG_("\n");
424
425 LOG_DBG("G_I (x)(Initiator's public auth key) (%d bytes): ",
426 ECC_KEY_LEN);
427 LOG_DBG_BYTES(ctx->creds.authen_key->ecc.pub.x, ECC_KEY_LEN);
428 LOG_DBG_("\n");
429
430 LOG_DBG("G_I (y)(Initiator's public auth key) (%d bytes): ",
431 ECC_KEY_LEN);
432 LOG_DBG_BYTES(ctx->creds.authen_key->ecc.pub.y, ECC_KEY_LEN);
433 LOG_DBG_("\n");
434
435 /* generate cred_x */
436 ctx->buffers.cred_x_sz =
437 edhoc_generate_cred_x(ctx->creds.authen_key,
438 ctx->buffers.cred_x,
439 sizeof(ctx->buffers.cred_x));
440 LOG_DBG("CRED_I (%d bytes): ", (int)ctx->buffers.cred_x_sz);
441 LOG_DBG_BYTES(ctx->buffers.cred_x, ctx->buffers.cred_x_sz);
442 LOG_DBG_("\n");
443
444 edhoc_print_credential("CRED_I", ctx->buffers.cred_x, ctx->buffers.cred_x_sz);
445
446 /* generate id_cred_x */
447 ctx->buffers.id_cred_x_sz =
448 edhoc_generate_id_cred_x(ctx->creds.authen_key,
449 ctx->buffers.id_cred_x,
450 sizeof(ctx->buffers.id_cred_x));
451 LOG_DBG("ID_CRED_I (%d bytes): ", (int)ctx->buffers.id_cred_x_sz);
452 LOG_DBG_BYTES(ctx->buffers.id_cred_x, ctx->buffers.id_cred_x_sz);
453 LOG_DBG_("\n");
454
455 uint8_t mac_or_signature_sz = -1;
456
457#if ((EDHOC_METHOD == EDHOC_METHOD2) || (EDHOC_METHOD == EDHOC_METHOD3))
458 /* Generate prk_4e3m */
459 edhoc_generate_prk_4e3m(ctx, &ctx->creds.authen_key->ecc, 0);
460
461 uint8_t edhoc_mac_len = ctx->config.mac_len;
462 uint8_t mac_or_sig[edhoc_mac_len];
463 edhoc_error_t mac_result = gen_mac(ctx, edhoc_mac_len, mac_or_sig);
464 if(mac_result != EDHOC_SUCCESS) {
465 return mac_result;
466 }
467 LOG_DBG("MAC 3 (%d bytes): ", edhoc_mac_len);
468 LOG_DBG_BYTES(mac_or_sig, edhoc_mac_len);
469 LOG_DBG_("\n");
470 mac_or_signature_sz = edhoc_mac_len;
471#endif
472
473#if (EDHOC_METHOD == EDHOC_METHOD0) || (EDHOC_METHOD == EDHOC_METHOD1)
474
475 /* prk_4e3m is prk_3e2m */
476 memcpy(ctx->state.prk_4e3m, ctx->state.prk_3e2m, HASH_LEN);
477
478 /* Derive MAC with HASH_LEN size (buf fits later signature) */
479 uint8_t mac_or_sig[EDHOC_MAC_OR_SIG_BUF_LEN];
480 edhoc_error_t mac_result = gen_mac(ctx, HASH_LEN, mac_or_sig);
481 if(mac_result != EDHOC_SUCCESS) {
482 return mac_result;
483 }
484 LOG_DBG("MAC_3 (%d bytes): ", HASH_LEN);
485 LOG_DBG_BYTES(mac_or_sig, HASH_LEN);
486 LOG_DBG_("\n");
487
488 /* Create signature from MAC and other data using COSE_Sign1. */
489
490 /* External AAD (TH_3, CRED_I, ? EAD_3) */
491 uint8_t external_aad[HASH_LEN + EDHOC_MAX_CRED_LEN];
492 cbor_writer_state_t writer;
493 cbor_init_writer(&writer, external_aad, sizeof(external_aad));
494 cbor_write_data(&writer, ctx->state.th, HASH_LEN);
495 cbor_write_object(&writer, ctx->buffers.cred_x, ctx->buffers.cred_x_sz);
496 size_t external_aad_sz = cbor_end_writer(&writer);
497 if(external_aad_sz == 0) {
498 LOG_ERR("Failed to encode external AAD for COSE_Sign1\n");
500 }
501
502 size_t sig_sz = cose_sign1_sign(ctx->config.sign_alg,
503 ctx->creds.authen_key->ecc.priv,
504 ctx->buffers.id_cred_x,
505 ctx->buffers.id_cred_x_sz,
506 external_aad, external_aad_sz,
507 mac_or_sig, HASH_LEN,
508 mac_or_sig);
509 if(sig_sz == 0) {
510 LOG_ERR("COSE_Sign1 signing failed\n");
512 }
513
514 LOG_DBG("Signature from COSE_Sign1 (%zu bytes): ", sig_sz);
515 LOG_DBG_BYTES(mac_or_sig, sig_sz);
516 LOG_DBG_("\n");
517
518 mac_or_signature_sz = sig_sz;
519#endif
520
521 /* Gen ciphertext_3 */
522 uint16_t ciphertext_sz = gen_ciphertext_3(ctx, auth_data, auth_data_size, mac_or_sig,
523 mac_or_signature_sz,
524 (ctx->buffers.msg_tx) + 1,
525 sizeof(ctx->buffers.msg_tx) - 1);
526 if(ciphertext_sz == 0) {
528 }
529
530 /* Prepend connection identifier C_R as per EDHOC MSG_3 format */
531 if(ctx->state.cid_rx_len > sizeof(ctx->buffers.msg_tx) - ciphertext_sz) {
533 }
534 /* Move ciphertext to make room for CID */
535 memmove(ctx->buffers.msg_tx + ctx->state.cid_rx_len,
536 ctx->buffers.msg_tx + 1, ciphertext_sz);
537 /* Copy CID to beginning */
538 memcpy(ctx->buffers.msg_tx, ctx->state.cid_rx, ctx->state.cid_rx_len);
539 ctx->buffers.tx_sz = ciphertext_sz + ctx->state.cid_rx_len;
540
541 /* Compute TH_4 WIP */
542 edhoc_generate_transcript_hash_4(ctx, ctx->buffers.cred_x, ctx->buffers.cred_x_sz,
543 ctx->buffers.plaintext, ctx->buffers.plaintext_sz);
544
545 return EDHOC_SUCCESS;
546}
547/*---------------------------------------------------------------------------*/
CBOR API.
Public API declarations for COSE (RFC 9052).
EDHOC configuration file.
Error handling module header for EDHOC.
edhoc_error_t
Unified error type for EDHOC operations.
Definition edhoc-error.h:60
@ EDHOC_ERR_CBOR_ENCODING
CBOR encoding failed.
@ EDHOC_ERR_NULL_POINTER
Null pointer provided.
Definition edhoc-error.h:68
@ EDHOC_ERR_CRYPTO_HASH
Hash operation failed.
Definition edhoc-error.h:77
@ EDHOC_ERR_CRYPTO_ENCRYPT
Encryption operation failed.
Definition edhoc-error.h:75
@ EDHOC_ERR_CRYPTO_AUTHENTICATION
Authentication failed.
Definition edhoc-error.h:79
@ EDHOC_ERR_INVALID_STATE
Invalid context state.
@ EDHOC_ERR_SUITE_NOT_SUPPORTED
Cipher suite not supported.
Definition edhoc-error.h:83
@ EDHOC_ERR_BUFFER_TOO_SMALL
Provided buffer is too small.
Definition edhoc-error.h:66
@ EDHOC_ERR_CRYPTO_SIGN
Digital signature failed.
Definition edhoc-error.h:73
void edhoc_print_credential(const char *label, const uint8_t *cred, size_t cred_sz)
Print credential (CRED_I/CRED_R) values in readable format.
void cose_print_key(cose_key_t *cose)
Print a key in cose_key_t struct format for debugging.
Declarations for EDHOC message generators.
size_t edhoc_serialize_msg_1(edhoc_msg_1_t *msg, unsigned char *buffer, size_t buffer_sz, bool suite_array)
Serialize EDHOC message 1 to CBOR format.
Definition edhoc-msgs.c:177
void edhoc_write_byte_identifier(cbor_writer_state_t *state, const uint8_t *bytes, size_t byte_length)
Write EDHOC byte identifier according to RFC 9528 rules.
Definition edhoc-msgs.c:108
EDHOC message serialization and parsing API.
An implementation of Ephemeral Diffie-Hellman Over COSE (EDHOC) (RFC9528).
uint8_t cose_get_key_len(uint8_t alg_id)
Get the symmetric key length for a COSE AEAD algorithm.
Definition cose.c:280
uint8_t cose_get_iv_len(uint8_t alg_id)
Get the nonce/IV length for a COSE AEAD algorithm.
Definition cose.c:294
uint8_t cose_get_tag_len(uint8_t alg_id)
Get the authentication tag length for a COSE AEAD algorithm.
Definition cose.c:308
size_t cose_encrypt0_seal(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 plaintext_len, size_t buf_capacity)
AEAD-encrypt a buffer in place as a COSE_Encrypt0.
Definition cose.c:103
size_t cose_sign1_sign(int8_t alg, const uint8_t *private_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, uint8_t *signature)
Produce a COSE_Sign1 signature.
Definition cose.c:209
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.
Definition edhoc.c:279
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).
Definition edhoc.c:417
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.
Definition edhoc.c:242
bool edhoc_generate_prk_2e(edhoc_context_t *ctx)
Generate pseudorandom key PRK_2e.
Definition edhoc.c:542
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).
Definition edhoc.c:373
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.
Definition edhoc.c:665
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.
size_t edhoc_generate_cred_x(const cose_key_t *cose, uint8_t *cred, size_t cred_sz)
Generate CBOR-encoded credential CRED_X.
Definition edhoc.c:210
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.
Definition edhoc.c:306
int16_t edhoc_generate_keystream_2e(edhoc_context_t *ctx, uint16_t length, uint8_t *ks_2e)
Generate keystream KS_2e for encryption.
Definition edhoc.c:561
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.
Definition edhoc.c:335
size_t cbor_end_writer(cbor_writer_state_t *state)
Finishes writing CBOR output.
Definition cbor.c:54
void cbor_close_data(cbor_writer_state_t *state)
Stops enclosing subsequent CBOR objects in the innermost byte string.
Definition cbor.c:249
cbor_size_t cbor_read_unsigned(cbor_reader_state_t *state, uint64_t *value)
Reads an unsigned integer.
Definition cbor.c:364
void cbor_open_data(cbor_writer_state_t *state)
Encloses subsequent CBOR objects in a byte string.
Definition cbor.c:243
const uint8_t * cbor_read_data(cbor_reader_state_t *state, size_t *data_size)
Reads a byte string.
Definition cbor.c:411
void cbor_write_object(cbor_writer_state_t *state, const void *object, size_t object_size)
Appends an arbitrary CBOR object.
Definition cbor.c:106
void cbor_init_writer(cbor_writer_state_t *state, uint8_t *buffer, size_t buffer_size)
Prepares for writing CBOR output.
Definition cbor.c:44
void cbor_init_reader(cbor_reader_state_t *state, const uint8_t *cbor, size_t cbor_size)
Prepares for reading CBOR input.
Definition cbor.c:293
void cbor_write_data(cbor_writer_state_t *state, const uint8_t *data, size_t data_size)
Appends a byte string.
Definition cbor.c:187
size_t cbor_read_map(cbor_reader_state_t *state)
Reads the number of entries of a map.
Definition cbor.c:460
static int value(int type)
#define EDHOC_SUITES_MAX_COUNT
The max number of suites.
#define EDHOC_MAX_CRED_LEN
Optimized buffer sizes for credentials based on COSE standard analysis CRED_X: 84-120 bytes typical →...
#define EDHOC_MAX_PAYLOAD_LEN
The max length of the EDHOC message.
#define EDHOC_MAC_OR_SIG_BUF_LEN
Buffer size for mac_or_sig.
edhoc_error_t edhoc_generate_message_1(edhoc_context_t *ctx, uint8_t *ad, size_t ad_sz, bool suite_array)
Generate the EDHOC Message 1 and set it in the EDHOC context.
#define EDHOC_ROLE
Set the EDHOC Protocol role.
edhoc_error_t edhoc_generate_message_3(edhoc_context_t *ctx, const uint8_t *auth_data, size_t auth_data_size)
Generate the EDHOC Message 3 and set it in the EDHOC context.
#define EDHOC_MAX_BUFFER
The max size of the buffers.
edhoc_error_t edhoc_generate_message_2(edhoc_context_t *ctx, const uint8_t *auth_data, size_t auth_data_size)
Generate the EDHOC Message 2 and set it in the EDHOC context.
Header file for the logging system.
Platform-independent SHA-256 API.
Structure of the internal state of a CBOR reader.
Definition cbor.h:130
Structure of the internal state of a CBOR writer.
Definition cbor.h:119