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 		   true);
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->ptr, in_ciphertext->len, key->ptr,
78 		 key->len, nonce->ptr, nonce->len, aad.ptr, aad.len,
79 		 out_plaintext->ptr, out_plaintext->len, tag.ptr, tag.len));
80 
81 	PRINT_ARRAY("Decrypted plaintext", out_plaintext->ptr,
82 		    out_plaintext->len);
83 	return ok;
84 }
85 
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)86 enum err oscore_cose_encrypt(struct byte_array *in_plaintext,
87 			     struct byte_array *out_ciphertext,
88 			     struct byte_array *nonce,
89 			     struct byte_array *sender_aad,
90 			     struct byte_array *key)
91 {
92 	/* get enc_structure  */
93 	uint32_t aad_len = sender_aad->len + ENCRYPT0_ENCODING_OVERHEAD;
94 	BYTE_ARRAY_NEW(aad, MAX_AAD_LEN, aad_len);
95 
96 	TRY(create_enc_structure(sender_aad, &aad));
97 	PRINT_ARRAY("aad enc structure", aad.ptr, aad.len);
98 
99 	struct byte_array tag =
100 		BYTE_ARRAY_INIT(out_ciphertext->ptr + in_plaintext->len, 8);
101 
102 	TRY(aead(ENCRYPT, in_plaintext->ptr, in_plaintext->len, key->ptr,
103 		 key->len, nonce->ptr, nonce->len, aad.ptr, aad.len,
104 		 out_ciphertext->ptr, out_ciphertext->len - tag.len, tag.ptr,
105 		 tag.len));
106 
107 	PRINT_ARRAY("tag", tag.ptr, tag.len);
108 	PRINT_ARRAY("Ciphertext", out_ciphertext->ptr, out_ciphertext->len);
109 	return ok;
110 }
111