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 <stdbool.h>
13 #include <stdint.h>
14 #include <stdio.h>
15 #include <string.h>
16 
17 #include "oscore.h"
18 
19 #include "oscore/aad.h"
20 #include "oscore/oscore_coap.h"
21 #include "oscore/nonce.h"
22 #include "oscore/option.h"
23 #include "oscore/oscore_cose.h"
24 #include "oscore/security_context.h"
25 
26 #include "common/byte_array.h"
27 #include "common/oscore_edhoc_error.h"
28 #include "common/memcpy_s.h"
29 #include "common/print_util.h"
30 
31 /**
32  * @brief Parse all received options to find the OSCORE_option. If it doesn't  * have OSCORE option, then this packet is a normal CoAP. If it does have, it's * an OSCORE packet, and then parse the compressed OSCORE_option value to get  * value of PIV, KID and KID context of the client.
33  * @param in: input OSCORE packet
34  * @param out: pointer output compressed OSCORE_option
35  * @return error types or is or not OSCORE packet
36  */
37 static inline enum err
oscore_option_parser(struct o_coap_packet * in,struct compressed_oscore_option * out,bool * oscore_pkt)38 oscore_option_parser(struct o_coap_packet *in,
39 		     struct compressed_oscore_option *out, bool *oscore_pkt)
40 {
41 	uint8_t temp_option_count = in->options_cnt;
42 	struct o_coap_option *temp_options = in->options;
43 	uint8_t temp_option_num = 0;
44 	uint8_t *temp_current_option_value_ptr;
45 	uint8_t temp_kid_len = 0;
46 
47 	*oscore_pkt = false;
48 
49 	for (uint8_t i = 0; i < temp_option_count; i++) {
50 		temp_option_num = temp_options[i].option_number;
51 		temp_kid_len = temp_options[i].len;
52 
53 		/* Check current option is OSCORE_option or not */
54 		if (temp_option_num == COAP_OPTION_OSCORE) {
55 			if (temp_options[i].len == 0) {
56 				/* No OSCORE option value*/
57 				out->h = 0;
58 				out->k = 0;
59 				out->n = 0;
60 				//				out->KID_len = 0;
61 				//				out->KIDC_len = 0;
62 				//				out->PIV = NULL;
63 				//				out->KID = NULL;
64 				//				out->KID_context = NULL;
65 			} else {
66 				/* Get address of current option value*/
67 				temp_current_option_value_ptr =
68 					temp_options[i].value;
69 				/* Parse first byte of OSCORE value*/
70 				out->h = ((*temp_current_option_value_ptr) &
71 					  COMP_OSCORE_OPT_KIDC_H_MASK) >>
72 					 COMP_OSCORE_OPT_KIDC_H_OFFSET;
73 				out->k = ((*temp_current_option_value_ptr) &
74 					  COMP_OSCORE_OPT_KID_K_MASK) >>
75 					 COMP_OSCORE_OPT_KID_K_OFFSET;
76 				out->n = ((*temp_current_option_value_ptr) &
77 					  COMP_OSCORE_OPT_PIV_N_MASK) >>
78 					 COMP_OSCORE_OPT_PIV_N_OFFSET;
79 				temp_current_option_value_ptr++;
80 				temp_kid_len--;
81 
82 				/* Get PIV */
83 				switch (out->n) {
84 				case 0:
85 					/* NO PIV in COSE object*/
86 					out->piv.ptr = NULL;
87 					break;
88 				case 6:
89 				case 7:
90 					/* ERROR: Byte length of PIV not right, max. 5 bytes */
91 					return oscore_inpkt_invalid_piv;
92 					break;
93 				default:
94 					out->piv.ptr =
95 						temp_current_option_value_ptr;
96 					out->piv.len = out->n;
97 					temp_current_option_value_ptr += out->n;
98 					temp_kid_len = (uint8_t)(temp_kid_len -
99 								 out->n);
100 					break;
101 				}
102 
103 				/* Get KID context */
104 				if (out->h == 0) {
105 					out->kid_context.len = 0;
106 					out->kid_context.ptr = NULL;
107 				} else {
108 					out->kid_context.len =
109 						*temp_current_option_value_ptr;
110 					out->kid_context.ptr =
111 						++temp_current_option_value_ptr;
112 					temp_current_option_value_ptr +=
113 						out->kid_context.len;
114 					temp_kid_len =
115 						(uint8_t)(temp_kid_len -
116 							  (out->kid_context.len + 1));
117 				}
118 
119 				/* Get KID */
120 				if (out->k == 0) {
121 					out->kid.len = 0;
122 					out->kid.ptr = NULL;
123 				} else {
124 					out->kid.len = temp_kid_len;
125 					out->kid.ptr =
126 						temp_current_option_value_ptr;
127 				}
128 			}
129 
130 			*oscore_pkt = true;
131 		}
132 	}
133 
134 	return ok;
135 }
136 
137 /**
138  * @brief Decrypt the OSCORE payload (ciphertext)
139  * @param out_plaintext: output plaintext
140  * @param received_piv_kid_context: received PIV, KID and KID context, will be used to calculate AEAD nonce and AAD
141  * @param oscore_packet: complete OSCORE packet which contains the ciphertext to be decrypted
142  * @return void
143  */
payload_decrypt(struct context * c,struct byte_array * out_plaintext,struct o_coap_packet * oscore_packet)144 static inline enum err payload_decrypt(struct context *c,
145 				       struct byte_array *out_plaintext,
146 				       struct o_coap_packet *oscore_packet)
147 {
148 	struct byte_array oscore_ciphertext = {
149 		.len = oscore_packet->payload_len,
150 		.ptr = oscore_packet->payload,
151 	};
152 	return oscore_cose_decrypt(&oscore_ciphertext, out_plaintext, &c->rrc.nonce,
153 			    &c->rrc.aad, &c->rc.recipient_key);
154 }
155 
156 /**
157  * @brief Reorder E-options and other U-options, and update their delta, and combine them all to normal CoAP packet
158  * @param in_oscore_packet: input OSCORE, which contains U-options
159  * @param E_options: input pointer to E-options array
160  * @param E_options_cnt: count number of input E-options
161  * @param out: output pointer to CoAP packet, which will have all reordered options
162  * @return ok or error code
163  */
164 static inline enum err
options_from_oscore_reorder(struct o_coap_packet * in_oscore_packet,struct o_coap_option * E_options,uint8_t E_options_cnt,struct o_coap_packet * out)165 options_from_oscore_reorder(struct o_coap_packet *in_oscore_packet,
166 			    struct o_coap_option *E_options,
167 			    uint8_t E_options_cnt, struct o_coap_packet *out)
168 {
169 	uint16_t temp_delta_sum = 0;
170 	uint8_t temp_opt_cnt =
171 		(uint8_t)(in_oscore_packet->options_cnt + E_options_cnt);
172 	uint8_t o_coap_opt_cnt = (uint8_t)(temp_opt_cnt - 1);
173 
174 	/* Get all option numbers */
175 	if (o_coap_opt_cnt > 0) {
176 		TRY(check_buffer_size(MAX_OPTION_COUNT, o_coap_opt_cnt));
177 		uint8_t temp_opt_number[MAX_OPTION_COUNT];
178 		memset(temp_opt_number, 0, o_coap_opt_cnt);
179 
180 		/* Get all option numbers but discard OSCORE option */
181 		uint8_t j = 0;
182 		for (uint8_t i = 0; i < o_coap_opt_cnt + 1; i++) {
183 			if (i < in_oscore_packet->options_cnt) {
184 				if (in_oscore_packet->options[i].option_number !=
185 				    COAP_OPTION_OSCORE)
186 					temp_opt_number[j++] =
187 						in_oscore_packet->options[i]
188 							.option_number;
189 			} else {
190 				temp_opt_number[j++] =
191 					E_options[i -
192 						  in_oscore_packet->options_cnt]
193 						.option_number;
194 			}
195 		}
196 
197 		/* Reorder the option numbers from minimum to maximum */
198 		// uint8_t min_opt_number;
199 		for (uint8_t i = 0; i < o_coap_opt_cnt; i++) {
200 			uint8_t ipp = (uint8_t)(i + 1);
201 			for (uint8_t k = ipp; k < o_coap_opt_cnt; k++) {
202 				if (temp_opt_number[i] > temp_opt_number[k]) {
203 					uint8_t temp;
204 					temp = temp_opt_number[i];
205 					temp_opt_number[i] = temp_opt_number[k];
206 					temp_opt_number[k] = temp;
207 				}
208 			}
209 		}
210 
211 		/* Reset output CoAP options count */
212 		out->options_cnt = 0;
213 
214 		/* Copy all U-options and E-options in increasing number sequence*/
215 		uint8_t U_opt_idx = 0;
216 		uint8_t E_opt_idx = 0;
217 		for (uint8_t i = 0; i < o_coap_opt_cnt; i++) {
218 			if (temp_opt_number[i] ==
219 			    in_oscore_packet->options[U_opt_idx].option_number) {
220 				out->options[out->options_cnt].delta =
221 					(uint16_t)(in_oscore_packet
222 							   ->options[U_opt_idx]
223 							   .option_number -
224 						   temp_delta_sum);
225 				out->options[out->options_cnt].len =
226 					in_oscore_packet->options[U_opt_idx].len;
227 				out->options[out->options_cnt].option_number =
228 					in_oscore_packet->options[U_opt_idx]
229 						.option_number;
230 				out->options[out->options_cnt].value =
231 					in_oscore_packet->options[U_opt_idx]
232 						.value;
233 
234 				temp_delta_sum =
235 					(uint16_t)(temp_delta_sum +
236 						   out->options[out->options_cnt]
237 							   .delta);
238 				out->options_cnt++;
239 				U_opt_idx++;
240 				continue;
241 			} else if (temp_opt_number[i] ==
242 				   E_options[E_opt_idx].option_number) {
243 				out->options[out->options_cnt].delta =
244 					(uint16_t)(E_options[E_opt_idx]
245 							   .option_number -
246 						   temp_delta_sum);
247 				out->options[out->options_cnt].len =
248 					E_options[E_opt_idx].len;
249 				out->options[out->options_cnt].option_number =
250 					E_options[E_opt_idx].option_number;
251 				out->options[out->options_cnt].value =
252 					E_options[E_opt_idx].value;
253 
254 				temp_delta_sum =
255 					(uint16_t)(temp_delta_sum +
256 						   out->options[out->options_cnt]
257 							   .delta);
258 				out->options_cnt++;
259 				E_opt_idx++;
260 				continue;
261 			}
262 		}
263 	} else {
264 		/* No any options! */
265 		out->options_cnt = 0;
266 	}
267 	return ok;
268 }
269 
270 /**
271  * @brief Parse incoming options byte string into options structure
272  * @param in_data: pointer to input data in byte string format
273  * @param in_data_len: length of input byte string
274  * @param out_options: pointer to output options structure array
275  * @param out_options_count: count number of output options
276  * @return  err
277  */
278 static inline enum err
oscore_packet_options_parser(uint8_t * in_data,uint16_t in_data_len,struct o_coap_option * out_options,uint8_t * out_options_count)279 oscore_packet_options_parser(uint8_t *in_data, uint16_t in_data_len,
280 			     struct o_coap_option *out_options,
281 			     uint8_t *out_options_count)
282 {
283 	uint8_t *temp_options_ptr = in_data;
284 	uint8_t temp_options_count = 0;
285 	uint8_t temp_option_header_len = 0;
286 	uint8_t temp_option_delta = 0;
287 	uint8_t temp_option_len = 0;
288 	uint8_t temp_option_number = 0;
289 
290 	// Go through the in_data to find out how many options are there
291 	uint16_t i = 0;
292 	while (i < in_data_len) {
293 		temp_option_header_len = 1;
294 		// Parser first byte,lower 4 bits for option value length and higher 4 bits for option delta
295 		temp_option_delta = ((*temp_options_ptr) & 0xF0) >> 4;
296 		temp_option_len = (*temp_options_ptr) & 0x0F;
297 
298 		temp_options_ptr++;
299 
300 		// Special cases for extended option delta: 13 - 1 extra delta byte, 14 - 2 extra delta bytes, 15 - reserved
301 		switch (temp_option_delta) {
302 		case 13:
303 			temp_option_header_len =
304 				(uint8_t)(temp_option_header_len + 1);
305 			temp_option_delta = (uint8_t)(*temp_options_ptr - 13);
306 			temp_options_ptr += 1;
307 			break;
308 		case 14:
309 			temp_option_header_len =
310 				(uint8_t)(temp_option_header_len + 2);
311 			temp_option_delta =
312 				(uint8_t)(((*temp_options_ptr) << 8 |
313 					   *(temp_options_ptr + 1)) -
314 					  269);
315 			temp_options_ptr += 2;
316 			break;
317 		case 15:
318 			// ERROR
319 			return oscore_inpkt_invalid_option_delta;
320 			break;
321 		default:
322 			break;
323 		}
324 
325 		// Special cases for extended option value length: 13 - 1 extra length byte, 14 - 2 extra length bytes, 15 - reserved
326 		switch (temp_option_len) {
327 		case 13:
328 			temp_option_header_len =
329 				(uint8_t)(temp_option_header_len + 1);
330 			temp_option_len = (uint8_t)(*temp_options_ptr - 13);
331 			temp_options_ptr += 1;
332 			break;
333 		case 14:
334 			temp_option_header_len =
335 				(uint8_t)(temp_option_header_len + 2);
336 			temp_option_len = (uint8_t)(((*temp_options_ptr) << 8 |
337 						     *(temp_options_ptr + 1)) -
338 						    269);
339 			temp_options_ptr += 2;
340 			break;
341 		case 15:
342 			// ERROR
343 			return oscore_inpkt_invalid_optionlen;
344 			break;
345 		default:
346 			break;
347 		}
348 
349 		temp_option_number =
350 			(uint8_t)(temp_option_number + temp_option_delta);
351 		// Update in output options
352 		out_options[temp_options_count].delta = temp_option_delta;
353 		out_options[temp_options_count].len = temp_option_len;
354 		out_options[temp_options_count].option_number =
355 			temp_option_number;
356 		if (temp_option_len == 0)
357 			out_options[temp_options_count].value = NULL;
358 		else
359 			out_options[temp_options_count].value =
360 				temp_options_ptr;
361 
362 		// Update parameters
363 		i = (uint16_t)(i + temp_option_header_len + temp_option_len);
364 		temp_options_ptr += temp_option_len;
365 		temp_options_count++;
366 	}
367 
368 	// Assign options count number
369 	*out_options_count = temp_options_count;
370 
371 	return ok;
372 }
373 
374 /**
375  * @brief Parse the decrypted OSCORE payload into code, E-options and original unprotected CoAP payload
376  * @param in_payload: input decrypted payload
377  * @param out_code: pointer to code number of the request
378  * @param out_E_options: output pointer to an array of E-options
379  * @param E_options_cnt: count number of E-options
380  * @param out_o_coap_payload: output pointer original unprotected CoAP payload
381  * @return  err
382  */
oscore_decrypted_payload_parser(struct byte_array * in_payload,uint8_t * out_code,struct o_coap_option * out_E_options,uint8_t * E_options_cnt,struct byte_array * out_o_coap_payload)383 static inline enum err oscore_decrypted_payload_parser(
384 	struct byte_array *in_payload, uint8_t *out_code,
385 	struct o_coap_option *out_E_options, uint8_t *E_options_cnt,
386 	struct byte_array *out_o_coap_payload)
387 {
388 	uint8_t *temp_payload_ptr = in_payload->ptr;
389 	uint32_t temp_payload_len = in_payload->len;
390 
391 	/* Code */
392 	*out_code = *(temp_payload_ptr++);
393 	temp_payload_len--;
394 
395 	/* Check whether E-options exists */
396 	if (*temp_payload_ptr == 0xFF || temp_payload_len == 0) {
397 		*E_options_cnt = 0;
398 	} else {
399 		uint8_t *temp_option_ptr = temp_payload_ptr;
400 		/* Length of E-options byte string*/
401 		uint16_t options_len = 0;
402 
403 		/* Move the temp_ptr to the original unprotected payload */
404 		while (*temp_payload_ptr != 0xFF && temp_payload_len != 0) {
405 			temp_payload_len--;
406 			temp_payload_ptr++;
407 			options_len++;
408 		}
409 
410 		/* Parser all options */
411 		if (options_len > 0) {
412 			TRY(oscore_packet_options_parser(
413 				temp_option_ptr, options_len, out_E_options,
414 				E_options_cnt));
415 
416 		} else
417 			*E_options_cnt = 0;
418 	}
419 
420 	/* Unprotected CoAP payload */
421 	++temp_payload_ptr;
422 	if (temp_payload_len == 0) {
423 		out_o_coap_payload->len = 0;
424 		out_o_coap_payload->ptr = NULL;
425 	} else {
426 		/* Minus byte of 0xFF */
427 		out_o_coap_payload->len = (uint32_t)(temp_payload_len - 1);
428 		out_o_coap_payload->ptr = temp_payload_ptr;
429 	}
430 
431 	return ok;
432 }
433 
434 /**
435  * @brief Generate CoAP packet from OSCORE packet
436  * @param decrypted_payload: decrypted OSCORE payload, which contains code, E-options and original unprotected CoAP payload
437  * @param in_oscore_packet:  input OSCORE packet
438  * @param out: pointer to output CoAP packet
439  * @return
440  */
441 static inline enum err
o_coap_pkg_generate(struct byte_array * decrypted_payload,struct o_coap_packet * in_oscore_packet,struct o_coap_packet * out)442 o_coap_pkg_generate(struct byte_array *decrypted_payload,
443 		    struct o_coap_packet *in_oscore_packet,
444 		    struct o_coap_packet *out)
445 {
446 	uint8_t code = 0;
447 	struct byte_array unprotected_o_coap_payload = {
448 		.len = 0,
449 		.ptr = NULL,
450 	};
451 	struct o_coap_option E_options[10];
452 	uint8_t E_options_cnt = 0;
453 
454 	/* Parse decrypted payload: code + options + unprotected CoAP payload*/
455 	TRY(oscore_decrypted_payload_parser(decrypted_payload, &code, E_options,
456 					    &E_options_cnt,
457 					    &unprotected_o_coap_payload));
458 
459 	/* Copy each items from OSCORE packet to CoAP packet */
460 	/* Header */
461 	out->header.ver = in_oscore_packet->header.ver;
462 	out->header.type = in_oscore_packet->header.type;
463 	out->header.TKL = in_oscore_packet->header.TKL;
464 	out->header.code = code;
465 	out->header.MID = in_oscore_packet->header.MID;
466 
467 	/* Token */
468 	if (in_oscore_packet->header.TKL == 0)
469 		out->token = NULL;
470 	else
471 		out->token = in_oscore_packet->token;
472 
473 	/* Payload */
474 	out->payload_len = unprotected_o_coap_payload.len;
475 	if (unprotected_o_coap_payload.len == 0)
476 		out->payload = NULL;
477 	else
478 		out->payload = unprotected_o_coap_payload.ptr;
479 
480 	/* reorder all options, and copy it to output coap packet */
481 	TRY(options_from_oscore_reorder(in_oscore_packet, E_options,
482 					E_options_cnt, out));
483 	return ok;
484 }
485 
is_request(struct o_coap_packet * packet)486 static bool is_request(struct o_coap_packet *packet)
487 {
488 	if ((CODE_CLASS_MASK & packet->header.code) == REQUEST_CLASS) {
489 		return true;
490 	} else {
491 		return false;
492 	}
493 }
494 
replay_check(uint64_t sender_sequence_number,uint64_t * replay_window,uint8_t replay_window_len)495 static inline enum err replay_check(uint64_t sender_sequence_number,
496 				    uint64_t *replay_window,
497 				    uint8_t replay_window_len)
498 {
499 	bool first_run = true;
500 
501 	if (first_run) {
502 		first_run = false;
503 		return ok;
504 	} else {
505 		/*if the sender sequence number is bigger than the
506 		right most element -> all good */
507 		if (sender_sequence_number >
508 		    replay_window[replay_window_len - 1]) {
509 			return ok;
510 		}
511 
512 		/*if the sender sequence number is smaller than the
513 		left most element -> a replay is detected*/
514 		if (sender_sequence_number < replay_window[0]) {
515 			return replayed_packed_received;
516 		}
517 
518 		/*if the sender sequence number is in the replay window
519 		-> a replay is detected*/
520 		for (uint8_t i = 0; i < replay_window_len; i++) {
521 			if (sender_sequence_number == replay_window[i]) {
522 				return replayed_packed_received;
523 			}
524 		}
525 	}
526 
527 	return ok;
528 }
529 
insert_sender_seq_number(uint64_t sender_seq_number,uint64_t * replay_window,uint8_t position)530 static void insert_sender_seq_number(uint64_t sender_seq_number,
531 				     uint64_t *replay_window, uint8_t position)
532 {
533 	/*shift all old values to the left*/
534 	for (uint8_t j = 0; j < position; j++) {
535 		replay_window[j] = replay_window[j + 1];
536 	}
537 	/*insert the new sender sequence number at a given position*/
538 	replay_window[position] = sender_seq_number;
539 }
540 
update_replay_window(uint64_t sender_seq_number,uint64_t * replay_window,uint8_t replay_window_len)541 static void update_replay_window(uint64_t sender_seq_number,
542 				 uint64_t *replay_window,
543 				 uint8_t replay_window_len)
544 {
545 	for (uint8_t i = 0; i < replay_window_len - 1; i++) {
546 		if ((replay_window[i] < sender_seq_number) &&
547 		    (sender_seq_number < replay_window[i + 1])) {
548 			insert_sender_seq_number(sender_seq_number,
549 						 replay_window, i);
550 			PRINT_ARRAY("Replay window:", (uint8_t *)replay_window,
551 				    (uint32_t)(replay_window_len *
552 					       sizeof(replay_window[0])));
553 			return;
554 		}
555 	}
556 	insert_sender_seq_number(sender_seq_number, replay_window,
557 				 (uint8_t)(replay_window_len - 1));
558 	PRINT_ARRAY("Replay window:", (uint8_t *)replay_window,
559 		    (uint32_t)(replay_window_len * sizeof(replay_window[0])));
560 }
561 
oscore2coap(uint8_t * buf_in,uint32_t buf_in_len,uint8_t * buf_out,uint32_t * buf_out_len,bool * oscore_pkg_flag,struct context * c)562 enum err oscore2coap(uint8_t *buf_in, uint32_t buf_in_len, uint8_t *buf_out,
563 		     uint32_t *buf_out_len, bool *oscore_pkg_flag,
564 		     struct context *c)
565 {
566 	enum err r = ok;
567 	struct o_coap_packet oscore_packet;
568 	struct compressed_oscore_option oscore_option;
569 	struct byte_array buf;
570 
571 	PRINT_MSG("\n\n\noscore2coap***************************************\n");
572 	PRINT_ARRAY("Input OSCORE packet", buf_in, buf_in_len);
573 
574 	buf.ptr = buf_in;
575 	buf.len = buf_in_len;
576 
577 	/*Parse the incoming message (buf_in) into a CoAP struct*/
578 	TRY(buf2coap(&buf, &oscore_packet));
579 
580 	/* Check if the packet is OSCORE packet and if so parse the OSCORE option */
581 	TRY(oscore_option_parser(&oscore_packet, &oscore_option,
582 				 oscore_pkg_flag));
583 
584 	/* If the incoming packet is OSCORE packet -- analyze and and decrypt it. */
585 	if (*oscore_pkg_flag) {
586 		/*In requests the OSCORE packet contains at least a KID = sender ID
587         and eventually sender sequence number*/
588 		if (is_request(&oscore_packet)) {
589 			/*Check that the recipient context c->rc has a  Recipient ID that
590 			 matches the received with the oscore option KID (Sender ID).
591 			 If this is not true return an error which indicates the caller
592 			 application to tray another context. This is useful when the caller
593 			 app doesn't know in advance to which context an incoming packet
594              belongs.*/
595 			if (!array_equals(&c->rc.recipient_id,
596 					  &oscore_option.kid)) {
597 				return oscore_kid_recipent_id_mismatch;
598 			}
599 
600 			/*check is the packet is replayed*/
601 			TRY(replay_check(*oscore_option.piv.ptr,
602 					 c->rc.replay_window,
603 					 c->rc.replay_window_len));
604 
605 			/*If this is a request message we need to calculate the nonce, aad
606             and eventually update the Common IV, Sender and Recipient Keys*/
607 			TRY(context_update(
608 				SERVER,
609 				(struct o_coap_option *)&oscore_packet.options,
610 				oscore_packet.options_cnt, &oscore_option.piv,
611 				&oscore_option.kid_context, c));
612 		}
613 
614 		/* Setup buffer for the plaintext. The plaintext is shorter than the ciphertext because of the authentication tag*/
615 		uint32_t plaintext_bytes_len =
616 			oscore_packet.payload_len - AUTH_TAG_LEN;
617 		TRY(check_buffer_size(MAX_PLAINTEXT_LEN, plaintext_bytes_len));
618 		uint8_t plaintext_bytes[MAX_PLAINTEXT_LEN];
619 		struct byte_array plaintext = {
620 			.len = plaintext_bytes_len,
621 			.ptr = plaintext_bytes,
622 		};
623 
624 		/* Decrypt payload */
625 		r = payload_decrypt(c, &plaintext, &oscore_packet);
626 		if (r == ok) {
627 			/*update the replay window after the decryption*/
628 			if (is_request(&oscore_packet)) {
629 				update_replay_window(*oscore_option.piv.ptr,
630 						     c->rc.replay_window,
631 						     c->rc.replay_window_len);
632 			}
633 		} else {
634 			return r;
635 		}
636 
637 		/* Generate corresponding CoAP packet */
638 		struct o_coap_packet o_coap_packet;
639 		TRY(o_coap_pkg_generate(&plaintext, &oscore_packet,
640 					&o_coap_packet));
641 
642 		/*Convert to byte string*/
643 		r = coap2buf(&o_coap_packet, buf_out, buf_out_len);
644 	}
645 	return r;
646 }
647