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