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 : : }
|