Skip to content

Commit e31791f

Browse files
committed
feat(drivers): Builtin CMAC driver use PSA cipher interface
Signed-off-by: harshal.patil <[email protected]>
1 parent 9b74ba0 commit e31791f

File tree

3 files changed

+323
-32
lines changed

3 files changed

+323
-32
lines changed

drivers/builtin/src/psa_crypto_mac.c

Lines changed: 290 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <mbedtls/error_common.h>
2020
#include "mbedtls/constant_time.h"
21+
#include "constant_time_internal.h"
2122
#include <string.h>
2223

2324
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
@@ -154,11 +155,139 @@ static psa_status_t psa_hmac_finish_internal(
154155
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
155156

156157
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
157-
static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation,
158-
const psa_key_attributes_t *attributes,
159-
const uint8_t *key_buffer)
158+
/*
159+
* Multiplication by u in the Galois field of GF(2^n)
160+
*
161+
* As explained in NIST SP 800-38B, this can be computed:
162+
*
163+
* If MSB(p) = 0, then p = (p << 1)
164+
* If MSB(p) = 1, then p = (p << 1) ^ R_n
165+
* with R_64 = 0x1B and R_128 = 0x87
166+
*
167+
* Input and output MUST NOT point to the same buffer
168+
* Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.
169+
*/
170+
static int cmac_multiply_by_u(unsigned char *output,
171+
const unsigned char *input,
172+
size_t blocksize)
173+
{
174+
const unsigned char R_128 = 0x87;
175+
unsigned char R_n;
176+
uint32_t overflow = 0x00;
177+
int i;
178+
179+
if (blocksize == PSA_AES_BLOCK_SIZE) {
180+
R_n = R_128;
181+
}
182+
#if defined(PSA_WANT_KEY_TYPE_DES)
183+
else if (blocksize == PSA_DES_BLOCK_SIZE) {
184+
const unsigned char R_64 = 0x1B;
185+
R_n = R_64;
186+
}
187+
#endif
188+
else {
189+
return PSA_ERROR_INVALID_ARGUMENT;
190+
}
191+
192+
for (i = (int) blocksize - 4; i >= 0; i -= 4) {
193+
uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);
194+
uint32_t new_overflow = i32 >> 31;
195+
i32 = (i32 << 1) | overflow;
196+
MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);
197+
overflow = new_overflow;
198+
}
199+
200+
R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n);
201+
output[blocksize - 1] ^= R_n;
202+
203+
return 0;
204+
}
205+
206+
/*
207+
* Generate subkeys
208+
*
209+
* - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
210+
*/
211+
static int cmac_generate_subkeys(psa_cipher_operation_t *ctx, size_t block_size,
212+
unsigned char *K1, unsigned char *K2)
213+
{
214+
int ret = PSA_ERROR_CORRUPTION_DETECTED;
215+
unsigned char L[PSA_CMAC_MAX_BLOCK_SIZE];
216+
size_t olen;
217+
218+
mbedtls_platform_zeroize(L, sizeof(L));
219+
220+
/* Calculate Ek(0) */
221+
if ((ret = psa_cipher_update(ctx, L, block_size, L, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
222+
goto exit;
223+
}
224+
225+
/*
226+
* Generate K1 and K2
227+
*/
228+
if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) {
229+
goto exit;
230+
}
231+
232+
if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) {
233+
goto exit;
234+
}
235+
236+
exit:
237+
mbedtls_platform_zeroize(L, sizeof(L));
238+
239+
return ret;
240+
}
241+
242+
/*
243+
* Create padded last block from (partial) last block.
244+
*
245+
* We can't use the padding option from the cipher layer, as it only works for
246+
* CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
247+
*/
248+
static void cmac_pad(unsigned char padded_block[PSA_CMAC_MAX_BLOCK_SIZE],
249+
size_t padded_block_len,
250+
const unsigned char *last_block,
251+
size_t last_block_len)
160252
{
161-
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253+
size_t j;
254+
255+
for (j = 0; j < padded_block_len; j++) {
256+
if (j < last_block_len) {
257+
padded_block[j] = last_block[j];
258+
} else if (j == last_block_len) {
259+
padded_block[j] = 0x80;
260+
} else {
261+
padded_block[j] = 0x00;
262+
}
263+
}
264+
}
265+
266+
static psa_status_t psa_cmac_abort_internal(
267+
mbedtls_psa_cmac_operation_t *cmac)
268+
{
269+
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
270+
271+
status = psa_destroy_key(cmac->key_id);
272+
if (status != PSA_SUCCESS) {
273+
return status;
274+
}
275+
276+
status = psa_cipher_abort(&cmac->cipher_ctx);
277+
if (status != PSA_SUCCESS) {
278+
return status;
279+
}
280+
281+
mbedtls_platform_zeroize(cmac, sizeof(mbedtls_psa_cmac_operation_t));
282+
return status;
283+
}
284+
285+
static psa_status_t psa_cmac_setup_internal(mbedtls_psa_cmac_operation_t *cmac,
286+
const psa_key_attributes_t *attributes,
287+
const uint8_t *key_buffer,
288+
size_t key_buffer_size)
289+
{
290+
int status = PSA_ERROR_CORRUPTION_DETECTED;
162291

163292
#if defined(PSA_WANT_KEY_TYPE_DES)
164293
/* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept
@@ -170,27 +299,167 @@ static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation,
170299
}
171300
#endif
172301

173-
const mbedtls_cipher_info_t *cipher_info =
174-
mbedtls_cipher_info_from_psa(
175-
PSA_ALG_CMAC,
176-
psa_get_key_type(attributes),
177-
psa_get_key_bits(attributes),
178-
NULL);
302+
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
303+
psa_key_type_t key_type = psa_get_key_type(attributes);
304+
size_t key_bits = psa_get_key_bits(attributes);
305+
psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
179306

307+
/* Set up key attributes for PSA import */
308+
psa_set_key_type(&key_attributes, key_type);
309+
psa_set_key_bits(&key_attributes, key_bits);
310+
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT);
311+
psa_set_key_algorithm(&key_attributes, alg);
312+
313+
/* Import key for cipher operations */
314+
status = psa_import_key(&key_attributes, key_buffer, key_buffer_size, &cmac->key_id);
315+
if (status != PSA_SUCCESS) {
316+
return status;
317+
}
318+
319+
status = psa_cipher_encrypt_setup(&cmac->cipher_ctx, cmac->key_id, alg);
320+
if (status != 0) {
321+
return status;
322+
}
323+
324+
const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_psa(alg, key_type, key_bits, NULL);
180325
if (cipher_info == NULL) {
181326
return PSA_ERROR_NOT_SUPPORTED;
182327
}
183328

