1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Crypto Component */
17 /** */
18 /** XCBC MAC Mode */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #include "nx_crypto_xcbc_mac.h"
24
25 /**************************************************************************/
26 /* */
27 /* FUNCTION RELEASE */
28 /* */
29 /* _nx_crypto_xcbc_xor PORTABLE C */
30 /* 6.1 */
31 /* AUTHOR */
32 /* */
33 /* Timothy Stapko, Microsoft Corporation */
34 /* */
35 /* DESCRIPTION */
36 /* */
37 /* This function performs XOR operation on the output buffer. */
38 /* */
39 /* INPUT */
40 /* */
41 /* plaintext Pointer to input plantext */
42 /* key Value to be xor'ed */
43 /* ciphertext Output buffer of 16 bytes */
44 /* */
45 /* OUTPUT */
46 /* */
47 /* None */
48 /* */
49 /* CALLS */
50 /* */
51 /* None */
52 /* */
53 /* CALLED BY */
54 /* */
55 /* _nx_crypto_xcbc_mac Perform XCBC MAC 96 hash */
56 /* */
57 /* RELEASE HISTORY */
58 /* */
59 /* DATE NAME DESCRIPTION */
60 /* */
61 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
62 /* 09-30-2020 Timothy Stapko Modified comment(s), disabled */
63 /* unaligned access by default,*/
64 /* resulting in version 6.1 */
65 /* */
66 /**************************************************************************/
_nx_crypto_xcbc_xor(UCHAR * plaintext,UCHAR * key,UCHAR * ciphertext)67 NX_CRYPTO_KEEP static VOID _nx_crypto_xcbc_xor(UCHAR *plaintext, UCHAR *key, UCHAR *ciphertext)
68 {
69 #ifdef NX_CRYPTO_ENABLE_UNALIGNED_ACCESS
70 UINT *p = (UINT *)plaintext;
71 UINT *c = (UINT *)ciphertext;
72 UINT *k = (UINT *)key;
73
74 c[0] = p[0] ^ k[0];
75 c[1] = p[1] ^ k[1];
76 c[2] = p[2] ^ k[2];
77 c[3] = p[3] ^ k[3];
78 #else
79 ciphertext[0] = plaintext[0] ^ key[0];
80 ciphertext[1] = plaintext[1] ^ key[1];
81 ciphertext[2] = plaintext[2] ^ key[2];
82 ciphertext[3] = plaintext[3] ^ key[3];
83 ciphertext[4] = plaintext[4] ^ key[4];
84 ciphertext[5] = plaintext[5] ^ key[5];
85 ciphertext[6] = plaintext[6] ^ key[6];
86 ciphertext[7] = plaintext[7] ^ key[7];
87 ciphertext[8] = plaintext[8] ^ key[8];
88 ciphertext[9] = plaintext[9] ^ key[9];
89 ciphertext[10] = plaintext[10] ^ key[10];
90 ciphertext[11] = plaintext[11] ^ key[11];
91 ciphertext[12] = plaintext[12] ^ key[12];
92 ciphertext[13] = plaintext[13] ^ key[13];
93 ciphertext[14] = plaintext[14] ^ key[14];
94 ciphertext[15] = plaintext[15] ^ key[15];
95 #endif
96 }
97
98
99 /**************************************************************************/
100 /* */
101 /* FUNCTION RELEASE */
102 /* */
103 /* _nx_crypto_xcbc_mac PORTABLE C */
104 /* 6.1 */
105 /* AUTHOR */
106 /* */
107 /* Timothy Stapko, Microsoft Corporation */
108 /* */
109 /* DESCRIPTION */
110 /* */
111 /* This function performs XCBC MAC 96 hash, only support block of */
112 /* 16 bytes. */
113 /* */
114 /* INPUT */
115 /* */
116 /* crypto_metadata Pointer to crypto metadata */
117 /* crypto_function Pointer to crypto function */
118 /* key_set_function Pointer to key set function */
119 /* additional_data Pointer to the additional data*/
120 /* additional_len Length of additional data */
121 /* input Pointer to clear text input */
122 /* output Pointer to encrypted output */
123 /* The size of the output */
124 /* buffer must be at least */
125 /* the size of input message. */
126 /* length Length of the input message. */
127 /* iv Nonce length + Nonce */
128 /* icv_len ICV length */
129 /* block_size Block size */
130 /* */
131 /* OUTPUT */
132 /* */
133 /* status Completion status */
134 /* */
135 /* CALLS */
136 /* */
137 /* _nx_crypto_xcbc_xor Perform XOR operation */
138 /* */
139 /* CALLED BY */
140 /* */
141 /* Application Code */
142 /* */
143 /* RELEASE HISTORY */
144 /* */
145 /* DATE NAME DESCRIPTION */
146 /* */
147 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
148 /* 09-30-2020 Timothy Stapko Modified comment(s), */
149 /* verified memcpy use cases, */
150 /* resulting in version 6.1 */
151 /* */
152 /**************************************************************************/
_nx_crypto_xcbc_mac(VOID * crypto_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UINT (* key_set_function)(VOID *,UCHAR *,UINT),UCHAR * additional_data,UINT additional_len,UCHAR * input,UCHAR * output,UINT input_length_in_byte,UCHAR * iv,UCHAR icv_len,UINT block_size)153 NX_CRYPTO_KEEP UINT _nx_crypto_xcbc_mac(VOID *crypto_metadata, UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
154 UINT (*key_set_function)(VOID *, UCHAR *, UINT),
155 UCHAR *additional_data, UINT additional_len,
156 UCHAR *input, UCHAR *output, UINT input_length_in_byte,
157 UCHAR *iv, UCHAR icv_len, UINT block_size)
158 {
159 UCHAR K1[NX_CRYPTO_XCBC_MAC_BLOCK_SIZE];
160 UCHAR E[NX_CRYPTO_XCBC_MAC_BLOCK_SIZE];
161 UCHAR K2[NX_CRYPTO_XCBC_MAC_BLOCK_SIZE];
162 UCHAR pad[NX_CRYPTO_XCBC_MAC_BLOCK_SIZE];
163 UCHAR *key = additional_data;
164 UINT key_size_in_bits = additional_len;
165
166 NX_CRYPTO_STATE_CHECK
167
168 NX_CRYPTO_PARAMETER_NOT_USED(iv);
169
170 /* Check the block size. */
171 if (block_size != NX_CRYPTO_XCBC_MAC_BLOCK_SIZE)
172 {
173 return(NX_CRYPTO_PTR_ERROR);
174 }
175
176 /* RFC 3566, section 4. */
177 /* K1 = 0x01010101010101010101010101010101 encrypted with Key K */
178 NX_CRYPTO_MEMSET(K1, 1, sizeof(K1));
179 key_set_function(crypto_metadata, key, key_size_in_bits >> 5);
180 crypto_function(crypto_metadata, K1, K1, block_size);
181
182 /* E = 0x00000000000000000000000000000000 */
183 NX_CRYPTO_MEMSET(E, 0, sizeof(E));
184
185 while (input_length_in_byte > block_size)
186 {
187
188 /* XOR M with E */
189 _nx_crypto_xcbc_xor(E, input, E);
190
191 /* Encrypt the result with Key K1, yielding E */
192 key_set_function(crypto_metadata, K1, sizeof(K1) >> 2);
193 crypto_function(crypto_metadata, E, E, block_size);
194
195 input_length_in_byte -= block_size;
196 input += block_size;
197 }
198
199 if (input_length_in_byte == block_size)
200 {
201
202 /* K2 = 0x02020202020202020202020202020202 encrypted with Key K */
203 NX_CRYPTO_MEMSET(K2, 2, sizeof(K2));
204 }
205 else
206 {
207
208 /* K3 = 0x03030303030303030303030303030303 encrypted with Key K */
209 NX_CRYPTO_MEMSET(K2, 3, sizeof(K2));
210
211 /* Pad M with a single "1" bit, followed by "0" bits. */
212 NX_CRYPTO_MEMSET(pad, 0, sizeof(pad));
213 pad[input_length_in_byte] = 0x80;
214 }
215 key_set_function(crypto_metadata, key, key_size_in_bits >> 5);
216 crypto_function(crypto_metadata, K2, K2, block_size);
217
218 NX_CRYPTO_MEMCPY(pad, input, input_length_in_byte); /* Use case of memcpy is verified. */
219
220 /* XOR M with E and Key K2 or K3 */
221 _nx_crypto_xcbc_xor(E, pad, E);
222 _nx_crypto_xcbc_xor(E, K2, E);
223
224 /* Encrypt the result with Key K1, yielding E */
225 key_set_function(crypto_metadata, K1, sizeof(K1) >> 2);
226 crypto_function(crypto_metadata, E, E, block_size);
227
228 NX_CRYPTO_MEMCPY(output, E, icv_len); /* Use case of memcpy is verified. */
229
230 #ifdef NX_SECURE_KEY_CLEAR
231 NX_CRYPTO_MEMSET(K1, 0, sizeof(K1));
232 NX_CRYPTO_MEMSET(E, 0, sizeof(E));
233 NX_CRYPTO_MEMSET(K2, 0, sizeof(K2));
234 NX_CRYPTO_MEMSET(pad, 0, sizeof(pad));
235 #endif /* NX_SECURE_KEY_CLEAR */
236
237 return(NX_CRYPTO_SUCCESS);
238 }
239
240