LCOV - code coverage report
Current view: top level - src/oscore - security_context.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 93 96 96.9 %
Date: 2024-09-16 20:15:30 Functions: 8 8 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 42 54 77.8 %

           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 <stdio.h>
      13                 :            : #include <stdlib.h>
      14                 :            : #include <string.h>
      15                 :            : 
      16                 :            : #include "oscore.h"
      17                 :            : 
      18                 :            : #include "oscore/aad.h"
      19                 :            : #include "oscore/nonce.h"
      20                 :            : #include "oscore/oscore_coap.h"
      21                 :            : #include "oscore/oscore_hkdf_info.h"
      22                 :            : #include "oscore/oscore_interactions.h"
      23                 :            : #include "oscore/security_context.h"
      24                 :            : #include "oscore/nvm.h"
      25                 :            : 
      26                 :            : #include "common/crypto_wrapper.h"
      27                 :            : #include "common/oscore_edhoc_error.h"
      28                 :            : #include "common/memcpy_s.h"
      29                 :            : #include "common/print_util.h"
      30                 :            : #include "common/unit_test.h"
      31                 :            : 
      32                 :            : /**
      33                 :            :  * @brief       Common derive procedure used to derive the Common IV and 
      34                 :            :  *              Sender / Recipient Keys
      35                 :            :  * @param cc    pointer to the common context
      36                 :            :  * @param id    empty array for Common IV, sender / recipient ID for keys
      37                 :            :  * @param type  IV for Common IV, KEY for Sender / Recipient Keys
      38                 :            :  * @param out   out-array. Must be initialized
      39                 :            :  * @return      err
      40                 :            :  */
      41                 :         34 : STATIC enum err derive(struct common_context *cc, struct byte_array *id,
      42                 :            :                        enum derive_type type, struct byte_array *out)
      43                 :            : {
      44         [ -  + ]:         34 :         BYTE_ARRAY_NEW(info, MAX_INFO_LEN, MAX_INFO_LEN);
      45         [ -  + ]:         34 :         TRY(oscore_create_hkdf_info(id, &cc->id_context, cc->aead_alg, type,
      46                 :            :                                     &info));
      47                 :            : 
      48                 :         34 :         PRINT_ARRAY("info struct", info.ptr, info.len);
      49                 :            : 
      50         [ +  + ]:         34 :         switch (cc->kdf) {
      51                 :         33 :         case OSCORE_SHA_256:
      52         [ -  + ]:         33 :                 TRY(hkdf_sha_256(&cc->master_secret, &cc->master_salt, &info,
      53                 :            :                                  out));
      54                 :         33 :                 break;
      55                 :          1 :         default:
      56                 :          1 :                 return oscore_unknown_hkdf;
      57                 :            :                 break;
      58                 :            :         }
      59                 :         33 :         return ok;
      60                 :            : }
      61                 :            : 
      62                 :            : /**
      63                 :            :  * @brief    Derives the Common IV 
      64                 :            :  * @param    cc    pointer to the common context
      65                 :            :  * @return   err
      66                 :            :  */
      67                 :         11 : static enum err derive_common_iv(struct common_context *cc)
      68                 :            : {
      69         [ -  + ]:         11 :         TRY(derive(cc, &EMPTY_ARRAY, IV, &cc->common_iv));
      70                 :         11 :         PRINT_ARRAY("Common IV", cc->common_iv.ptr, cc->common_iv.len);
      71                 :         11 :         return ok;
      72                 :            : }
      73                 :            : 
      74                 :            : /**
      75                 :            :  * @brief    Derives the Sender Key 
      76                 :            :  * @param    cc    pointer to the common context
      77                 :            :  * @param    sc    pointer to the sender context
      78                 :            :  * @return   err
      79                 :            :  */
      80                 :         11 : static enum err derive_sender_key(struct common_context *cc,
      81                 :            :                                   struct sender_context *sc)
      82                 :            : {
      83         [ -  + ]:         11 :         TRY(derive(cc, &sc->sender_id, KEY, &sc->sender_key));
      84                 :         11 :         PRINT_ARRAY("Sender Key", sc->sender_key.ptr, sc->sender_key.len);
      85                 :         11 :         return ok;
      86                 :            : }
      87                 :            : 
      88                 :            : /**
      89                 :            :  * @brief    Derives the Recipient Key 
      90                 :            :  * @param    cc    pointer to the common context
      91                 :            :  * @param    sc    pointer to the recipient context
      92                 :            :  * @return   err
      93                 :            :  */
      94                 :         11 : static enum err derive_recipient_key(struct common_context *cc,
      95                 :            :                                      struct recipient_context *rc)
      96                 :            : {
      97         [ -  + ]:         11 :         TRY(derive(cc, &rc->recipient_id, KEY, &rc->recipient_key));
      98                 :            : 
      99                 :         11 :         PRINT_ARRAY("Recipient Key", rc->recipient_key.ptr,
     100                 :            :                     rc->recipient_key.len);
     101                 :         11 :         return ok;
     102                 :            : }
     103                 :            : 
     104                 :         13 : enum err oscore_context_init(struct oscore_init_params *params,
     105                 :            :                              struct context *c)
     106                 :            : {
     107                 :            :         /*derive common context************************************************/
     108                 :            : 
     109         [ +  + ]:         13 :         if (params->aead_alg != OSCORE_AES_CCM_16_64_128) {
     110                 :          1 :                 return oscore_invalid_algorithm_aead;
     111                 :            :         } else {
     112                 :         12 :                 c->cc.aead_alg =
     113                 :            :                         OSCORE_AES_CCM_16_64_128; /*that's the default*/
     114                 :            :         }
     115                 :            : 
     116         [ +  + ]:         12 :         if (params->hkdf != OSCORE_SHA_256) {
     117                 :          1 :                 return oscore_invalid_algorithm_hkdf;
     118                 :            :         } else {
     119                 :         11 :                 c->cc.kdf = OSCORE_SHA_256; /*that's the default*/
     120                 :            :         }
     121                 :            : 
     122                 :         11 :         c->cc.fresh_master_secret_salt = params->fresh_master_secret_salt;
     123                 :         11 :         c->cc.master_secret = params->master_secret;
     124                 :         11 :         c->cc.master_salt = params->master_salt;
     125                 :         11 :         c->cc.id_context = params->id_context;
     126                 :         11 :         c->cc.common_iv.len = sizeof(c->cc.common_iv_buf);
     127                 :         11 :         c->cc.common_iv.ptr = c->cc.common_iv_buf;
     128         [ -  + ]:         11 :         TRY(derive_common_iv(&c->cc));
     129                 :            : 
     130                 :            :         /*derive Recipient Context*********************************************/
     131                 :         11 :         c->rc.notification_num_initialized = false;
     132                 :         11 :         server_replay_window_init(&c->rc.replay_window);
     133                 :         11 :         c->rc.recipient_id.len = params->recipient_id.len;
     134                 :         11 :         c->rc.recipient_id.ptr = c->rc.recipient_id_buf;
     135                 :         11 :         memcpy(c->rc.recipient_id.ptr, params->recipient_id.ptr,
     136                 :         11 :                params->recipient_id.len);
     137                 :         11 :         c->rc.recipient_key.len = sizeof(c->rc.recipient_key_buf);
     138                 :         11 :         c->rc.recipient_key.ptr = c->rc.recipient_key_buf;
     139         [ -  + ]:         11 :         TRY(derive_recipient_key(&c->cc, &c->rc));
     140                 :            : 
     141                 :            :         /*derive Sender Context************************************************/
     142                 :         11 :         c->sc.sender_id = params->sender_id;
     143                 :         11 :         c->sc.sender_key.len = sizeof(c->sc.sender_key_buf);
     144                 :         11 :         c->sc.sender_key.ptr = c->sc.sender_key_buf;
     145                 :         11 :         struct nvm_key_t nvm_key = { .sender_id = c->sc.sender_id,
     146                 :            :                                      .recipient_id = c->rc.recipient_id,
     147                 :            :                                      .id_context = c->cc.id_context };
     148                 :            : 
     149         [ -  + ]:         11 :         TRY(ssn_init(&nvm_key, &c->sc.ssn, params->fresh_master_secret_salt));
     150         [ -  + ]:         11 :         TRY(derive_sender_key(&c->cc, &c->sc));
     151                 :            : 
     152                 :            :         /*set up the request response context**********************************/
     153                 :         11 :         oscore_interactions_init(c->rrc.interactions);
     154                 :         11 :         c->rrc.nonce.len = sizeof(c->rrc.nonce_buf);
     155                 :         11 :         c->rrc.nonce.ptr = c->rrc.nonce_buf;
     156                 :         11 :         c->rrc.echo_opt_val.len = sizeof(c->rrc.echo_opt_val_buf);
     157                 :         11 :         c->rrc.echo_opt_val.ptr = c->rrc.echo_opt_val_buf;
     158                 :            : 
     159                 :            :         /* no ECHO challenge needed if the context is fresh */
     160                 :         11 :         c->rrc.echo_state_machine =
     161         [ +  + ]:         11 :                 (params->fresh_master_secret_salt ? ECHO_SYNCHRONIZED :
     162                 :            :                                                     ECHO_REBOOT);
     163                 :            : 
     164                 :         11 :         return ok;
     165                 :            : }
     166                 :            : 
     167                 :         33 : enum err check_context_freshness(struct context *c)
     168                 :            : {
     169         [ -  + ]:         33 :         if (NULL == c) {
     170                 :          0 :                 return wrong_parameter;
     171                 :            :         }
     172                 :            : 
     173                 :            :         /* "If the Sender Sequence Number exceeds the maximum, the endpoint MUST NOT
     174                 :            :            process any more messages with the given Sender Context."
     175                 :            :            For more info, refer to RFC 8613 p. 7.2.1. */
     176         [ -  + ]:         33 :         if (c->sc.ssn >= OSCORE_SSN_OVERFLOW_VALUE) {
     177                 :          0 :                 PRINT_MSG(
     178                 :            :                         "Sender Sequence Number reached its limit. New security context must be established.\n");
     179                 :          0 :                 return oscore_ssn_overflow;
     180                 :            :         }
     181                 :         33 :         return ok;
     182                 :            : }
     183                 :            : 
     184                 :         21 : enum err ssn2piv(uint64_t ssn, struct byte_array *piv)
     185                 :            : {
     186   [ +  +  +  +  :         21 :         if ((NULL == piv) || (NULL == piv->ptr) ||
                   +  + ]
     187                 :            :             (ssn > MAX_PIV_FIELD_VALUE)) {
     188                 :          3 :                 return wrong_parameter;
     189                 :            :         }
     190                 :            : 
     191                 :            :         static uint8_t tmp_piv[MAX_PIV_LEN];
     192                 :         18 :         uint8_t len = 0;
     193         [ +  + ]:         41 :         while (ssn > 0) {
     194                 :         23 :                 tmp_piv[len] = (uint8_t)(ssn & 0xFF);
     195                 :         23 :                 len++;
     196                 :         23 :                 ssn >>= 8;
     197                 :            :         }
     198                 :            : 
     199         [ +  + ]:         18 :         if (len == 0) {
     200                 :            :                 //if the sender seq number is 0 piv has value 0 and length 1
     201                 :          3 :                 piv->ptr[0] = 0;
     202                 :          3 :                 piv->len = 1;
     203                 :            :         } else {
     204                 :            :                 //PIV is encoded in big endian
     205         [ +  + ]:         38 :                 for (uint8_t pos = 0; pos < len; pos++) {
     206                 :         23 :                         piv->ptr[pos] = tmp_piv[len - 1 - pos];
     207                 :            :                 }
     208                 :         15 :                 piv->len = len;
     209                 :            :         }
     210                 :         18 :         return ok;
     211                 :            : }
     212                 :            : 
     213                 :         18 : enum err piv2ssn(struct byte_array *piv, uint64_t *ssn)
     214                 :            : {
     215   [ +  +  +  + ]:         18 :         if ((NULL == ssn) || (NULL == piv)) {
     216                 :          2 :                 return wrong_parameter;
     217                 :            :         }
     218                 :            : 
     219                 :         16 :         uint8_t *value = piv->ptr;
     220                 :         16 :         uint32_t len = piv->len;
     221         [ +  + ]:         16 :         if (len > MAX_PIV_LEN) {
     222                 :          1 :                 return wrong_parameter;
     223                 :            :         }
     224                 :            : 
     225                 :         15 :         uint64_t result = 0;
     226         [ +  + ]:         15 :         if (NULL != value) {
     227                 :            :                 //PIV is encoded in big endian
     228         [ +  + ]:         34 :                 for (uint32_t pos = 0; pos < len; pos++) {
     229                 :         21 :                         result += (uint64_t)(value[pos])
     230                 :         21 :                                   << (8 * (len - 1 - pos));
     231                 :            :                 }
     232                 :            :         }
     233                 :         15 :         *ssn = result;
     234                 :         15 :         return ok;
     235                 :            : }

Generated by: LCOV version 1.14