184-
ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info);
185-
if (ret != 0) {
329+
/* Ensure we're using a supported block cipher */
330+
switch (cipher_info->type) {
331+
case MBEDTLS_CIPHER_AES_128_ECB:
332+
case MBEDTLS_CIPHER_AES_192_ECB:
333+
case MBEDTLS_CIPHER_AES_256_ECB:
334+
case MBEDTLS_CIPHER_DES_EDE3_ECB:
335+
break;
336+
default:
337+
return PSA_ERROR_INVALID_ARGUMENT;
338+
}
339+
340+
cmac->unprocessed_len = 0;
341+
cmac->cipher_block_length = mbedtls_cipher_info_get_block_size(cipher_info);
342+
mbedtls_platform_zeroize(cmac->state, sizeof(cmac->state));
343+
mbedtls_platform_zeroize(cmac->unprocessed_block, sizeof(cmac->unprocessed_block));
344+
return PSA_SUCCESS;
345+
}
346+
347+
static psa_status_t psa_cmac_update_internal(
348+
mbedtls_psa_cmac_operation_t *cmac,
349+
const uint8_t *data,
350+
size_t data_length)
351+
{
352+
unsigned char *state = cmac->state;
353+
int ret = 0;
354+
size_t n, j, olen, block_size;
355+
356+
if (cmac == NULL || data == NULL) {
357+
return PSA_ERROR_INVALID_ARGUMENT;
358+
}
359+
360+
block_size = cmac->cipher_block_length;
361+
362+
/* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form
363+
* error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */
364+
MBEDTLS_ASSUME(block_size <= PSA_CMAC_MAX_BLOCK_SIZE);
365+
366+
/* Is there data still to process from the last call, that's greater in
367+
* size than a block? */
368+
if (cmac->unprocessed_len > 0 &&
369+
data_length > block_size - cmac->unprocessed_len) {
370+
memcpy(&cmac->unprocessed_block[cmac->unprocessed_len],
371+
data,
372+
block_size - cmac->unprocessed_len);
373+
374+
mbedtls_xor_no_simd(state, cmac->unprocessed_block, state, block_size);
375+
376+
if ((ret = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
377+
goto exit;
378+
}
379+
380+
data += block_size - cmac->unprocessed_len;
381+
data_length -= block_size - cmac->unprocessed_len;
382+
cmac->unprocessed_len = 0;
383+
}
384+
385+
/* n is the number of blocks including any final partial block */
386+
n = (data_length + block_size - 1) / block_size;
387+
388+
/* Iterate across the input data in block sized chunks, excluding any
389+
* final partial or complete block */
390+
for (j = 1; j < n; j++) {
391+
mbedtls_xor_no_simd(state, data, state, block_size);
392+
393+
if ((ret = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
394+
goto exit;
395+
}
396+
397+
data_length -= block_size;
398+
data += block_size;
399+
}
400+
401+
/* If there is data left over that wasn't aligned to a block */
402+
if (data_length > 0) {
403+
memcpy(&cmac->unprocessed_block[cmac->unprocessed_len],
404+
data,
405+
data_length);
406+
cmac->unprocessed_len += data_length;
407+
}
408+
409+
exit:
410+
return ret;
411+
}
412+
413+
static psa_status_t psa_cmac_finish_internal(
414+
mbedtls_psa_cmac_operation_t *cmac,
415+
uint8_t *mac, size_t mac_size)
416+
{
417+
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
418+
size_t olen, block_size;
419+
420+
unsigned char *state, *last_block;
421+
unsigned char K1[PSA_CMAC_MAX_BLOCK_SIZE];
422+
unsigned char K2[PSA_CMAC_MAX_BLOCK_SIZE];
423+
unsigned char M_last[PSA_CMAC_MAX_BLOCK_SIZE];
424+
425+
if (cmac == NULL || mac == NULL) {
426+
return PSA_ERROR_INVALID_ARGUMENT;
427+
}
428+
429+
state = cmac->state;
430+
block_size = cmac->cipher_block_length;
431+
432+
mbedtls_platform_zeroize(K1, sizeof(K1));
433+
mbedtls_platform_zeroize(K2, sizeof(K2));
434+
cmac_generate_subkeys(&cmac->cipher_ctx, block_size, K1, K2);
435+
436+
last_block = cmac->unprocessed_block;
437+
438+
/* Calculate last block */
439+
if (cmac->unprocessed_len < block_size) {
440+
cmac_pad(M_last, block_size, last_block, cmac->unprocessed_len);
441+
mbedtls_xor(M_last, M_last, K2, block_size);
442+
} else {
443+
/* Last block is complete block */
444+
mbedtls_xor(M_last, last_block, K1, block_size);
445+
}
446+
447+
mbedtls_xor(state, M_last, state, block_size);
448+
if ((status = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
186449
goto exit;
187450
}
188451

189-
ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac,
190-
key_buffer,
191-
psa_get_key_bits(attributes));
452+
memcpy(mac, state, mac_size);
453+
192454
exit:
193-
return mbedtls_to_psa_error(ret);
455+
mbedtls_platform_zeroize(K1, sizeof(K1));
456+
mbedtls_platform_zeroize(K2, sizeof(K2));
457+
458+
cmac->unprocessed_len = 0;
459+
mbedtls_platform_zeroize(cmac->unprocessed_block, sizeof(cmac->unprocessed_block));
460+
mbedtls_platform_zeroize(state, PSA_CMAC_MAX_BLOCK_SIZE);
461+
462+
return status;
194463
}
195464
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
196465

@@ -209,7 +478,7 @@ static psa_status_t mac_init(
209478

210479
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
211480
if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
212-
mbedtls_cipher_init(&operation->ctx.cmac);
481+
memset(&operation->ctx.cmac, 0, sizeof(operation->ctx.cmac));
213482
status = PSA_SUCCESS;
214483
} else
215484
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
@@ -241,7 +510,7 @@ psa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation)
241510
} else
242511
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
243512
if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
244-
mbedtls_cipher_free(&operation->ctx.cmac);
513+
return psa_cmac_abort_internal(&operation->ctx.cmac);
245514
} else
246515
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
247516
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
@@ -290,8 +559,7 @@ static psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation,
290559
if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {
291560
/* Key buffer size for CMAC is dictated by the key bits set on the
292561
* attributes, and previously validated by the core on key import. */
293-
(void) key_buffer_size;
294-
status = cmac_setup(operation, attributes, key_buffer);
562+
status = psa_cmac_setup_internal(&operation->ctx.cmac, attributes, key_buffer, key_buffer_size);
295563
} else
296564
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
297565
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
@@ -349,9 +617,7 @@ psa_status_t mbedtls_psa_mac_update(
349617

350618
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
351619
if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
352-
return mbedtls_to_psa_error(
353-
mbedtls_cipher_cmac_update(&operation->ctx.cmac,
354-
input, input_length));
620+
return psa_cmac_update_internal(&operation->ctx.cmac, input, input_length);
355621
} else
356622
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
357623
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
@@ -375,13 +641,7 @@ static psa_status_t psa_mac_finish_internal(
375641
{
376642
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
377643
if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
378-
uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE];
379-
int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp);
380-
if (ret == 0) {
381-
memcpy(mac, tmp, mac_size);
382-
}
383-
mbedtls_platform_zeroize(tmp, sizeof(tmp));
384-
return mbedtls_to_psa_error(ret);
644+
return psa_cmac_finish_internal(&operation->ctx.cmac, mac, mac_size);
385645
} else
386646
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
387647
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)

0 commit comments

Comments
 (0)