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