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 
14 #include "oscore.h"
15 
16 #include "oscore/oscore_cose.h"
17 #include "oscore/security_context.h"
18 
19 #include "common/crypto_wrapper.h"
20 #include "common/memcpy_s.h"
21 #include "common/print_util.h"
22 
23 #include "cbor/oscore_enc_structure.h"
24 
25 /*the additional bytes in the enc_structure are constant*/
26 #define ENCRYPT0_ENCODING_OVERHEAD 16
27 
28 /**
29  * @brief Encode the input AAD to defined COSE structure
30  * @param external_aad: input aad to form COSE structure
31  * @param out: output encoded COSE byte string
32  * @return err
33  */
create_enc_structure(struct byte_array * external_aad,struct byte_array * out)34 static enum err create_enc_structure(struct byte_array *external_aad,
35 				     struct byte_array *out)
36 {
37 	struct oscore_enc_structure enc_structure;
38 
39 	uint8_t context[] = { "Encrypt0" };
40 	enc_structure.oscore_enc_structure_context.value = context;
41 	enc_structure.oscore_enc_structure_context.len =
42 		(uint32_t)strlen((char *)context);
43 	enc_structure.oscore_enc_structure_protected.value = NULL;
44 	enc_structure.oscore_enc_structure_protected.len = 0;
45 	enc_structure.oscore_enc_structure_external_aad.value =
46 		external_aad->ptr;
47 	enc_structure.oscore_enc_structure_external_aad.len =
48 		external_aad->len;
49 
50 	size_t payload_len_out = 0;
51 
52 	TRY_EXPECT(cbor_encode_oscore_enc_structure(out->ptr, out->len,
53 						    &enc_structure,
54 						    &payload_len_out),
55 		   0);
56 
57 	out->len = (uint32_t)payload_len_out;
58 	return ok;
59 }
60 
oscore_cose_decrypt(struct byte_array * in_ciphertext,struct byte_array * out_plaintext,struct byte_array * nonce,struct byte_array * recipient_aad,struct byte_array * key)61 enum err oscore_cose_decrypt(struct byte_array *in_ciphertext,
62 			     struct byte_array *out_plaintext,
63 			     struct byte_array *nonce,
64 			     struct byte_array *recipient_aad,
65 			     struct byte_array *key)
66 {
67 	/* get enc_structure */
68 	uint32_t aad_len = recipient_aad->len + ENCRYPT0_ENCODING_OVERHEAD;
69 	BYTE_ARRAY_NEW(aad, MAX_AAD_LEN, aad_len);
70 	TRY(create_enc_structure(recipient_aad, &aad));
71 	PRINT_ARRAY("AAD encoded", aad.ptr, aad.len);
72 	struct byte_array tag = BYTE_ARRAY_INIT(
73 		(in_ciphertext->ptr + in_ciphertext->len - 8), 8);
74 
75 	PRINT_ARRAY("Ciphertext", in_ciphertext->ptr, in_ciphertext->len);
76 
77 	TRY(aead(DECRYPT, in_ciphertext, key, nonce, &aad, out_plaintext,
78 		 &tag));
79 
80 	PRINT_ARRAY("Decrypted plaintext", out_plaintext->ptr,
81 		    out_plaintext->len);
82 	return ok;
83 }
84 
oscore_cose_encrypt(struct byte_array * in_plaintext,struct byte_array * out_ciphertext,struct byte_array * nonce,struct byte_array * sender_aad,struct byte_array * key)85 enum err oscore_cose_encrypt(struct byte_array *in_plaintext,
86 			     struct byte_array *out_ciphertext,
87 			     struct byte_array *nonce,
88 			     struct byte_array *sender_aad,
89 			     struct byte_array *key)
90 {
91 	/* get enc_structure  */
92 	uint32_t aad_len = sender_aad->len + ENCRYPT0_ENCODING_OVERHEAD;
93 	BYTE_ARRAY_NEW(aad, MAX_AAD_LEN, aad_len);
94 
95 	TRY(create_enc_structure(sender_aad, &aad));
96 	PRINT_ARRAY("aad enc structure", aad.ptr, aad.len);
97 
98 	struct byte_array tag =
99 		BYTE_ARRAY_INIT(out_ciphertext->ptr + in_plaintext->len, 8);
100 
101 	out_ciphertext->len -= tag.len;
102 	TRY(aead(ENCRYPT, in_plaintext, key, nonce, &aad, out_ciphertext,
103 		 &tag));
104 
105 	PRINT_ARRAY("tag", tag.ptr, tag.len);
106 	PRINT_ARRAY("Ciphertext", out_ciphertext->ptr, out_ciphertext->len);
107 	out_ciphertext->len += tag.len;
108 	PRINT_ARRAY("Ciphertext + tag", out_ciphertext->ptr,
109 		    out_ciphertext->len);
110 
111 	return ok;
112 }
113