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  */
derive(struct common_context * cc,struct byte_array * id,enum derive_type type,struct byte_array * out)41 STATIC enum err derive(struct common_context *cc, struct byte_array *id,
42 		       enum derive_type type, struct byte_array *out)
43 {
44 	BYTE_ARRAY_NEW(info, MAX_INFO_LEN, MAX_INFO_LEN);
45 	TRY(oscore_create_hkdf_info(id, &cc->id_context, cc->aead_alg, type,
46 				    &info));
47 
48 	PRINT_ARRAY("info struct", info.ptr, info.len);
49 
50 	switch (cc->kdf) {
51 	case OSCORE_SHA_256:
52 		TRY(hkdf_sha_256(&cc->master_secret, &cc->master_salt, &info,
53 				 out));
54 		break;
55 	default:
56 		return oscore_unknown_hkdf;
57 		break;
58 	}
59 	return ok;
60 }
61 
62 /**
63  * @brief    Derives the Common IV
64  * @param    cc    pointer to the common context
65  * @return   err
66  */
derive_common_iv(struct common_context * cc)67 static enum err derive_common_iv(struct common_context *cc)
68 {
69 	TRY(derive(cc, &EMPTY_ARRAY, IV, &cc->common_iv));
70 	PRINT_ARRAY("Common IV", cc->common_iv.ptr, cc->common_iv.len);
71 	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  */
derive_sender_key(struct common_context * cc,struct sender_context * sc)80 static enum err derive_sender_key(struct common_context *cc,
81 				  struct sender_context *sc)
82 {
83 	TRY(derive(cc, &sc->sender_id, KEY, &sc->sender_key));
84 	PRINT_ARRAY("Sender Key", sc->sender_key.ptr, sc->sender_key.len);
85 	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  */
derive_recipient_key(struct common_context * cc,struct recipient_context * rc)94 static enum err derive_recipient_key(struct common_context *cc,
95 				     struct recipient_context *rc)
96 {
97 	TRY(derive(cc, &rc->recipient_id, KEY, &rc->recipient_key));
98 
99 	PRINT_ARRAY("Recipient Key", rc->recipient_key.ptr,
100 		    rc->recipient_key.len);
101 	return ok;
102 }
103 
oscore_context_init(struct oscore_init_params * params,struct context * c)104 enum err oscore_context_init(struct oscore_init_params *params,
105 			     struct context *c)
106 {
107 	/*derive common context************************************************/
108 
109 	if (params->aead_alg != OSCORE_AES_CCM_16_64_128) {
110 		return oscore_invalid_algorithm_aead;
111 	} else {
112 		c->cc.aead_alg =
113 			OSCORE_AES_CCM_16_64_128; /*that's the default*/
114 	}
115 
116 	if (params->hkdf != OSCORE_SHA_256) {
117 		return oscore_invalid_algorithm_hkdf;
118 	} else {
119 		c->cc.kdf = OSCORE_SHA_256; /*that's the default*/
120 	}
121 
122         c->cc.fresh_master_secret_salt = params->fresh_master_secret_salt;
123 	c->cc.master_secret = params->master_secret;
124 	c->cc.master_salt = params->master_salt;
125 	c->cc.id_context = params->id_context;
126 	c->cc.common_iv.len = sizeof(c->cc.common_iv_buf);
127 	c->cc.common_iv.ptr = c->cc.common_iv_buf;
128 	TRY(derive_common_iv(&c->cc));
129 
130 	/*derive Recipient Context*********************************************/
131 	c->rc.notification_num_initialized = false;
132 	server_replay_window_init(&c->rc.replay_window);
133 	c->rc.recipient_id.len = params->recipient_id.len;
134 	c->rc.recipient_id.ptr = c->rc.recipient_id_buf;
135 	memcpy(c->rc.recipient_id.ptr, params->recipient_id.ptr,
136 	       params->recipient_id.len);
137 	c->rc.recipient_key.len = sizeof(c->rc.recipient_key_buf);
138 	c->rc.recipient_key.ptr = c->rc.recipient_key_buf;
139 	TRY(derive_recipient_key(&c->cc, &c->rc));
140 
141 	/*derive Sender Context************************************************/
142 	c->sc.sender_id = params->sender_id;
143 	c->sc.sender_key.len = sizeof(c->sc.sender_key_buf);
144 	c->sc.sender_key.ptr = c->sc.sender_key_buf;
145 	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 	TRY(ssn_init(&nvm_key, &c->sc.ssn, params->fresh_master_secret_salt));
150 	TRY(derive_sender_key(&c->cc, &c->sc));
151 
152 	/*set up the request response context**********************************/
153 	oscore_interactions_init(c->rrc.interactions);
154 	c->rrc.nonce.len = sizeof(c->rrc.nonce_buf);
155 	c->rrc.nonce.ptr = c->rrc.nonce_buf;
156 	c->rrc.echo_opt_val.len = sizeof(c->rrc.echo_opt_val_buf);
157 	c->rrc.echo_opt_val.ptr = c->rrc.echo_opt_val_buf;
158 
159 	/* no ECHO challenge needed if the context is fresh */
160 	c->rrc.echo_state_machine =
161 		(params->fresh_master_secret_salt ? ECHO_SYNCHRONIZED :
162 						    ECHO_REBOOT);
163 
164 	return ok;
165 }
166 
check_context_freshness(struct context * c)167 enum err check_context_freshness(struct context *c)
168 {
169 	if (NULL == c) {
170 		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 	if (c->sc.ssn >= OSCORE_SSN_OVERFLOW_VALUE) {
177 		PRINT_MSG(
178 			"Sender Sequence Number reached its limit. New security context must be established.\n");
179 		return oscore_ssn_overflow;
180 	}
181 	return ok;
182 }
183 
ssn2piv(uint64_t ssn,struct byte_array * piv)184 enum err ssn2piv(uint64_t ssn, struct byte_array *piv)
185 {
186 	if ((NULL == piv) || (NULL == piv->ptr) ||
187 	    (ssn > MAX_PIV_FIELD_VALUE)) {
188 		return wrong_parameter;
189 	}
190 
191 	static uint8_t tmp_piv[MAX_PIV_LEN];
192 	uint8_t len = 0;
193 	while (ssn > 0) {
194 		tmp_piv[len] = (uint8_t)(ssn & 0xFF);
195 		len++;
196 		ssn >>= 8;
197 	}
198 
199 	if (len == 0) {
200 		//if the sender seq number is 0 piv has value 0 and length 1
201 		piv->ptr[0] = 0;
202 		piv->len = 1;
203 	} else {
204 		//PIV is encoded in big endian
205 		for (uint8_t pos = 0; pos < len; pos++) {
206 			piv->ptr[pos] = tmp_piv[len - 1 - pos];
207 		}
208 		piv->len = len;
209 	}
210 	return ok;
211 }
212 
piv2ssn(struct byte_array * piv,uint64_t * ssn)213 enum err piv2ssn(struct byte_array *piv, uint64_t *ssn)
214 {
215 	if ((NULL == ssn) || (NULL == piv)) {
216 		return wrong_parameter;
217 	}
218 
219 	uint8_t *value = piv->ptr;
220 	uint32_t len = piv->len;
221 	if (len > MAX_PIV_LEN) {
222 		return wrong_parameter;
223 	}
224 
225 	uint64_t result = 0;
226 	if (NULL != value) {
227 		//PIV is encoded in big endian
228 		for (uint32_t pos = 0; pos < len; pos++) {
229 			result += (uint64_t)(value[pos])
230 				  << (8 * (len - 1 - pos));
231 		}
232 	}
233 	*ssn = result;
234 	return ok;
235 }
236