LCOV - code coverage report
Current view: top level - src/edhoc - initiator.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.8 % 108 97
Test Date: 2026-03-12 12:01:18 Functions: 100.0 % 7 7
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 51.4 % 142 73

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :    Copyright (c) 2021 Fraunhofer AISEC. See the COPYRIGHT
       3                 :             :    file at the top-level directory of this distribution.
       4                 :             : 
       5                 :             :    Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
       6                 :             :    http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
       7                 :             :    <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
       8                 :             :    option. This file may not be copied, modified, or distributed
       9                 :             :    except according to those terms.
      10                 :             : */
      11                 :             : 
      12                 :             : #include <stdbool.h>
      13                 :             : #include "edhoc_internal.h"
      14                 :             : 
      15                 :             : #include "common/crypto_wrapper.h"
      16                 :             : #include "common/oscore_edhoc_error.h"
      17                 :             : #include "common/memcpy_s.h"
      18                 :             : #include "common/print_util.h"
      19                 :             : 
      20                 :             : #include "edhoc/buffer_sizes.h"
      21                 :             : #include "edhoc/hkdf_info.h"
      22                 :             : #include "edhoc/messages.h"
      23                 :             : #include "edhoc/okm.h"
      24                 :             : #include "edhoc/plaintext.h"
      25                 :             : #include "edhoc/prk.h"
      26                 :             : #include "edhoc/retrieve_cred.h"
      27                 :             : #include "edhoc/signature_or_mac_msg.h"
      28                 :             : #include "edhoc/suites.h"
      29                 :             : #include "edhoc/th.h"
      30                 :             : #include "edhoc/txrx_wrapper.h"
      31                 :             : #include "edhoc/ciphertext.h"
      32                 :             : #include "edhoc/runtime_context.h"
      33                 :             : #include "edhoc/bstr_encode_decode.h"
      34                 :             : #include "edhoc/int_encode_decode.h"
      35                 :             : 
      36                 :             : #include "cbor/edhoc_encode_message_1.h"
      37                 :             : #include "cbor/edhoc_decode_message_2.h"
      38                 :             : #include "cbor/edhoc_encode_message_3.h"
      39                 :             : 
      40                 :             : /** 
      41                 :             :  * @brief                       Parses message 2.
      42                 :             :  * @param c                     Initiator context.
      43                 :             :  * @param[in] msg2              Message 2. 
      44                 :             :  * @param[out] g_y              G_Y ephemeral public key of the responder.
      45                 :             :  * @param[out] ciphertext2      Ciphertext 2.
      46                 :             :  * @retval                      Ok or error code.
      47                 :             :  */
      48                 :           3 : static inline enum err msg2_parse(struct byte_array *msg2,
      49                 :             :                                   struct byte_array *g_y,
      50                 :             :                                   struct byte_array *ciphertext2)
      51                 :             : {
      52         [ -  + ]:           3 :         BYTE_ARRAY_NEW(g_y_ciphertext_2, G_Y_CIPHERTEXT_2, G_Y_CIPHERTEXT_2);
      53         [ -  + ]:           3 :         TRY(decode_bstr(msg2, &g_y_ciphertext_2));
      54                 :             : 
      55         [ -  + ]:           3 :         TRY(_memcpy_s(g_y->ptr, g_y->len, g_y_ciphertext_2.ptr, g_y->len));
      56                 :           3 :         PRINT_ARRAY("g_y", g_y->ptr, g_y->len);
      57                 :             : 
      58         [ -  + ]:           3 :         TRY(_memcpy_s(ciphertext2->ptr, ciphertext2->len,
      59                 :             :                       g_y_ciphertext_2.ptr + g_y->len,
      60                 :             :                       g_y_ciphertext_2.len - g_y->len));
      61                 :             : 
      62                 :           3 :         ciphertext2->len = g_y_ciphertext_2.len - g_y->len;
      63                 :           3 :         PRINT_ARRAY("ciphertext2", ciphertext2->ptr, ciphertext2->len);
      64                 :             : 
      65                 :           3 :         return ok;
      66                 :             : }
      67                 :             : 
      68                 :           3 : enum err msg1_gen(const struct edhoc_initiator_context *c,
      69                 :             :                   struct runtime_context *rc)
      70                 :             : {
      71                 :             :         struct message_1 m1;
      72                 :             : 
      73                 :             :         /*METHOD_CORR*/
      74                 :           3 :         m1.message_1_METHOD = (int32_t)c->method;
      75                 :             : 
      76                 :             :         /*SUITES_I*/
      77         [ +  - ]:           3 :         if (c->suites_i.len == 1) {
      78                 :             :                 /* only one suite, encode into int */
      79                 :           3 :                 m1.message_1_SUITES_I_choice = message_1_SUITES_I_int_c;
      80                 :           3 :                 m1.message_1_SUITES_I_int = c->suites_i.ptr[0];
      81         [ #  # ]:           0 :         } else if (c->suites_i.len > 1) {
      82                 :             :                 /* more than one suites, encode into array */
      83                 :           0 :                 m1.message_1_SUITES_I_choice = SUITES_I_suite_l_c;
      84                 :           0 :                 m1.SUITES_I_suite_l_suite_count = c->suites_i.len;
      85         [ #  # ]:           0 :                 for (uint32_t i = 0; i < c->suites_i.len; i++) {
      86                 :           0 :                         m1.SUITES_I_suite_l_suite[i] = c->suites_i.ptr[i];
      87                 :             :                 }
      88                 :             :         }
      89                 :             : 
      90                 :             :         /* G_X ephemeral public key */
      91                 :           3 :         m1.message_1_G_X.value = c->g_x.ptr;
      92                 :           3 :         m1.message_1_G_X.len = c->g_x.len;
      93                 :             : 
      94                 :             :         /* C_I connection ID  of the initiator*/
      95                 :           3 :         PRINT_ARRAY("C_I", c->c_i.ptr, c->c_i.len);
      96         [ +  - ]:           3 :         if (c_x_is_encoded_int(&c->c_i)) {
      97                 :           3 :                 m1.message_1_C_I_choice = message_1_C_I_int_c;
      98         [ -  + ]:           3 :                 TRY(decode_int(&c->c_i, &m1.message_1_C_I_int));
      99                 :             :         } else {
     100                 :           0 :                 m1.message_1_C_I_choice = message_1_C_I_bstr_c;
     101                 :           0 :                 m1.message_1_C_I_bstr.value = c->c_i.ptr;
     102                 :           0 :                 m1.message_1_C_I_bstr.len = c->c_i.len;
     103                 :             :         }
     104                 :             : 
     105         [ -  + ]:           3 :         if (c->ead_1.len != 0) {
     106                 :             :                 /* ead_1 unprotected opaque auxiliary data */
     107                 :           0 :                 m1.message_1_ead_1.value = c->ead_1.ptr;
     108                 :           0 :                 m1.message_1_ead_1.len = c->ead_1.len;
     109                 :           0 :                 m1.message_1_ead_1_present = true;
     110                 :             :         } else {
     111                 :           3 :                 m1.message_1_ead_1_present = false;
     112                 :             :         }
     113                 :             : 
     114                 :             :         size_t payload_len_out;
     115         [ -  + ]:           3 :         TRY_EXPECT(cbor_encode_message_1(rc->msg.ptr, rc->msg.len, &m1,
     116                 :             :                                          &payload_len_out),
     117                 :             :                    0);
     118                 :           3 :         rc->msg.len = (uint32_t)payload_len_out;
     119                 :             : 
     120                 :           3 :         PRINT_ARRAY("message_1 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
     121                 :             : 
     122         [ -  + ]:           3 :         TRY(get_suite((enum suite_label)c->suites_i.ptr[c->suites_i.len - 1],
     123                 :             :                       &rc->suite));
     124                 :             :         /* Calculate hash of msg1 for TH2. */
     125         [ -  + ]:           3 :         TRY(hash(rc->suite.edhoc_hash, &rc->msg, &rc->msg1_hash));
     126                 :           3 :         return ok;
     127                 :             : }
     128                 :             : 
     129                 :           3 : static enum err msg2_process(const struct edhoc_initiator_context *c,
     130                 :             :                              struct runtime_context *rc,
     131                 :             :                              struct cred_array *cred_r_array,
     132                 :             :                              struct byte_array *c_r, bool static_dh_i,
     133                 :             :                              bool static_dh_r, struct byte_array *th3,
     134                 :             :                              struct byte_array *PRK_3e2m)
     135                 :             : {
     136   [ -  +  -  + ]:           3 :         BYTE_ARRAY_NEW(g_y, G_Y_SIZE, get_ecdh_pk_len(rc->suite.edhoc_ecdh));
     137                 :           3 :         uint32_t ciphertext_len = rc->msg.len - g_y.len;
     138   [ +  -  +  +  :           3 :         ciphertext_len -= BSTR_ENCODING_OVERHEAD(ciphertext_len);
                   +  - ]
     139   [ -  +  -  + ]:           3 :         BYTE_ARRAY_NEW(ciphertext, CIPHERTEXT2_SIZE, ciphertext_len);
     140   [ -  +  -  + ]:           3 :         BYTE_ARRAY_NEW(plaintext, PLAINTEXT2_SIZE, ciphertext.len);
     141                 :           3 :         PRINT_ARRAY("message_2 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
     142                 :             : 
     143                 :             :         /*parse the message*/
     144         [ -  + ]:           3 :         TRY(msg2_parse(&rc->msg, &g_y, &ciphertext));
     145                 :             : 
     146                 :             :         /*calculate the DH shared secret*/
     147         [ -  + ]:           3 :         BYTE_ARRAY_NEW(g_xy, ECDH_SECRET_SIZE, ECDH_SECRET_SIZE);
     148                 :             : 
     149         [ -  + ]:           3 :         TRY(shared_secret_derive(rc->suite.edhoc_ecdh, &c->x, &g_y, g_xy.ptr));
     150                 :           3 :         PRINT_ARRAY("G_XY (ECDH shared secret) ", g_xy.ptr, g_xy.len);
     151                 :             : 
     152                 :             :         /*calculate th2*/
     153   [ -  +  -  + ]:           3 :         BYTE_ARRAY_NEW(th2, HASH_SIZE, get_hash_len(rc->suite.edhoc_hash));
     154                 :             : 
     155         [ -  + ]:           3 :         TRY(th2_calculate(rc->suite.edhoc_hash, &rc->msg1_hash, &g_y, &th2));
     156                 :             : 
     157                 :             :         /*calculate PRK_2e*/
     158         [ -  + ]:           3 :         BYTE_ARRAY_NEW(PRK_2e, PRK_SIZE, PRK_SIZE);
     159         [ -  + ]:           3 :         TRY(hkdf_extract(rc->suite.edhoc_hash, &th2, &g_xy, PRK_2e.ptr));
     160                 :           3 :         PRINT_ARRAY("PRK_2e", PRK_2e.ptr, PRK_2e.len);
     161                 :             : 
     162         [ -  + ]:           3 :         BYTE_ARRAY_NEW(sign_or_mac, SIG_OR_MAC_SIZE, SIG_OR_MAC_SIZE);
     163         [ -  + ]:           3 :         BYTE_ARRAY_NEW(id_cred_r, ID_CRED_R_SIZE, ID_CRED_R_SIZE);
     164                 :             : 
     165                 :           3 :         plaintext.len = ciphertext.len;
     166         [ -  + ]:           3 :         TRY(check_buffer_size(PLAINTEXT2_SIZE, plaintext.len));
     167                 :             : 
     168         [ -  + ]:           3 :         TRY(ciphertext_decrypt_split(CIPHERTEXT2, &rc->suite, c_r, &id_cred_r,
     169                 :             :                                      &sign_or_mac, &rc->ead, &PRK_2e, &th2,
     170                 :             :                                      &ciphertext, &plaintext));
     171                 :             : 
     172                 :             :         /*check the authenticity of the responder*/
     173         [ -  + ]:           3 :         BYTE_ARRAY_NEW(cred_r, CRED_R_SIZE, CRED_R_SIZE);
     174         [ -  + ]:           3 :         BYTE_ARRAY_NEW(pk, PK_SIZE, PK_SIZE);
     175         [ -  + ]:           3 :         BYTE_ARRAY_NEW(g_r, G_R_SIZE, G_R_SIZE);
     176         [ -  + ]:           3 :         TRY(retrieve_cred(static_dh_r, cred_r_array, &id_cred_r, &cred_r, &pk,
     177                 :             :                           &g_r));
     178                 :           3 :         PRINT_ARRAY("CRED_R", cred_r.ptr, cred_r.len);
     179                 :           3 :         PRINT_ARRAY("pk", pk.ptr, pk.len);
     180                 :           3 :         PRINT_ARRAY("g_r", g_r.ptr, g_r.len);
     181                 :             : 
     182                 :             :         /*derive prk_3e2m*/
     183         [ -  + ]:           3 :         TRY(prk_derive(static_dh_r, rc->suite, SALT_3e2m, &th2, &PRK_2e, &g_r,
     184                 :             :                        &c->x, PRK_3e2m->ptr));
     185                 :           3 :         PRINT_ARRAY("prk_3e2m", PRK_3e2m->ptr, PRK_3e2m->len);
     186                 :             : 
     187         [ -  + ]:           3 :         TRY(signature_or_mac(VERIFY, static_dh_r, &rc->suite, NULL, &pk,
     188                 :             :                              PRK_3e2m, c_r, &th2, &id_cred_r, &cred_r, &rc->ead,
     189                 :             :                              MAC_2, &sign_or_mac));
     190                 :             : 
     191         [ -  + ]:           3 :         TRY(th34_calculate(rc->suite.edhoc_hash, &th2, &plaintext, &cred_r,
     192                 :             :                            th3));
     193                 :             : 
     194                 :             :         /*derive prk_4e3m*/
     195         [ -  + ]:           3 :         TRY(prk_derive(static_dh_i, rc->suite, SALT_4e3m, th3, PRK_3e2m, &g_y,
     196                 :             :                        &c->i, rc->prk_4e3m.ptr));
     197                 :           3 :         PRINT_ARRAY("prk_4e3m", rc->prk_4e3m.ptr, rc->prk_4e3m.len);
     198                 :             : 
     199                 :           3 :         return ok;
     200                 :             : }
     201                 :             : 
     202                 :           3 : static enum err msg3_only_gen(const struct edhoc_initiator_context *c,
     203                 :             :                               struct runtime_context *rc, bool static_dh_i,
     204                 :             :                               struct byte_array *th3,
     205                 :             :                               struct byte_array *PRK_3e2m,
     206                 :             :                               struct byte_array *prk_out)
     207                 :             : {
     208   [ -  +  -  + ]:           3 :         BYTE_ARRAY_NEW(plaintext, PLAINTEXT3_SIZE,
     209                 :             :                        c->id_cred_i.len + AS_BSTR_SIZE(SIG_OR_MAC_SIZE) +
     210                 :             :                                c->ead_3.len);
     211   [ +  -  +  +  :           3 :         BYTE_ARRAY_NEW(ciphertext, CIPHERTEXT3_SIZE,
          +  -  -  +  +  
          -  +  +  +  -  
          -  +  +  -  +  
                +  +  - ]
     212                 :             :                        AS_BSTR_SIZE(plaintext.len) +
     213                 :             :                                get_aead_mac_len(rc->suite.edhoc_aead));
     214                 :             :         /*calculate Signature_or_MAC_3*/
     215         [ -  + ]:           3 :         BYTE_ARRAY_NEW(sign_or_mac_3, SIG_OR_MAC_SIZE, SIG_OR_MAC_SIZE);
     216         [ -  + ]:           3 :         TRY(signature_or_mac(GENERATE, static_dh_i, &rc->suite, &c->sk_i,
     217                 :             :                              &c->pk_i, &rc->prk_4e3m, &NULL_ARRAY, th3,
     218                 :             :                              &c->id_cred_i, &c->cred_i, &c->ead_3, MAC_3,
     219                 :             :                              &sign_or_mac_3));
     220                 :             : 
     221                 :             :         /*create plaintext3 and ciphertext3*/
     222         [ -  + ]:           3 :         TRY(ciphertext_gen(CIPHERTEXT3, &rc->suite, &NULL_ARRAY, &c->id_cred_i,
     223                 :             :                            &sign_or_mac_3, &c->ead_3, PRK_3e2m, th3,
     224                 :             :                            &ciphertext, &plaintext));
     225                 :             : 
     226                 :             :         /*massage 3 create and send*/
     227         [ -  + ]:           3 :         TRY(encode_bstr(&ciphertext, &rc->msg));
     228                 :           3 :         PRINT_ARRAY("msg3", rc->msg.ptr, rc->msg.len);
     229                 :             : 
     230                 :             :         /*TH4*/
     231         [ -  + ]:           3 :         TRY(th34_calculate(rc->suite.edhoc_hash, th3, &plaintext, &c->cred_i,
     232                 :             :                            &rc->th4));
     233                 :             : 
     234                 :             :         /*PRK_out*/
     235         [ -  + ]:           3 :         TRY(edhoc_kdf(rc->suite.edhoc_hash, &rc->prk_4e3m, PRK_out, &rc->th4,
     236                 :             :                       prk_out));
     237                 :           3 :         return ok;
     238                 :             : }
     239                 :             : 
     240                 :           3 : enum err msg3_gen(const struct edhoc_initiator_context *c,
     241                 :             :                   struct runtime_context *rc, struct cred_array *cred_r_array,
     242                 :             :                   struct byte_array *c_r, struct byte_array *prk_out)
     243                 :             : {
     244                 :           3 :         bool static_dh_i = false, static_dh_r = false;
     245                 :           3 :         authentication_type_get(c->method, &static_dh_i, &static_dh_r);
     246         [ -  + ]:           3 :         BYTE_ARRAY_NEW(th3, HASH_SIZE, HASH_SIZE);
     247         [ -  + ]:           3 :         BYTE_ARRAY_NEW(PRK_3e2m, PRK_SIZE, PRK_SIZE);
     248                 :             : 
     249                 :             :         /*process message 2*/
     250         [ -  + ]:           3 :         TRY(msg2_process(c, rc, cred_r_array, c_r, static_dh_i, static_dh_r,
     251                 :             :                          &th3, &PRK_3e2m));
     252                 :             : 
     253                 :             :         /*generate message 3*/
     254                 :           3 :         msg3_only_gen(c, rc, static_dh_i, &th3, &PRK_3e2m, prk_out);
     255                 :           3 :         return ok;
     256                 :             : }
     257                 :             : 
     258                 :             : #ifdef MESSAGE_4
     259                 :             : enum err msg4_process(struct runtime_context *rc)
     260                 :             : {
     261                 :             :         PRINT_ARRAY("message4 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
     262                 :             : 
     263                 :             :         BYTE_ARRAY_NEW(ciphertext4, CIPHERTEXT4_SIZE, CIPHERTEXT4_SIZE);
     264                 :             :         TRY(decode_bstr(&rc->msg, &ciphertext4));
     265                 :             :         PRINT_ARRAY("ciphertext_4", ciphertext4.ptr, ciphertext4.len);
     266                 :             : 
     267                 :             :         BYTE_ARRAY_NEW(plaintext4,
     268                 :             :                        PLAINTEXT4_SIZE + get_aead_mac_len(rc->suite.edhoc_aead),
     269                 :             :                        ciphertext4.len);
     270                 :             :         TRY(ciphertext_decrypt_split(CIPHERTEXT4, &rc->suite, NULL, &NULL_ARRAY,
     271                 :             :                                      &NULL_ARRAY, &rc->ead, &rc->prk_4e3m,
     272                 :             :                                      &rc->th4, &ciphertext4, &plaintext4));
     273                 :             :         return ok;
     274                 :             : }
     275                 :             : #endif // MESSAGE_4
     276                 :             : 
     277                 :           3 : enum err edhoc_initiator_run_extended(
     278                 :             :         const struct edhoc_initiator_context *c,
     279                 :             :         struct cred_array *cred_r_array, struct byte_array *err_msg,
     280                 :             :         struct byte_array *c_r_bytes, struct byte_array *prk_out,
     281                 :             :         enum err (*tx)(void *sock, struct byte_array *data),
     282                 :             :         enum err (*rx)(void *sock, struct byte_array *data),
     283                 :             :         enum err (*ead_process)(void *params, struct byte_array *ead24))
     284                 :             : {
     285                 :           3 :         struct runtime_context rc = { 0 };
     286                 :           3 :         runtime_context_init(&rc);
     287                 :             : 
     288                 :             :         /*create and send message 1*/
     289         [ -  + ]:           3 :         TRY(msg1_gen(c, &rc));
     290         [ -  + ]:           3 :         TRY(tx(c->sock, &rc.msg));
     291                 :             : 
     292                 :             :         /*receive message 2*/
     293                 :           3 :         PRINT_MSG("waiting to receive message 2...\n");
     294                 :           3 :         rc.msg.len = sizeof(rc.msg_buf);
     295         [ -  + ]:           3 :         TRY(rx(c->sock, &rc.msg));
     296                 :             : 
     297                 :             :         /*create and send message 3*/
     298         [ -  + ]:           3 :         TRY(msg3_gen(c, &rc, cred_r_array, c_r_bytes, prk_out));
     299         [ -  + ]:           3 :         TRY(ead_process(c->params_ead_process, &rc.ead));
     300         [ -  + ]:           3 :         TRY(tx(c->sock, &rc.msg));
     301                 :             : 
     302                 :             :         /*receive message 4*/
     303                 :             : #ifdef MESSAGE_4
     304                 :             :         PRINT_MSG("waiting to receive message 4...\n");
     305                 :             :         rc.msg.len = sizeof(rc.msg_buf);
     306                 :             :         TRY(rx(c->sock, &rc.msg));
     307                 :             :         TRY(msg4_process(&rc));
     308                 :             :         TRY(ead_process(c->params_ead_process, &rc.ead));
     309                 :             : #endif // MESSAGE_4
     310                 :           3 :         return ok;
     311                 :             : }
     312                 :             : 
     313                 :           3 : enum err edhoc_initiator_run(
     314                 :             :         const struct edhoc_initiator_context *c,
     315                 :             :         struct cred_array *cred_r_array, struct byte_array *err_msg,
     316                 :             :         struct byte_array *prk_out,
     317                 :             :         enum err (*tx)(void *sock, struct byte_array *data),
     318                 :             :         enum err (*rx)(void *sock, struct byte_array *data),
     319                 :             :         enum err (*ead_process)(void *params, struct byte_array *ead24))
     320                 :             : {
     321         [ -  + ]:           3 :         BYTE_ARRAY_NEW(c_r, C_R_SIZE, C_R_SIZE);
     322                 :             : 
     323                 :           3 :         return edhoc_initiator_run_extended(c, cred_r_array, err_msg, &c_r,
     324                 :             :                                             prk_out, tx, rx, ead_process);
     325                 :             : }
        

Generated by: LCOV version 2.0-1