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