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

           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 1.14