MCUX CLNS
MCUX Crypto Library Normal Secure
mcuxClExample_RFC3394_Helper.h
1 /*--------------------------------------------------------------------------*/
2 /* Copyright 2022-2023 NXP */
3 /* */
4 /* NXP Confidential. This software is owned or controlled by NXP and may */
5 /* only be used strictly in accordance with the applicable license terms. */
6 /* By expressly accepting such terms or by downloading, installing, */
7 /* activating and/or otherwise using the software, you are agreeing that */
8 /* you have read, and that you agree to comply with and are bound by, such */
9 /* license terms. If you do not agree to be bound by the applicable license */
10 /* terms, then you may not retain, install, activate or otherwise use the */
11 /* software. */
12 /*--------------------------------------------------------------------------*/
13 
14 #ifndef MCUXCLEXAMPLE_RFC3394_HELPER_H_
15 #define MCUXCLEXAMPLE_RFC3394_HELPER_H_
16 
17 #include <mcuxClConfig.h> // Exported features flags header
18 #include <mcuxClCore_Platform.h>
19 #include <mcuxClEls.h>
20 #include <mcuxCsslFlowProtection.h>
22 #include <mcuxClMemory_Copy.h>
23 
28 static inline bool mcuxClExample_rfc3394_wrap(
29  const uint8_t * pInput, //< pointer to key to be wrapped
30  size_t inputLength, //< length of key to be wrapped in bytes
31  const uint8_t * pKek_in, //< pointer to key wrapping key
32  mcuxClEls_KeyIndex_t keyIdx, //< keyslot index of key wrapping key
33  uint8_t extkey, //< 0-use key stored internally at keyIdx as wrapping key, 1-use external pKek_in as wrapping key
34  size_t kekLength, //< length of key wrapping key in bytes
35  uint8_t * pOutput, //< pointer to output buffer, size has to be inputLength + 16 bytes
36  mcuxClEls_KeyProp_t properties //< properties of the key to be wrapped
37 )
38 {
39  uint32_t concat[MCUXCLELS_CIPHER_BLOCK_SIZE_AES/sizeof(uint32_t)] = { 0u };
40 
41  uint32_t input[MCUXCLELS_CIPHER_BLOCK_SIZE_AES/sizeof(uint32_t)] = { 0u };
42  uint8_t pKek[MCUXCLELS_CIPHER_KEY_SIZE_AES_256] = { 0u };
43 
44  if (extkey == MCUXCLELS_CIPHER_EXTERNAL_KEY)
45  {
47  pKek_in,
48  kekLength,
49  kekLength));
50 
52  {
53  return false;
54  }
55 
57  }
58 
59  // Intermediate state is stored in pOutput as it is large enough
60 
61  // initialize buffer
62  concat[0] = 0xA6A6A6A6u; // first half of concat is the A from the standard, initialized to RFC3394 IV
63  concat[1] = 0xA6A6A6A6u;
64  concat[2] = properties.word.value; // second half of concat is R(input)/B(output), first R consists of properties...
65  concat[3] = 0x00000000u; // ... and ELS padding (zeros)
66  concat[2] = (concat[2] << 24u) | (concat[2] >> 24u) | ((concat[2] & 0x0000ff00u) << 8u) | ((concat[2] >> 8u) & 0x0000ff00u); // swap endianness
67 
68  // initialize ELS encryption parameters
69  mcuxClEls_CipherOption_t cipher_options;
70  cipher_options.word.value = 0;
72  cipher_options.bits.dcrpt = MCUXCLELS_CIPHER_ENCRYPT;
73  cipher_options.bits.extkey = extkey;
74 
75  // input has to be multiple of 64 bits
76  if (inputLength % sizeof(uint64_t) != 0u)
77  {
78  return false;
79  }
80 
81  uint32_t *pSource = (uint32_t*) pInput;
82  uint32_t *pDest = (uint32_t*) pOutput;
83  uint32_t std_n = inputLength/sizeof(uint64_t) + 1; // n value from standard
84  for(size_t jdx = 0u; jdx < 6u; jdx++)
85  {
86  for(size_t idx = 0u; idx < std_n; idx++)
87  {
88  input[0]=concat[0];
89  input[1]=concat[1];
90  input[2]=concat[2];
91  input[3]=concat[3];
92 
93  // Encrypt concatenated A and chunk to be processed
95  cipher_options,
96  keyIdx,
97  pKek,
98  kekLength,
99  (uint8_t*) input,
101  NULL,
102  (uint8_t*) concat));
104  {
105  return false;
106  }
108 
111  {
112  return false;
113  }
115 
116  // Write out processed key chunk
117  pDest[2u*idx + 2u] = concat[2u];
118  pDest[2u*idx + 3u] = concat[3u];
119 
120  if( idx == std_n - 1u)
121  {
122  // Load next key chunk
123  concat[2u] = pDest[2u];
124  concat[3u] = pDest[3u];
125  pSource = pDest + 4;
126  }
127  else
128  {
129  // Load next key chunk
130  concat[2u] = pSource[2u*idx + 0u];
131  concat[3u] = pSource[2u*idx + 1u];
132  }
133 
134  // XOR round constant into A
135  uint32_t gdx = std_n * jdx + (idx+1); // all values should fit into a uint32_t
136  gdx = (gdx << 24u) | (gdx >> 24u) | ((gdx & 0x0000ff00u) << 8u) | ((gdx >> 8u) & 0x0000ff00u); // swap endianness
137  concat[1u] ^= gdx;
138  }
139  }
140  // Write out processed key chunk
141  pDest[0u] = concat[0u];
142  pDest[1u] = concat[1u];
143 
144  return true;
145 }
146 
151 static inline bool mcuxClExample_rfc3394_unwrap(
152  const uint8_t * pInput, //< pointer to rfc3394 blob to be wrapped
153  size_t inputLength, //< length of key the rfc3394 blob in bytes
154  const uint8_t * pKek_in, //< pointer to key wrapping key
155  mcuxClEls_KeyIndex_t keyIdx, //< keyslot index of key wrapping key
156  uint8_t extkey, //< 0-use key stored internally at keyIdx as wrapping key, 1-use external pKek_in as wrapping key
157  size_t kekLength, //< length of key wrapping key in bytes
158  uint8_t * pOutput //< pointer to output buffer, size has to inputLength - 8 bytes, contents will be properties|zeros|key
159 )
160 {
161  uint32_t concat[MCUXCLELS_CIPHER_BLOCK_SIZE_AES/sizeof(uint32_t)] = { 0u };
162 
163  uint32_t input[MCUXCLELS_CIPHER_BLOCK_SIZE_AES/sizeof(uint32_t)] = { 0u };
164  uint8_t pKek[MCUXCLELS_CIPHER_KEY_SIZE_AES_256] = { 0u };
165 
166  if (extkey == MCUXCLELS_CIPHER_EXTERNAL_KEY)
167  {
169  pKek_in,
170  kekLength,
171  kekLength));
172 
174  {
175  return false;
176  }
177 
179  }
180 
181  // initialize buffer
182  concat[0] = ((uint32_t*) pInput)[0]; // first half of concat is the A from the standard, to first chunk of input
183  concat[1] = ((uint32_t*) pInput)[1];
184 
185  // initialize ELS encryption parameters
186  mcuxClEls_CipherOption_t cipher_options;
187  cipher_options.word.value = 0;
189  cipher_options.bits.dcrpt = MCUXCLELS_CIPHER_DECRYPT;
190  cipher_options.bits.extkey = extkey;
191 
192  // input has to be multiple of 64 bits
193  if (inputLength % sizeof(uint64_t) != 0u)
194  {
195  return false;
196  }
197 
198 
199  uint32_t std_n = inputLength/sizeof(uint64_t) - 1; // n value from standard
200  uint32_t *pSource = ((uint32_t*) pInput ) + 2u; // skip first 64 bits
201  uint32_t *pDest = ((uint32_t*) pOutput) + 0u;
202  for(size_t jdx = 6u; jdx > 0u; jdx--)
203  {
204  for(size_t idx = std_n; idx > 0u; idx--)
205  {
206  // Load next key chunk
207  concat[2u] = pSource[2u*(idx-1) + 0u];
208  concat[3u] = pSource[2u*(idx-1) + 1u];
209 
210  // XOR round constant into A
211  uint32_t gdx = std_n * (jdx-1u) + idx; // all values should fit into a uint32_t
212  gdx = (gdx << 24u) | (gdx >> 24u) | ((gdx & 0x0000ff00u) << 8u) | ((gdx >> 8u) & 0x0000ff00u); // swap endianness
213  concat[1u] ^= gdx;
214 
215  input[0]=concat[0];
216  input[1]=concat[1];
217  input[2]=concat[2];
218  input[3]=concat[3];
219 
220  // Decrypt concatenated A and chunk to be processed
222  cipher_options,
223  keyIdx,
224  pKek,
225  kekLength,
226  (uint8_t*) input,
228  NULL,
229  (uint8_t*) concat));
231  {
232  return false;
233  }
235 
238  {
239  return false;
240  }
242 
243  // Write out processed key chunk
244  pDest[2u*(idx-1) + 0u] = concat[2u];
245  pDest[2u*(idx-1) + 1u] = concat[3u];
246  }
247  pSource = pDest;
248  }
249  pDest[0] = (pDest[0] << 24u) | (pDest[0] >> 24u) | ((pDest[0] & 0x0000ff00u) << 8u) | ((pDest[0] >> 8u) & 0x0000ff00u); // swap endianness
250  // Check padding
251  if((concat[0u] != 0xA6A6A6A6u) || (concat[1u] != 0xA6A6A6A6u))
252  {
253  return false;
254  }
255  return true;
256 }
257 
258 #endif /* MCUXCLEXAMPLE_RFC3394_HELPER_H_ */
uint32_t cphmde
Define cipher mode.
Definition: mcuxClEls_Cipher.h:130
uint32_t extkey
Define whether an external key from memory or ELS internal key should be used.
Definition: mcuxClEls_Cipher.h:138
Top-level include file for the ELS driver.
MCUXCLELS_API mcuxClEls_Status_t mcuxClEls_Cipher_Async(mcuxClEls_CipherOption_t options, mcuxClEls_KeyIndex_t keyIdx, uint8_t const *pKey, size_t keyLength, uint8_t const *pInput, size_t inputLength, uint8_t *pIV, uint8_t *pOutput)
Performs AES encryption/decryption.
#define MCUXCLELS_CIPHER_EXTERNAL_KEY
Set this option at mcuxClEls_CipherOption_t.extkey to use a key located in CPU memory provided by pKe...
Definition: mcuxClEls_Cipher.h:73
uint32_t mcuxClEls_KeyIndex_t
Type for ELS keystore indices.
Definition: mcuxClEls_Types.h:221
#define MCUXCLELS_CIPHER_DECRYPT
Set this option at mcuxClEls_CipherOption_t.dcrpt to perform a decryption.
Definition: mcuxClEls_Cipher.h:63
struct mcuxClEls_CipherOption_t::@2 word
Access mcuxClEls_CipherOption_t word-wise.
#define MCUX_CSSL_FP_FUNCTION_CALLED(...)
Expectation of a called function.
Definition: mcuxCsslFlowProtection.h:730
void mcuxClMemory_copy(uint8_t *pDst, uint8_t const *pSrc, size_t length, size_t bufLength)
Copies a memory buffer to another location.
uint32_t value
Accesses the bit field as a full word.
Definition: mcuxClEls_Cipher.h:124
Provides the API for the CSSL flow protection mechanism.
#define MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB
Set this option at mcuxClEls_CipherOption_t.cphmde to use AES engine in Electornic Code Book (ECB) mo...
Definition: mcuxClEls_Cipher.h:76
Memory header for copy functions.
MCUXCLELS_API mcuxClEls_Status_t mcuxClEls_WaitForOperation(mcuxClEls_ErrorHandling_t errorHandling)
Wait for an ELS operation and optionally clear the error status.
#define MCUX_CSSL_FP_FUNCTION_CALL_VOID_END(...)
End a void function call section started by MCUX_CSSL_FP_FUNCTION_CALL_VOID_BEGIN.
Definition: mcuxCsslFlowProtection.h:678
Command option bit field for mcuxClEls_Cipher_Async.
Definition: mcuxClEls_Cipher.h:120
#define MCUXCLELS_STATUS_OK
No error occurred.
Definition: mcuxClEls_Types.h:170
#define MCUXCLELS_CIPHER_ENCRYPT
Set this option at mcuxClEls_CipherOption_t.dcrpt to perform an encryption.
Definition: mcuxClEls_Cipher.h:62
uint32_t value
Accesses the bit field as a full word; initialize with a combination of constants from MCUXCLELS_KEYP...
Definition: mcuxClEls_Types.h:228
uint32_t dcrpt
Define operation mode.
Definition: mcuxClEls_Cipher.h:129
#define MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(...)
Call a flow protected function and check the protection token.
Definition: mcuxCsslFlowProtection.h:576
#define MCUXCLELS_CIPHER_KEY_SIZE_AES_256
Size of an AES192 key: 256 bit (32 bytes)
Definition: mcuxClEls_Cipher.h:98
Type for ELS key store key properties.
Definition: mcuxClEls_Types.h:224
Definition of function identifiers for the flow protection mechanism.
#define MCUX_CSSL_FP_FUNCTION_CALL_VOID_BEGIN(...)
Call a flow protected void function and check the protection token.
Definition: mcuxCsslFlowProtection.h:647
struct mcuxClEls_KeyProp_t::@40 word
Access mcuxClEls_KeyProp_t word-wise.
#define MCUXCLELS_STATUS_OK_WAIT
An _Async function successfully started an ELS command. Call mcuxClEls_WaitForOperation to complete i...
Definition: mcuxClEls_Types.h:171
#define MCUXCLELS_ERROR_FLAGS_CLEAR
Set this option at mcuxClEls_ErrorHandling_t to clear all ELS error flags.
Definition: mcuxClEls_Common.h:137
#define MCUXCLELS_CIPHER_BLOCK_SIZE_AES
Definition: mcuxClEls_Cipher.h:87
struct mcuxClEls_CipherOption_t::@3 bits
Access mcuxClEls_CipherOption_t bit-wise.
#define MCUX_CSSL_FP_FUNCTION_CALL_END(...)
End a function call section started by MCUX_CSSL_FP_FUNCTION_CALL_BEGIN.
Definition: mcuxCsslFlowProtection.h:611