qrc_opensource_rs/cipher/
aes.rs

1/* The AGPL version 3 License (AGPLv3)
2* 
3* Copyright (c) 2021 Digital Freedom Defence Inc.
4* This file is part of the QSC Cryptographic library
5* 
6* This program is free software : you can redistribute it and / or modify
7* it under the terms of the GNU Affero General Public License as published by
8* the Free Software Foundation, either version 3 of the License, or
9* (at your option) any later version.
10* 
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14* See the GNU Affero General Public License for more details.
15* 
16* You should have received a copy of the GNU Affero General Public License
17* along with this program. If not, see <http://www.gnu.org/licenses/>.
18*
19*
20*
21* Copyright (c) Original-2021 John G. Underhill <john.underhill@mailfence.com>
22* Copyright (c) 2022-Present QRC Eurosmart SA <opensource-support@qrcrypto.ch>
23*
24* The following code is a derivative work of the code from the QSC Cryptographic library in C, 
25* which is licensed AGPLv3. This code therefore is also licensed under the terms of 
26* the GNU Affero General Public License, version 3. The AGPL version 3 License (AGPLv3). */
27
28use crate::{common::common::QRC_SYSTEM_AESNI_ENABLED, digest::{sha2::{qrc_hkdf256_expand, qrc_hkdf256_extract, qrc_hmac256_blockupdate, qrc_hmac256_dispose, qrc_hmac256_blockfinalize, qrc_hmac256_initialize, QrcHmac256State, QRC_HMAC_256_MAC_SIZE}, sha3::{qrc_cshake256_compute, qrc_cshake_initialize, qrc_cshake_squeezeblocks, qrc_keccak_dispose, qrc_kmac_finalize, qrc_kmac_initialize, qrc_kmac_update, QrcKeccakRate, QrcKeccakState, QRC_KECCAK_256_RATE, QRC_KECCAK_STATE_SIZE}}, tools::intutils::{qrc_intutils_be8increment, qrc_intutils_be8to32, qrc_intutils_clear32, qrc_intutils_clear64, qrc_intutils_clear8, qrc_intutils_copy8, qrc_intutils_le32to8, qrc_intutils_le64to8, qrc_intutils_le8increment, qrc_intutils_min, qrc_intutils_verify}};
29
30use core::{mem::size_of, default::Default};
31
32#[cfg(feature = "no_std")]
33use alloc::{vec::Vec, borrow::ToOwned};
34
35/*
36\def QRC_HBA_KMAC_EXTENSION
37* Enables the cSHAKE extensions for the HBA cipher mode
38*///
39pub const QRC_HBA_KMAC_EXTENSION: bool = true;
40
41///*
42//\def QRC_HBA_HKDF_EXTENSION
43//* Enables the HKDF extensions for the HBA cipher-mode; alternative to HBA(cSHAKE)
44//*/
45pub const QRC_HBA_HKDF_EXTENSION: bool = true;
46
47/* \enum qrc_aes_cipher_mode
48* The pre-defined cipher mode implementations
49*/
50#[derive(PartialEq)]
51pub enum QrcAesCipherType {
52	AES128 = 1,	/*< The AES-128 block cipher */
53	AES256 = 2,	/*< The AES-256 block cipher */
54}
55/* \enum qrc_aes_cipher_mode
56* The pre-defined cipher mode implementations
57*/
58#[derive(PartialEq)]
59pub enum QrcAesCipherMode {
60	CBC = 1,	/*< Cipher Block Chaining */
61	CTR = 2,	/*< segmented integer counter */
62	ECB = 3,	/*< Electronic CodeBook mode (insecure) */
63}
64
65/**********************************
66*     AES CONSTANTS AND SIZES      *
67***********************************/
68
69/*
70\def QRC_AES_BLOCK_SIZE
71* The internal block size in bytes, required by the encryption and decryption functions.
72*/
73pub const QRC_AES_BLOCK_SIZE: usize = 16;
74
75/*
76\def QRC_AES_IV_SIZE
77* The initialization vector size in bytes.
78*/
79pub const QRC_AES_IV_SIZE: usize = 16;
80
81/*
82\def QRC_AES128_KEY_SIZE
83* The size in bytes of the AES-128 input cipher-key.
84*/
85pub const QRC_AES128_KEY_SIZE: usize = 16;
86
87/*
88\def QRC_AES256_KEY_SIZE
89* The size in bytes of the AES-256 input cipher-key.
90*/
91pub const QRC_AES256_KEY_SIZE: usize = 32;
92
93/*
94\def QRC_HBA256_MAC_LENGTH
95* The HBA-256 MAC code array length in bytes.
96*/
97pub const QRC_HBA256_MAC_LENGTH: usize = 32;
98
99/*
100\def QRC_HBA_MAXAAD_SIZE
101* The maximum allowed AAD size.
102*/
103pub const QRC_HBA_MAXAAD_SIZE: usize = 256;
104
105/*
106\def QRC_HBA_MAXINFO_SIZE
107* The maximum allowed key info size.
108*/
109pub const QRC_HBA_MAXINFO_SIZE: usize = 256;
110
111
112/*
113\def QRC_HBA_KMAC_AUTH
114* Use KMAC to authenticate HBA; removing this macro is enabled when running in SHAKE extension mode.
115* If the QRC_HBA_KMAC_EXTENSION is disabled, HMAC(SHA2) is the default authentication mode in HBA.
116*/
117pub const QRC_HBA_KMAC_AUTH: bool = if QRC_HBA_KMAC_EXTENSION {
118    true
119} else {
120    false
121};
122
123/* \struct qrc_aes_keyparams
124* The key parameters structure containing key and info arrays and lengths.
125* Use this structure to load an input cipher-key and optional info tweak, using the qrc_aes_initialize function.
126* Keys must be random and secret, and align to the corresponding key size of the cipher implemented.
127* The info parameter is optional, and can be a salt or cryptographic key.
128*/
129#[derive(Clone)]
130pub struct QrcAesKeyparams {
131	pub key: Vec<u8>,				    /*< [const] The input cipher key */
132	pub keylen: usize,					/*< The length in bytes of the cipher key */
133	pub nonce: Vec<u8>,					/*< The nonce or initialization vector */
134	pub info: Vec<u8>,			        /*< [const] The information tweak */
135	pub infolen: usize,					/*< The length in bytes of the HBA information tweak */
136}
137impl Default for QrcAesKeyparams {
138    fn default() -> Self {
139        Self {
140			key: Default::default(),
141            keylen: Default::default(),
142            nonce: Default::default(),
143			info: Default::default(),
144			infolen: Default::default()
145        }
146    }
147}
148
149/* \struct qrc_aes_state
150* The internal state structure containing the round-key array.
151*/
152#[derive(Clone)]
153pub struct QrcAesState{
154	pub roundkeys: [u32; 124],		    /*< The round-keys 32-bit sub-key array */
155	pub roundkeylen: usize,				/*< The round-key array length */
156	pub rounds: usize,					/*< The number of transformation rounds */
157	pub nonce: Vec<u8>,					/*< The nonce or initialization vector */
158}
159impl Default for QrcAesState {
160    fn default() -> Self {
161        Self {
162			roundkeys: [Default::default(); 124],
163            roundkeylen: Default::default(),
164            rounds: Default::default(),
165			nonce: Default::default()
166        }
167    }
168}
169
170/* common functions */
171
172/*
173* \brief Erase the round-key array and size
174*/
175pub fn qrc_aes_dispose(state: &mut QrcAesState) {
176	/* erase the state members */
177	qrc_intutils_clear32(&mut state.roundkeys, 124);
178    state.roundkeylen = 0;
179}
180
181/*
182* \brief Initialize the state with the input cipher-key and optional info tweak.
183* The qrc_aes_state round-key array must be initialized and size set before passing the state to this function.
184*
185* \param state: [struct] The qrc_aes_state structure
186* \param keyparams: [const] The input cipher-key, expanded to the state round-key array
187* \param encryption: Initialize the cipher for encryption, false for decryption mode
188*
189* \warning When using a CTR mode, the cipher is always initialized for encryption.
190*/
191pub fn qrc_aes_initialize(state: &mut QrcAesState, keyparams: QrcAesKeyparams, ctype: QrcAesCipherType) {
192	state.nonce = keyparams.nonce.clone();
193
194	qrc_intutils_clear32(&mut state.roundkeys, 124);
195
196	if ctype == QrcAesCipherType::AES256 {
197		state.roundkeylen = AES256_ROUNDKEY_SIZE;
198		state.rounds = 14;
199		aes_standard_expand(state, keyparams);
200	} else if ctype == QrcAesCipherType::AES128 {
201		state.roundkeylen = AES128_ROUNDKEY_SIZE;
202		state.rounds = 10;
203		aes_standard_expand(state, keyparams);
204	} else {
205		state.rounds = 0;
206		state.roundkeylen = 0;
207	}
208}
209
210/* cbc mode */
211
212/*
213* \brief Decrypt a length of cipher-text using Cipher Block Chaining mode. \n
214*
215* \warning the qrc_aes_initialize function must be called first to initialize the state
216*
217* \param state: [struct] The initialized qrc_aes_state structure
218* \param output: The output byte array; receives the decrypted plain-text
219* \param input: [const] The input cipher-text bytes
220* \param length: The number of input cipher-text bytes to decrypt
221*/
222pub fn qrc_aes_cbc_decrypt(state: &mut QrcAesState, output: &mut [u8], outputlen: &mut usize, input: &[u8], mut length: usize) {
223	let tmpb = &mut [0u8; QRC_AES_BLOCK_SIZE];
224	let mut oft = 0;
225
226	while length > QRC_AES_BLOCK_SIZE {
227		qrc_aes_cbc_decrypt_block(state, &mut output[oft..], &input[oft..]);
228		length -= QRC_AES_BLOCK_SIZE;
229		oft += QRC_AES_BLOCK_SIZE;
230	}
231
232	qrc_aes_cbc_decrypt_block(state, tmpb, &input[oft..]);
233	let nlen = qrc_pkcs7_padding_length(tmpb);
234	qrc_intutils_copy8(&mut output[oft..], tmpb, QRC_AES_BLOCK_SIZE - nlen);
235	*outputlen = oft + QRC_AES_BLOCK_SIZE - nlen;
236}
237
238/*
239* \brief Encrypt a length of cipher-text using Cipher Block Chaining mode. \n
240*
241* \warning the qrc_aes_initialize function must be called first to initialize the state
242*
243* \param state: [struct] The initialized qrc_aes_state structure
244* \param output: The output byte array; receives the encrypted plain-text
245* \param input: [const] The input plain-text bytes
246* \param length: The number of input plain-text bytes to encrypt
247*/
248pub fn qrc_aes_cbc_encrypt(state: &mut QrcAesState, output: &mut [u8], input: &[u8], mut length: usize) {
249	let mut oft = 0;
250
251	while length > QRC_AES_BLOCK_SIZE {
252		qrc_aes_cbc_encrypt_block(state, &mut output[oft..], &input[oft..]);
253		length -= QRC_AES_BLOCK_SIZE;
254		oft += QRC_AES_BLOCK_SIZE;
255	}
256
257	if length != 0 {
258		let tmpb = &mut [0u8; QRC_AES_BLOCK_SIZE];
259		qrc_intutils_copy8(tmpb, &input[oft..], length);
260
261		if length < QRC_AES_BLOCK_SIZE {
262			qrc_pkcs7_add_padding(tmpb, QRC_AES_BLOCK_SIZE - length);
263		}
264
265		qrc_aes_cbc_encrypt_block(state, &mut output[oft..], tmpb);
266	}
267}
268
269/*
270* \brief Decrypt one 16-byte block of cipher-text using Cipher Block Chaining mode. \n
271*
272* \warning the qrc_aes_initialize function must be called first to initialize the state
273*
274* \param state: [struct] The initialized qrc_aes_state structure
275* \param output: The output byte array; receives the decrypted plain-text
276* \param input: [const] The input cipher-text block of bytes
277*/
278pub fn qrc_aes_cbc_decrypt_block(state: &mut QrcAesState, output: &mut [u8], input: &[u8]) {
279	let tmpv = &mut [0u8; QRC_AES_BLOCK_SIZE];
280
281	qrc_intutils_copy8(tmpv, input, QRC_AES_BLOCK_SIZE);
282	aes_decrypt_block(state.clone(), output, input);
283
284	for i in 0..QRC_AES_BLOCK_SIZE {
285		output[i] ^= state.nonce[i];
286	}
287
288	qrc_intutils_copy8(&mut state.nonce, tmpv, QRC_AES_BLOCK_SIZE);
289}
290
291/*
292* \brief Encrypt one 16-byte block of cipher-text using Cipher Block Chaining mode. \n
293*
294* \warning the qrc_aes_initialize function must be called first to initialize the state
295*
296* \param state: [struct] The initialized qrc_aes_state structure
297* \param output: The output byte array; receives the encrypted cipher-text
298* \param input: [const] The input plain-text block of bytes
299*/
300pub fn qrc_aes_cbc_encrypt_block(state: &mut QrcAesState, output: &mut [u8], input: &[u8]) {
301	for i in 0..QRC_AES_BLOCK_SIZE {
302		state.nonce[i] ^= input[i];
303	}
304
305	aes_encrypt_block(state.clone(), output, &state.nonce);
306	qrc_intutils_copy8(&mut state.nonce, output, QRC_AES_BLOCK_SIZE);
307}
308
309/* pkcs7 */
310
311/*
312* \brief Add padding to a plain-text block pad before encryption.
313*
314* \param input: The block of input plain-text
315* \param offset: The first byte in the block to pad
316* \param length: The length of the plain-text block
317*/
318pub fn qrc_pkcs7_add_padding(input: &mut [u8], length: usize) {
319
320	let padoft = QRC_AES_BLOCK_SIZE - length;
321
322	let code = length as u8;
323	let mut ctr = padoft;
324
325	while ctr != QRC_AES_BLOCK_SIZE	{
326		input[ctr] = code;
327		ctr += 1;
328	}
329}
330
331/*
332* \brief Get the number of padded bytes in a block of decrypted cipher-text.
333*
334* \param input: [const] The block of input plain-text
335* \param offset: The first byte in the block to pad
336* \param length: The length of the plain-text block
337*
338* \return: The length of the block padding
339*/
340pub fn qrc_pkcs7_padding_length(input: &[u8]) -> usize {
341	let mut count = input[QRC_AES_BLOCK_SIZE - 1] as usize;
342    count = if count < QRC_AES_BLOCK_SIZE { count } else { 0 };
343
344	if count != 0 {
345		for i in 2..=count {
346			if input[QRC_AES_BLOCK_SIZE - i] as usize != count {
347				count = 0;
348				break;
349			}
350		}
351	}
352
353	return count;
354}
355
356/* ctr mode */
357
358/*
359* \brief Transform a length of data using a Big Endian block cipher Counter mode. \n
360* The CTR mode will encrypt plain-text, and decrypt cipher-text.
361*
362* \warning the qrc_aes_initialize function must be called first to initialize the state
363*
364* \param state: [struct] The initialized qrc_aes_state structure
365* \param output: The output byte array; receives the transformed text
366* \param input: [const] The input data byte array
367* \param length: The number of input bytes to transform
368*/
369pub fn qrc_aes_ctrbe_transform(state: &mut QrcAesState, output: &mut [u8], input: &[u8], mut length: usize) {
370    let mut oft = 0;
371
372	while length >= QRC_AES_BLOCK_SIZE {
373		aes_encrypt_block(state.clone(), &mut output[oft..], &state.nonce);
374
375		for i in 0..QRC_AES_BLOCK_SIZE {
376			output[oft + i] ^= input[oft + i];
377		}
378
379		qrc_intutils_be8increment(&mut state.nonce, QRC_AES_BLOCK_SIZE);
380
381		length -= QRC_AES_BLOCK_SIZE;
382		oft += QRC_AES_BLOCK_SIZE;
383	}
384
385	if length != 0 {
386		let tmpb = &mut [0u8; QRC_AES_BLOCK_SIZE];
387
388		aes_encrypt_block(state.clone(), tmpb, &state.nonce);
389
390		for i in 0..length {
391			output[oft + i] = tmpb[i] ^ input[oft + i];
392		}
393
394		qrc_intutils_be8increment(&mut state.nonce, QRC_AES_BLOCK_SIZE);
395	}
396}
397
398/*
399* \brief Transform a length of data using a Little Endian block cipher Counter mode. \n
400* The CTR mode will encrypt plain-text, and decrypt cipher-text.
401*
402* \warning the qrc_aes_initialize function must be called first to initialize the state
403*
404* \param state: [struct] The initialized qrc_aes_state structure
405* \param output: The output byte array; receives the transformed text
406* \param input: [const] The input data byte array
407* \param length: The number of input bytes to transform
408*/
409pub fn qrc_aes_ctrle_transform(state: &mut QrcAesState, output: &mut [u8], input: &[u8], mut length: usize) {
410	let mut oft = 0;
411
412	while length >= QRC_AES_BLOCK_SIZE {
413		aes_encrypt_block(state.clone(), &mut output[oft..], &state.nonce);
414
415		for i in 0..QRC_AES_BLOCK_SIZE {
416			output[oft + i] ^= input[oft + i];
417		}
418
419		qrc_intutils_le8increment(&mut state.nonce, QRC_AES_BLOCK_SIZE);
420
421		length -= QRC_AES_BLOCK_SIZE;
422		oft += QRC_AES_BLOCK_SIZE;
423	}
424
425	if length != 0 {
426		let tmpb = &mut [0u8; QRC_AES_BLOCK_SIZE];
427
428		aes_encrypt_block(state.clone(), tmpb, &state.nonce);
429
430		for i in 0..length {
431			output[oft + i] = tmpb[i] ^ input[oft + i];
432		}
433
434		qrc_intutils_le8increment(&mut state.nonce, QRC_AES_BLOCK_SIZE);
435	}
436}
437
438/* ecb mode */
439
440/*
441* \brief Decrypt one 16-byte block of cipher-text using Electronic CodeBook Mode mode. \n
442* \warning ECB is not a secure mode, and should be used only for testing, or building more complex primitives.
443*
444* \param state: [struct] The initialized qrc_aes_state structure
445* \param output: The output byte array; receives the decrypted plain-text
446* \param input: [const] The input cipher-text block of bytes
447*/
448pub fn qrc_aes_ecb_decrypt_block(state: QrcAesState, output: &mut [u8], input: &[u8]) {
449	aes_decrypt_block(state, output, input);
450}
451
452/*
453* \brief Encrypt one 16-byte block of cipher-text using Electronic CodeBook Mode mode. \n
454* \warning ECB is not a secure mode, and should be used only for testing, or building more complex primitives.
455*
456* \param state: [struct] The initialized qrc_aes_state structure
457* \param output: The output byte array; receives the encrypted cipher-text
458* \param input: [const] The input plain-text block of bytes
459*/
460pub fn qrc_aes_ecb_encrypt_block(state: QrcAesState, output: &mut [u8], input: &[u8]) {
461	aes_encrypt_block(state, output, input);
462}
463
464/* HBA-256 */
465
466/* \struct qrc_aes_hba256_state
467* The HBA-256 state array; pointers for the cipher state, mac-key and length, transformation mode, and the state counter.
468* Used by the long-form of the HBA api, and initialized by the hba_initialize function.
469*/
470pub struct QrcAesHba256State {
471	pub kstate: QrcKeccakState,	        	/*< the mac state */
472	pub hstate: QrcHmac256State,        	/*< the mac state */
473	pub cstate: QrcAesState,				/*< the underlying block-ciphers state structure */
474	pub counter: u64,					    /*< the processed bytes counter */
475	pub mkey: [u8; 32],					    /*< the mac generators key array */
476	pub cust: [u8; QRC_HBA_MAXINFO_SIZE],	/*< the ciphers custom key */
477	pub custlen: usize,						/*< the custom key array length */
478	pub encrypt: bool,						/*< the transformation mode; true for encryption */
479}
480impl Default for QrcAesHba256State {
481	fn default() -> Self {
482		Self {
483			kstate: QrcKeccakState::default(),
484			hstate: QrcHmac256State::default(),
485			cstate: QrcAesState::default(),
486			counter: Default::default(),
487			mkey: [Default::default(); 32],
488			cust: [Default::default(); QRC_HBA_MAXINFO_SIZE],
489			custlen: Default::default(),
490			encrypt: Default::default()
491		}
492	}
493}
494
495/*
496* \brief Dispose of the HBA-256 cipher state
497*
498* \warning The dispose function must be called when disposing of the cipher.
499* This function destroys internal arrays allocated on the heap,
500* and must be called before the state goes out of scope.
501*
502* \param state: [struct] The HBA state structure; contains internal state information
503*/
504pub fn qrc_aes_hba256_dispose(state: &mut QrcAesHba256State) {
505    if QRC_HBA_KMAC_EXTENSION {
506		qrc_keccak_dispose(&mut state.kstate);
507    } else {
508		qrc_hmac256_dispose(&mut state.hstate);
509    }
510
511    qrc_aes_dispose(&mut state.cstate);
512    qrc_intutils_clear8(&mut state.cust, QRC_HBA_MAXINFO_SIZE);
513    qrc_intutils_clear8(&mut state.mkey, 32);
514
515    state.counter = 0;
516    state.custlen = 0;
517    state.encrypt = false;
518}
519
520/*
521* \brief Initialize the cipher and load the keying material.
522* Initializes the cipher state to an AES-256 instance.
523*
524* \warning The initialize function must be called before either the associated data or transform functions are called.
525*
526* \param state: [struct] The HBA state structure; contains internal state information
527* \param keyparams: [const][struct] The HBA key parameters, includes the key, and optional AAD and user info arrays
528* \param encrypt: The cipher encryption mode; true for encryption, false for decryption
529*/
530pub fn qrc_aes_hba256_initialize(state: &mut QrcAesHba256State, keyparams: QrcAesKeyparams, encrypt: bool) {
531	let cprk = &mut [0u8; QRC_AES256_KEY_SIZE];
532
533	state.custlen = qrc_intutils_min(keyparams.infolen, QRC_HBA_MAXINFO_SIZE);
534
535	if state.custlen != 0 {
536		qrc_intutils_clear8(&mut state.cust, QRC_HBA_MAXINFO_SIZE);
537		qrc_intutils_copy8(&mut state.cust, &keyparams.info, state.custlen);
538	}
539
540	qrc_intutils_clear8(&mut state.mkey, 32);
541
542	/* generate the cipher and mac keys */
543	aes_hba256_genkeys(keyparams.clone(), cprk, &mut state.mkey);
544
545	/* initialize the mac state */
546    if QRC_HBA_KMAC_EXTENSION {
547        qrc_kmac_initialize(&mut state.kstate, QRC_KECCAK_256_RATE, &mut state.mkey, HBA256_MKEY_LENGTH, &mut [], 0);
548    } else {
549        qrc_hmac256_initialize(&mut state.hstate, &state.mkey, HBA256_MKEY_LENGTH);
550    }
551
552	/* initialize the key parameters struct, info is optional */
553	let kp = QrcAesKeyparams {
554        key: cprk.to_vec(),
555        keylen: QRC_AES256_KEY_SIZE,
556        nonce: keyparams.nonce,
557        info: [].to_vec(),
558        infolen: 0,
559    };
560	/* initialize the cipher state */
561	qrc_aes_initialize(&mut state.cstate, kp, QrcAesCipherType::AES256);
562
563	/* populate the hba state structure with mac-key and counter */
564	/* the state counter always initializes at 1 */
565	state.counter = 1;
566	state.encrypt = encrypt;
567}
568
569/*
570* \brief Set the associated data string used in authenticating the message.
571* The associated data may be packet header information, domain specific data, or a secret shared by a group.
572* The associated data must be set after initialization, and before each transformation call.
573* The data is erased after each call to the transform.
574*
575* \param state: [struct] The HBA-256 state structure; contains internal state information
576* \param data: [const] The associated data array
577* \param datalen: The associated data array length
578*/
579pub fn qrc_aes_hba256_set_associated(state: &mut QrcAesHba256State, data: &[u8], datalen: usize) {
580	/* process the additional data */
581	if datalen != 0 {
582		let actr = &mut [0u8; size_of::<u32>()];
583
584		/* add the additional data to the mac */
585		aes_hba256_update(state, data, datalen);
586		/* 1.1a encode with the ad size */
587		qrc_intutils_le32to8(actr, datalen as u32);
588		aes_hba256_update(state, actr, size_of::<u32>());
589	}
590}
591
592/*
593* \brief Transform an array of bytes using an instance of AES-256.
594* In encryption mode, the input plain-text is encrypted and then an authentication MAC code is appended to the cipher-text.
595* In decryption mode, the input cipher-text is authenticated internally and compared to the mac code appended to the cipher-text,
596* if the codes to not match, the cipher-text is not decrypted and the call fails.
597*
598* \warning The cipher must be initialized before this function can be called
599*
600* \param state: [struct] The HBA state structure; contains internal state information
601* \param output: The output byte array
602* \param input: [const] The input byte array
603* \param length: The number of bytes to transform
604*
605* \return: Returns true if the cipher has been initialized successfully, false on failure
606*/
607pub fn qrc_aes_hba256_transform(state: &mut QrcAesHba256State, output: &mut [u8], input: &[u8], length: usize) -> bool {
608	let mut res = false;
609
610	/* update the processed bytes counter */
611	state.counter += length as u64;
612
613    let nonce = &state.cstate.nonce.to_owned();
614	if state.encrypt {
615		/* update the mac with the nonce */
616		aes_hba256_update(state, nonce, QRC_AES_BLOCK_SIZE);
617		/* use aes counter-mode to encrypt the array */
618		qrc_aes_ctrle_transform(&mut state.cstate, output, input, length);
619		/* update the mac with the cipher-text */
620		aes_hba256_update(state, output, length);
621		/* mac the cipher-text appending the code to the end of the array */
622		aes_hba256_finalize(state, &mut output[length..]);
623		res = true;
624	} else {
625		let code = &mut [0u8; QRC_HBA256_MAC_LENGTH];
626
627		/* update the mac with the nonce */
628		aes_hba256_update(state, nonce, QRC_AES_BLOCK_SIZE);
629		/* update the mac with the cipher-text */
630		aes_hba256_update(state, input, length);
631		/* mac the cipher-text to the mac */
632		aes_hba256_finalize(state, code);
633
634		/* test the mac for equality, bypassing the transform if the mac check fails */
635		if qrc_intutils_verify(code, &input[length..], QRC_HBA256_MAC_LENGTH) == 0 {
636			/* use aes counter-mode to decrypt the array */
637			qrc_aes_ctrle_transform(&mut state.cstate, output, input, length);
638			res = true;
639		} else {
640			/* Fake decrypt to ensure timing */
641			let mut fake_state = state.cstate.clone();
642			let fake_output_len = output.len();
643			let mut fake_output = vec![0u8; fake_output_len];
644			qrc_intutils_copy8(&mut fake_output, output, fake_output_len);
645			qrc_aes_ctrle_transform(&mut fake_state, &mut fake_output, input, length);
646			qrc_aes_dispose(&mut fake_state);
647			qrc_intutils_clear8(&mut fake_output, fake_output_len);
648		}
649	}
650
651	return res;
652}
653
654/*
655\def AES128_ROUND_COUNT
656* The number of Rijndael mixing rounds used by AES-128.
657*/
658const AES128_ROUND_COUNT: usize = 10;
659
660/*
661\def AES256_ROUND_COUNT
662* The number of Rijndael mixing rounds used by AES-256.
663*/
664const AES256_ROUND_COUNT: usize = 14;
665
666/*
667\def ROUNDKEY_ELEMENT_SIZE
668* The round key element size in bytes.
669*/
670const ROUNDKEY_ELEMENT_SIZE: usize = if QRC_SYSTEM_AESNI_ENABLED {
671    16
672} else {
673    4
674};
675
676/*
677\def AES_NONCE_SIZE
678* The size byte size of the CTR nonce and CBC initialization vector.
679*/
680//const AES_NONCE_SIZE: usize = QRC_AES_BLOCK_SIZE;
681
682/*
683\def AES128_ROUNDKEY_SIZE
684* The size of the AES-128 internal round-key array in bytes.
685* Use this macro to define the size of the round-key array in an qrc_aes_state struct.
686*/
687const AES128_ROUNDKEY_SIZE: usize = (AES128_ROUND_COUNT + 1) * (QRC_AES_BLOCK_SIZE / ROUNDKEY_ELEMENT_SIZE);
688
689/*
690\def AES256_ROUNDKEY_SIZE
691* The size of the AES-256 internal round-key array in bytes.
692* Use this macro to define the size of the round-key array in an qrc_aes_state struct.
693*/
694const AES256_ROUNDKEY_SIZE: usize = (AES256_ROUND_COUNT + 1) * (QRC_AES_BLOCK_SIZE / ROUNDKEY_ELEMENT_SIZE);
695
696/* HBA */
697
698/*
699\def HBA_INFO_LENGTH
700* The HBA version information array length.
701*/
702//const HBA_INFO_LENGTH: usize = 16;
703
704/*
705\def HBA256_MKEY_LENGTH
706* The size of the hba-256 mac key array
707*/
708const HBA256_MKEY_LENGTH: usize = 32;
709
710/*
711\def HBA512_MKEY_LENGTH
712* The size of the hba-512 mac key array
713*/
714//const HBA512_MKEY_LENGTH: usize = 64;
715
716/*
717\def HBA_NAME_LENGTH
718* The HBA implementation specific name array length.
719*/
720const HBA_NAME_LENGTH: usize = if QRC_HBA_KMAC_EXTENSION {
721    29
722} else {
723    33
724};
725const HBA_NAME_LENGTH_MAX: usize = 33;
726
727
728/* rijndael rcon, and s-box constant tables */
729
730const RCON: [u32; 30] = [
731	0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000,
732	0x80000000, 0x1B000000, 0x36000000, 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
733	0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000, 0x97000000, 0x35000000, 0x6A000000,
734	0xD4000000, 0xB3000000, 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000
735];
736
737fn gf_mul(mut a: u8, mut b: u8) -> u8 {
738    let mut res: u16 = 0;
739    for _ in 0..8 {
740        let mask = 0u16.wrapping_sub((b & 1) as u16);
741        res ^= (a as u16) & mask;
742
743        let hi = (a & 0x80) != 0;
744        a = a << 1;
745        let red = 0u8.wrapping_sub(hi as u8) & 0x1B;
746        a ^= red;
747
748        b >>= 1;
749    }
750    return (res & 0xFF) as u8;
751}
752
753fn rotl8(x: u8, r: u32) -> u8 {
754	return x.rotate_left(r);
755}
756
757fn gf_inv(a: u8) -> u8 {
758    let a2   = gf_mul(a, a);       	 // a^2
759    let a4   = gf_mul(a2, a2);     // a^4
760    let a8   = gf_mul(a4, a4);     // a^8
761    let a16  = gf_mul(a8, a8);     // a^16
762    let a32  = gf_mul(a16, a16);   // a^32
763    let a64  = gf_mul(a32, a32);   // a^64
764    let a128 = gf_mul(a64, a64);   // a^128
765
766    let mut t = a2;
767    t = gf_mul(t, a4);
768    t = gf_mul(t, a8);
769    t = gf_mul(t, a16);
770    t = gf_mul(t, a32);
771    t = gf_mul(t, a64);
772    t = gf_mul(t, a128);
773    return t;
774}
775
776fn affine_transform(x: u8) -> u8 {
777    return x ^ rotl8(x, 1) ^ rotl8(x, 2) ^ rotl8(x, 3) ^ rotl8(x, 4) ^ 0x63;
778}
779
780fn inverse_affine_transform(s: u8) -> u8 {
781    return rotl8(s, 1) ^ rotl8(s, 3) ^ rotl8(s, 6) ^ 0x05;
782}
783
784fn sbox_u8(x: u8) -> u8 {
785    let inv = gf_inv(x);
786    return affine_transform(inv);
787}
788
789fn inv_sbox_u8(s: u8) -> u8 {
790    let b = inverse_affine_transform(s);
791   	return gf_inv(b);
792}
793
794fn aes_add_roundkey(state: &mut [u8], skeys: &[u32]) {
795    let mut k: u32;
796    for i in (0..QRC_AES_BLOCK_SIZE).step_by(size_of::<u32>()) {
797		k = skeys[i/size_of::<u32>()];
798		state[i] ^= (k >> 24) as u8;
799		state[i + 1] ^= ((k >> 16) & 0xFF) as u8 ;
800		state[i + 2] ^= ((k >> 8) & 0xFF) as u8 ;
801		state[i + 3] ^= (k & 0xFF) as u8;
802    }
803}
804
805fn aes_gf256_reduce(x: u32) -> u8 {
806	let y = x >> 8;
807
808	return (x ^ y ^ (y << 1) ^ (y << 3) ^ (y << 4)) as u8 & 0xFF;
809}
810
811
812fn aes_invmix_columns(state: &mut [u8]) {
813	for i in (0..QRC_AES_BLOCK_SIZE).step_by(size_of::<u32>()) {
814		let s0 = state[i] as u32;
815		let s1 = state[i + 1] as u32;
816		let s2 = state[i + 2] as u32;
817		let s3 = state[i + 3] as u32;
818
819		let t0 = (s0 << 1) ^ (s0 << 2) ^ (s0 << 3) ^ s1 ^ (s1 << 1) ^ (s1 << 3)
820			^ s2 ^ (s2 << 2) ^ (s2 << 3) ^ s3 ^ (s3 << 3);
821
822		let t1 = s0 ^ (s0 << 3) ^ (s1 << 1) ^ (s1 << 2) ^ (s1 << 3)
823			^ s2 ^ (s2 << 1) ^ (s2 << 3) ^ s3 ^ (s3 << 2) ^ (s3 << 3);
824
825		let t2 = s0 ^ (s0 << 2) ^ (s0 << 3) ^ s1 ^ (s1 << 3)
826			^ (s2 << 1) ^ (s2 << 2) ^ (s2 << 3) ^ s3 ^ (s3 << 1) ^ (s3 << 3);
827
828		let t3 = s0 ^ (s0 << 1) ^ (s0 << 3) ^ s1 ^ (s1 << 2) ^ (s1 << 3)
829			^ s2 ^ (s2 << 3) ^ (s3 << 1) ^ (s3 << 2) ^ (s3 << 3);
830
831		state[i] = aes_gf256_reduce(t0);
832		state[i + 1] = aes_gf256_reduce(t1);
833		state[i + 2] = aes_gf256_reduce(t2);
834		state[i + 3] = aes_gf256_reduce(t3);
835	}
836}
837
838fn aes_invshift_rows(state: &mut [u8]) {
839	let mut tmp = state[13];
840	state[13] = state[9];
841	state[9] = state[5];
842	state[5] = state[1];
843	state[1] = tmp;
844
845	tmp = state[2];
846	state[2] = state[10];
847	state[10] = tmp;
848	tmp = state[6];
849	state[6] = state[14];
850	state[14] = tmp;
851
852	tmp = state[3];
853	state[3] = state[7];
854	state[7] = state[11];
855	state[11] = state[15];
856	state[15] = tmp;
857}
858
859fn aes_invsub_bytes(state: &mut [u8]) {
860	for i in 0..QRC_AES_BLOCK_SIZE {
861		state[i] = inv_sbox_u8(state[i]);
862	}
863}
864
865fn aes_mix_columns(state: &mut [u8]) {
866	for i in (0..QRC_AES_BLOCK_SIZE).step_by(size_of::<u32>()) {
867		let s0 = state[i + 0] as u32;
868		let s1 = state[i + 1] as u32;
869		let s2 = state[i + 2] as u32;
870		let s3 = state[i + 3] as u32;
871
872		let t0 = (s0 << 1) ^ s1 ^ (s1 << 1) ^ s2 ^ s3;
873		let t1 = s0 ^ (s1 << 1) ^ s2 ^ (s2 << 1) ^ s3;
874		let t2 = s0 ^ s1 ^ (s2 << 1) ^ s3 ^ (s3 << 1);
875		let t3 = s0 ^ (s0 << 1) ^ s1 ^ s2 ^ (s3 << 1);
876
877		state[i + 0] = (t0 ^ (((!(t0 >> 8)).wrapping_add(1)) & 0x0000011B)) as u8;
878		state[i + 1] = (t1 ^ (((!(t1 >> 8)).wrapping_add(1)) & 0x0000011B)) as u8;
879		state[i + 2] = (t2 ^ (((!(t2 >> 8)).wrapping_add(1)) & 0x0000011B)) as u8;
880		state[i + 3] = (t3 ^ (((!(t3 >> 8)).wrapping_add(1)) & 0x0000011B)) as u8;
881	}
882}
883
884fn aes_shift_rows(state: &mut [u8]) {
885	let mut tmp = state[1];
886	state[1] = state[5];
887	state[5] = state[9];
888	state[9] = state[13];
889	state[13] = tmp;
890
891	tmp = state[2];
892	state[2] = state[10];
893	state[10] = tmp;
894	tmp = state[6];
895	state[6] = state[14];
896	state[14] = tmp;
897
898	tmp = state[15];
899	state[15] = state[11];
900	state[11] = state[7];
901	state[7] = state[3];
902	state[3] = tmp;
903}
904
905fn aes_sub_bytes(state: &mut [u8]) {
906	for i in 0..QRC_AES_BLOCK_SIZE {
907		state[i] = sbox_u8(state[i]);
908	}
909}
910
911fn aes_substitution(rot: u32) -> u32 {
912    let b0 = sbox_u8((rot & 0xFF) as u8) as u32;
913    let b1 = sbox_u8(((rot >> 8) & 0xFF) as u8) as u32;
914    let b2 = sbox_u8(((rot >> 16) & 0xFF) as u8) as u32;
915    let b3 = sbox_u8(((rot >> 24) & 0xFF) as u8) as u32;
916    return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
917}
918
919fn aes_decrypt_block(state: QrcAesState, output: &mut [u8], input: &[u8]) {
920	let s = &mut [0u8; 16];
921
922	let buf = input;
923	qrc_intutils_copy8(s, buf, QRC_AES_BLOCK_SIZE);
924	aes_add_roundkey(s, &state.roundkeys[(state.rounds << 2)..]);
925
926	for i in (1..(state.rounds)).rev() {
927
928		aes_invshift_rows(s);
929		aes_invsub_bytes(s);
930		aes_add_roundkey(s, &state.roundkeys[(i << 2)..]);
931		aes_invmix_columns(s);
932	}
933
934	aes_invshift_rows(s);
935	aes_invsub_bytes(s);
936	aes_add_roundkey(s, &state.roundkeys);
937	qrc_intutils_copy8(output, s, QRC_AES_BLOCK_SIZE);
938}
939
940fn aes_encrypt_block(state: QrcAesState, output: &mut [u8], input: &[u8]) {
941	let buf = &mut [0u8; QRC_AES_BLOCK_SIZE];
942
943	qrc_intutils_copy8(buf, input, QRC_AES_BLOCK_SIZE);
944	aes_add_roundkey(buf, &state.roundkeys);
945
946	for i in 1..state.rounds {
947		aes_sub_bytes(buf);
948		aes_shift_rows(buf);
949		aes_mix_columns(buf);
950		aes_add_roundkey(buf, &state.roundkeys[(i << 2)..]);
951	}
952
953	aes_sub_bytes(buf);
954	aes_shift_rows(buf);
955
956	aes_add_roundkey(buf, &state.roundkeys[(state.rounds << 2)..]);
957
958	qrc_intutils_copy8(output, buf, QRC_AES_BLOCK_SIZE);
959}
960
961fn aes_expand_rot(key: &mut [u32], mut keyindex: u32, keyoffset: u32, rconindex: u32) {
962	let mut subkey = keyindex - keyoffset;
963	key[keyindex as usize] = key[subkey as usize] ^ aes_substitution((key[keyindex as usize - 1] << 8) | ((key[keyindex as usize - 1] >> 24) & 0xFF)) ^ RCON[rconindex as usize];
964	keyindex += 1;
965	subkey += 1;
966	key[keyindex as usize] = key[subkey as usize] ^ key[keyindex as usize - 1];
967    keyindex += 1;
968	subkey += 1;
969	key[keyindex as usize] = key[subkey as usize] ^ key[keyindex as usize - 1];
970    keyindex += 1;
971	subkey += 1;
972	key[keyindex as usize] = key[subkey as usize] ^ key[keyindex as usize - 1];
973}
974
975fn aes_expand_sub(key: &mut [u32], mut keyindex: u32, keyoffset: u32) {
976	let mut subkey = keyindex - keyoffset;
977	key[keyindex as usize] = aes_substitution(key[keyindex as usize - 1]) ^ key[subkey as usize];
978	keyindex += 1;
979	subkey += 1;
980	key[keyindex as usize] = key[subkey as usize] ^ key[keyindex as usize - 1];
981	keyindex += 1;
982	subkey += 1;
983	key[keyindex as usize] = key[subkey as usize] ^ key[keyindex as usize - 1];
984	keyindex += 1;
985	subkey += 1;
986	key[keyindex as usize] = key[subkey as usize] ^ key[keyindex as usize - 1];
987}
988
989fn aes_standard_expand(state: &mut QrcAesState, keyparams: QrcAesKeyparams) {
990	/* key in 32 bit words */
991	let kwords = keyparams.keylen / size_of::<u32>();
992
993	if kwords == 8 {
994		state.roundkeys[0] = qrc_intutils_be8to32(&keyparams.key);
995		state.roundkeys[1] = qrc_intutils_be8to32(&keyparams.key[4..]);
996		state.roundkeys[2] = qrc_intutils_be8to32(&keyparams.key[8..]);
997		state.roundkeys[3] = qrc_intutils_be8to32(&keyparams.key[12..]);
998		state.roundkeys[4] = qrc_intutils_be8to32(&keyparams.key[16..]);
999		state.roundkeys[5] = qrc_intutils_be8to32(&keyparams.key[20..]);
1000		state.roundkeys[6] = qrc_intutils_be8to32(&keyparams.key[24..]);
1001		state.roundkeys[7] = qrc_intutils_be8to32(&keyparams.key[28..]);
1002
1003		/* k256 r: 8,16,24,32,40,48,56 s: 12,20,28,36,44,52 */
1004		aes_expand_rot(&mut state.roundkeys, 8, 8, 1);
1005		aes_expand_sub(&mut state.roundkeys, 12, 8);
1006		aes_expand_rot(&mut state.roundkeys, 16, 8, 2);
1007		aes_expand_sub(&mut state.roundkeys, 20, 8);
1008		aes_expand_rot(&mut state.roundkeys, 24, 8, 3);
1009		aes_expand_sub(&mut state.roundkeys, 28, 8);
1010		aes_expand_rot(&mut state.roundkeys, 32, 8, 4);
1011		aes_expand_sub(&mut state.roundkeys, 36, 8);
1012		aes_expand_rot(&mut state.roundkeys, 40, 8, 5);
1013		aes_expand_sub(&mut state.roundkeys, 44, 8);
1014		aes_expand_rot(&mut state.roundkeys, 48, 8, 6);
1015		aes_expand_sub(&mut state.roundkeys, 52, 8);
1016		aes_expand_rot(&mut state.roundkeys, 56, 8, 7);
1017	} else {
1018		state.roundkeys[0] = qrc_intutils_be8to32(&keyparams.key);
1019		state.roundkeys[1] = qrc_intutils_be8to32(&keyparams.key[4..]);
1020		state.roundkeys[2] = qrc_intutils_be8to32(&keyparams.key[8..]);
1021		state.roundkeys[3] = qrc_intutils_be8to32(&keyparams.key[12..]);
1022
1023		/* k128 r: 4,8,12,16,20,24,28,32,36,40 */
1024		aes_expand_rot(&mut state.roundkeys, 4, 4, 1);
1025		aes_expand_rot(&mut state.roundkeys, 8, 4, 2);
1026		aes_expand_rot(&mut state.roundkeys, 12, 4, 3);
1027		aes_expand_rot(&mut state.roundkeys, 16, 4, 4);
1028		aes_expand_rot(&mut state.roundkeys, 20, 4, 5);
1029		aes_expand_rot(&mut state.roundkeys, 24, 4, 6);
1030		aes_expand_rot(&mut state.roundkeys, 28, 4, 7);
1031		aes_expand_rot(&mut state.roundkeys, 32, 4, 8);
1032		aes_expand_rot(&mut state.roundkeys, 36, 4, 9);
1033		aes_expand_rot(&mut state.roundkeys, 40, 4, 10);
1034	}
1035}
1036
1037/* Block-cipher counter mode with Hash Based Authentication, -HBA- AEAD authenticated mode */
1038
1039/* aes-hba256 */
1040
1041const fn def_aes_hba256_name() -> [u8; HBA_NAME_LENGTH_MAX] {
1042	if QRC_HBA_KMAC_AUTH {
1043		return [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x42, 0x41, 0x2D, 0x52, 0x48, 0x58, 0x53, 0x32, 0x35, 0x36, 0x2D, 0x4B, 0x4D, 0x41, 0x43, 0x32, 0x35, 0x36, 0x00, 0x00, 0x00, 0x00];
1044	} else {
1045		return [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x42, 0x41, 0x2D, 0x52, 0x48, 0x58, 0x48, 0x32, 0x35, 0x36, 0x2D, 0x48, 0x4D, 0x41, 0x43, 0x53, 0x48, 0x41, 0x32, 0x32, 0x35, 0x36];
1046	};
1047}
1048const AES_HBA256_NAME: [u8; HBA_NAME_LENGTH] = {
1049	let a = def_aes_hba256_name();
1050	const L: usize = HBA_NAME_LENGTH;
1051    let mut o = [0u8; L];
1052
1053    let mut i = 0;
1054    while i < L {
1055        o[i] = a[i];
1056        i += 1;
1057    }
1058    o
1059};
1060
1061fn aes_hba256_update(state: &mut QrcAesHba256State, input: &[u8], length: usize) {
1062    if QRC_HBA_KMAC_EXTENSION {
1063	    qrc_kmac_update(&mut state.kstate, QRC_KECCAK_256_RATE, input, length);
1064    } else {
1065        qrc_hmac256_blockupdate(&mut state.hstate, input, length);
1066    }
1067}
1068
1069fn aes_hba256_finalize(state: &mut QrcAesHba256State, output: &mut [u8]) {
1070	let mkey = &mut [0u8; HBA256_MKEY_LENGTH];
1071	let pctr = &mut [0u8; size_of::<u64>()];
1072	let tmpn = &mut [0u8; HBA_NAME_LENGTH];
1073
1074	/* version 1.1a add the nonce, ciphertext, and encoding sizes to the counter */
1075	let mctr = (QRC_AES_BLOCK_SIZE + state.counter as usize + size_of::<u64>()) as u64;
1076	/* convert to little endian bytes  */
1077	qrc_intutils_le64to8(pctr, mctr);
1078	/* encode with message size, counter, and terminating string sizes */
1079	aes_hba256_update(state, pctr, size_of::<u64>());
1080
1081    if QRC_HBA_KMAC_AUTH {
1082        /* mac the data and add the code to the end of the cipher-text output array */
1083        qrc_kmac_finalize(&mut state.kstate, QRC_KECCAK_256_RATE, output, QRC_HBA256_MAC_LENGTH);
1084    } else {
1085        /* mac the data and add the code to the end of the cipher-text output array */
1086        qrc_hmac256_blockfinalize(&mut state.hstate, output, &[], 0);
1087    }
1088
1089	/* generate the new mac key */
1090	qrc_intutils_copy8(tmpn, &AES_HBA256_NAME, HBA_NAME_LENGTH);
1091	/* add 1 + the nonce, and last input size */
1092	/* append the counter to the end of the mac input array */
1093	qrc_intutils_le64to8(tmpn, state.counter);
1094
1095    if QRC_HBA_KMAC_AUTH {
1096        qrc_cshake256_compute(mkey, HBA256_MKEY_LENGTH, &state.mkey, 32, tmpn, HBA_NAME_LENGTH, &state.cust, state.custlen);
1097        qrc_intutils_copy8(&mut state.mkey, mkey, HBA256_MKEY_LENGTH);
1098        qrc_kmac_initialize(&mut state.kstate, QRC_KECCAK_256_RATE, &mut state.mkey, HBA256_MKEY_LENGTH, &mut [], 0);
1099    }  else {
1100        /* extract the HKDF key from the state mac-key and salt */
1101        qrc_hkdf256_extract(mkey, &state.mkey, HBA256_MKEY_LENGTH, tmpn, 32);
1102        /* key HKDF Expand and generate the next mac-key to state */
1103        qrc_hkdf256_expand(&mut state.mkey, 32, mkey, HBA256_MKEY_LENGTH, &state.cust, state.custlen);
1104    }
1105}
1106
1107fn aes_hba256_genkeys(keyparams: QrcAesKeyparams, cprk: &mut [u8], mack: &mut [u8]) {
1108    if QRC_HBA_KMAC_EXTENSION {
1109
1110        let kstate = &mut QrcKeccakState::default();
1111        let sbuf = &mut [0u8; QRC_KECCAK_256_RATE];
1112
1113        qrc_intutils_clear64(&mut kstate.state, QRC_KECCAK_STATE_SIZE);
1114
1115        let rate = QrcKeccakRate::QrcKeccakRate256 as usize;
1116
1117        /* initialize an instance of cSHAKE */
1118        qrc_cshake_initialize(kstate, rate, &keyparams.key, keyparams.keylen, &AES_HBA256_NAME, HBA_NAME_LENGTH, &keyparams.info, keyparams.infolen);
1119
1120        /* use two permutation calls to seperate the cipher/mac key outputs to match the CEX implementation */
1121        qrc_cshake_squeezeblocks(kstate, rate, sbuf, 1);
1122        qrc_intutils_copy8(cprk, sbuf, keyparams.keylen);
1123        qrc_cshake_squeezeblocks(kstate, rate, sbuf, 1);
1124        qrc_intutils_copy8(mack, sbuf, HBA256_MKEY_LENGTH);
1125        /* clear the shake buffer */
1126        qrc_intutils_clear64(&mut kstate.state, QRC_KECCAK_STATE_SIZE);
1127
1128    } else {
1129
1130        let kbuf = &mut [0u8; QRC_AES256_KEY_SIZE + HBA256_MKEY_LENGTH];
1131        let genk = &mut [0u8; QRC_HMAC_256_MAC_SIZE];
1132
1133        /* extract the HKDF key from the user-key and salt */
1134        qrc_hkdf256_extract(genk, &keyparams.key, keyparams.keylen, &AES_HBA256_NAME, HBA_NAME_LENGTH);
1135
1136        /* key HKDF Expand and generate the key buffer */
1137        qrc_hkdf256_expand(kbuf, QRC_AES256_KEY_SIZE + HBA256_MKEY_LENGTH, genk, QRC_HMAC_256_MAC_SIZE, &keyparams.info, keyparams.infolen);
1138
1139        /* copy the cipher and mac keys from the buffer */
1140        qrc_intutils_copy8(cprk, kbuf, QRC_AES256_KEY_SIZE);
1141        qrc_intutils_copy8(mack, &kbuf[QRC_AES256_KEY_SIZE..], HBA256_MKEY_LENGTH);
1142
1143        /* clear the buffer */
1144        qrc_intutils_clear8(kbuf, QRC_AES256_KEY_SIZE + HBA256_MKEY_LENGTH);
1145
1146    }
1147}