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.master_secret = params->master_secret;
123 	c->cc.master_salt = params->master_salt;
124 	c->cc.id_context = params->id_context;
125 	c->cc.common_iv.len = sizeof(c->cc.common_iv_buf);
126 	c->cc.common_iv.ptr = c->cc.common_iv_buf;
127 	TRY(derive_common_iv(&c->cc));
128 
129 	/*derive Recipient Context*********************************************/
130 	c->rc.notification_num_initialized = false;
131 	server_replay_window_init(&c->rc.replay_window);
132 	c->rc.recipient_id.len = params->recipient_id.len;
133 	c->rc.recipient_id.ptr = c->rc.recipient_id_buf;
134 	memcpy(c->rc.recipient_id.ptr, params->recipient_id.ptr,
135 	       params->recipient_id.len);
136 	c->rc.recipient_key.len = sizeof(c->rc.recipient_key_buf);
137 	c->rc.recipient_key.ptr = c->rc.recipient_key_buf;
138 	TRY(derive_recipient_key(&c->cc, &c->rc));
139 
140 	/*derive Sender Context************************************************/
141 	c->sc.sender_id = params->sender_id;
142 	c->sc.sender_key.len = sizeof(c->sc.sender_key_buf);
143 	c->sc.sender_key.ptr = c->sc.sender_key_buf;
144 	struct nvm_key_t nvm_key = { .sender_id = c->sc.sender_id,
145 				     .recipient_id = c->rc.recipient_id,
146 				     .id_context = c->cc.id_context };
147 
148 	TRY(ssn_init(&nvm_key, &c->sc.ssn, params->fresh_master_secret_salt));
149 	TRY(derive_sender_key(&c->cc, &c->sc));
150 
151 	/*set up the request response context**********************************/
152 	oscore_interactions_init(c->rrc.interactions);
153 	c->rrc.nonce.len = sizeof(c->rrc.nonce_buf);
154 	c->rrc.nonce.ptr = c->rrc.nonce_buf;
155 	c->rrc.echo_opt_val.len = sizeof(c->rrc.echo_opt_val_buf);
156 	c->rrc.echo_opt_val.ptr = c->rrc.echo_opt_val_buf;
157 
158 	/* no ECHO challenge needed if the context is fresh */
159 	c->rrc.echo_state_machine =
160 		(params->fresh_master_secret_salt ? ECHO_SYNCHRONIZED :
161 						    ECHO_REBOOT);
162 
163 	return ok;
164 }
165 
check_context_freshness(struct context * c)166 enum err check_context_freshness(struct context *c)
167 {
168 	if (NULL == c) {
169 		return wrong_parameter;
170 	}
171 
172 	/* "If the Sender Sequence Number exceeds the maximum, the endpoint MUST NOT
173 	   process any more messages with the given Sender Context."
174 	   For more info, refer to RFC 8613 p. 7.2.1. */
175 	if (c->sc.ssn >= OSCORE_SSN_OVERFLOW_VALUE) {
176 		PRINT_MSG(
177 			"Sender Sequence Number reached its limit. New security context must be established.\n");
178 		return oscore_ssn_overflow;
179 	}
180 	return ok;
181 }
182 
ssn2piv(uint64_t ssn,struct byte_array * piv)183 enum err ssn2piv(uint64_t ssn, struct byte_array *piv)
184 {
185 	if ((NULL == piv) || (NULL == piv->ptr) ||
186 	    (ssn > MAX_PIV_FIELD_VALUE)) {
187 		return wrong_parameter;
188 	}
189 
190 	static uint8_t tmp_piv[MAX_PIV_LEN];
191 	uint8_t len = 0;
192 	while (ssn > 0) {
193 		tmp_piv[len] = (uint8_t)(ssn & 0xFF);
194 		len++;
195 		ssn >>= 8;
196 	}
197 
198 	if (len == 0) {
199 		//if the sender seq number is 0 piv has value 0 and length 1
200 		piv->ptr[0] = 0;
201 		piv->len = 1;
202 	} else {
203 		//PIV is encoded in big endian
204 		for (uint8_t pos = 0; pos < len; pos++) {
205 			piv->ptr[pos] = tmp_piv[len - 1 - pos];
206 		}
207 		piv->len = len;
208 	}
209 	return ok;
210 }
211 
piv2ssn(struct byte_array * piv,uint64_t * ssn)212 enum err piv2ssn(struct byte_array *piv, uint64_t *ssn)
213 {
214 	if ((NULL == ssn) || (NULL == piv)) {
215 		return wrong_parameter;
216 	}
217 
218 	uint8_t *value = piv->ptr;
219 	uint32_t len = piv->len;
220 	if (len > MAX_PIV_LEN) {
221 		return wrong_parameter;
222 	}
223 
224 	uint64_t result = 0;
225 	if (NULL != value) {
226 		//PIV is encoded in big endian
227 		for (uint32_t pos = 0; pos < len; pos++) {
228 			result += (uint64_t)(value[pos])
229 				  << (8 * (len - 1 - pos));
230 		}
231 	}
232 	*ssn = result;
233 	return ok;
234 }
235