1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * NIST SP800-38C compliant CCM implementation 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6a8e1175bSopenharmony_ci */ 7a8e1175bSopenharmony_ci 8a8e1175bSopenharmony_ci/* 9a8e1175bSopenharmony_ci * Definition of CCM: 10a8e1175bSopenharmony_ci * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf 11a8e1175bSopenharmony_ci * RFC 3610 "Counter with CBC-MAC (CCM)" 12a8e1175bSopenharmony_ci * 13a8e1175bSopenharmony_ci * Related: 14a8e1175bSopenharmony_ci * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" 15a8e1175bSopenharmony_ci */ 16a8e1175bSopenharmony_ci 17a8e1175bSopenharmony_ci#include "common.h" 18a8e1175bSopenharmony_ci 19a8e1175bSopenharmony_ci#if defined(MBEDTLS_CCM_C) 20a8e1175bSopenharmony_ci 21a8e1175bSopenharmony_ci#include "mbedtls/ccm.h" 22a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h" 23a8e1175bSopenharmony_ci#include "mbedtls/error.h" 24a8e1175bSopenharmony_ci#include "mbedtls/constant_time.h" 25a8e1175bSopenharmony_ci 26a8e1175bSopenharmony_ci#if defined(MBEDTLS_BLOCK_CIPHER_C) 27a8e1175bSopenharmony_ci#include "block_cipher_internal.h" 28a8e1175bSopenharmony_ci#endif 29a8e1175bSopenharmony_ci 30a8e1175bSopenharmony_ci#include <string.h> 31a8e1175bSopenharmony_ci 32a8e1175bSopenharmony_ci#if defined(MBEDTLS_PLATFORM_C) 33a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 34a8e1175bSopenharmony_ci#else 35a8e1175bSopenharmony_ci#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 36a8e1175bSopenharmony_ci#include <stdio.h> 37a8e1175bSopenharmony_ci#define mbedtls_printf printf 38a8e1175bSopenharmony_ci#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 39a8e1175bSopenharmony_ci#endif /* MBEDTLS_PLATFORM_C */ 40a8e1175bSopenharmony_ci 41a8e1175bSopenharmony_ci#if !defined(MBEDTLS_CCM_ALT) 42a8e1175bSopenharmony_ci 43a8e1175bSopenharmony_ci 44a8e1175bSopenharmony_ci/* 45a8e1175bSopenharmony_ci * Initialize context 46a8e1175bSopenharmony_ci */ 47a8e1175bSopenharmony_civoid mbedtls_ccm_init(mbedtls_ccm_context *ctx) 48a8e1175bSopenharmony_ci{ 49a8e1175bSopenharmony_ci memset(ctx, 0, sizeof(mbedtls_ccm_context)); 50a8e1175bSopenharmony_ci} 51a8e1175bSopenharmony_ci 52a8e1175bSopenharmony_ciint mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, 53a8e1175bSopenharmony_ci mbedtls_cipher_id_t cipher, 54a8e1175bSopenharmony_ci const unsigned char *key, 55a8e1175bSopenharmony_ci unsigned int keybits) 56a8e1175bSopenharmony_ci{ 57a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 58a8e1175bSopenharmony_ci 59a8e1175bSopenharmony_ci#if defined(MBEDTLS_BLOCK_CIPHER_C) 60a8e1175bSopenharmony_ci mbedtls_block_cipher_free(&ctx->block_cipher_ctx); 61a8e1175bSopenharmony_ci 62a8e1175bSopenharmony_ci if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) { 63a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 64a8e1175bSopenharmony_ci } 65a8e1175bSopenharmony_ci 66a8e1175bSopenharmony_ci if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) { 67a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 68a8e1175bSopenharmony_ci } 69a8e1175bSopenharmony_ci#else 70a8e1175bSopenharmony_ci const mbedtls_cipher_info_t *cipher_info; 71a8e1175bSopenharmony_ci 72a8e1175bSopenharmony_ci cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, 73a8e1175bSopenharmony_ci MBEDTLS_MODE_ECB); 74a8e1175bSopenharmony_ci if (cipher_info == NULL) { 75a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 76a8e1175bSopenharmony_ci } 77a8e1175bSopenharmony_ci 78a8e1175bSopenharmony_ci if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { 79a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 80a8e1175bSopenharmony_ci } 81a8e1175bSopenharmony_ci 82a8e1175bSopenharmony_ci mbedtls_cipher_free(&ctx->cipher_ctx); 83a8e1175bSopenharmony_ci 84a8e1175bSopenharmony_ci if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { 85a8e1175bSopenharmony_ci return ret; 86a8e1175bSopenharmony_ci } 87a8e1175bSopenharmony_ci 88a8e1175bSopenharmony_ci if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, 89a8e1175bSopenharmony_ci MBEDTLS_ENCRYPT)) != 0) { 90a8e1175bSopenharmony_ci return ret; 91a8e1175bSopenharmony_ci } 92a8e1175bSopenharmony_ci#endif 93a8e1175bSopenharmony_ci 94a8e1175bSopenharmony_ci return ret; 95a8e1175bSopenharmony_ci} 96a8e1175bSopenharmony_ci 97a8e1175bSopenharmony_ci/* 98a8e1175bSopenharmony_ci * Free context 99a8e1175bSopenharmony_ci */ 100a8e1175bSopenharmony_civoid mbedtls_ccm_free(mbedtls_ccm_context *ctx) 101a8e1175bSopenharmony_ci{ 102a8e1175bSopenharmony_ci if (ctx == NULL) { 103a8e1175bSopenharmony_ci return; 104a8e1175bSopenharmony_ci } 105a8e1175bSopenharmony_ci#if defined(MBEDTLS_BLOCK_CIPHER_C) 106a8e1175bSopenharmony_ci mbedtls_block_cipher_free(&ctx->block_cipher_ctx); 107a8e1175bSopenharmony_ci#else 108a8e1175bSopenharmony_ci mbedtls_cipher_free(&ctx->cipher_ctx); 109a8e1175bSopenharmony_ci#endif 110a8e1175bSopenharmony_ci mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context)); 111a8e1175bSopenharmony_ci} 112a8e1175bSopenharmony_ci 113a8e1175bSopenharmony_ci#define CCM_STATE__CLEAR 0 114a8e1175bSopenharmony_ci#define CCM_STATE__STARTED (1 << 0) 115a8e1175bSopenharmony_ci#define CCM_STATE__LENGTHS_SET (1 << 1) 116a8e1175bSopenharmony_ci#define CCM_STATE__AUTH_DATA_STARTED (1 << 2) 117a8e1175bSopenharmony_ci#define CCM_STATE__AUTH_DATA_FINISHED (1 << 3) 118a8e1175bSopenharmony_ci#define CCM_STATE__ERROR (1 << 4) 119a8e1175bSopenharmony_ci 120a8e1175bSopenharmony_ci/* 121a8e1175bSopenharmony_ci * Encrypt or decrypt a partial block with CTR 122a8e1175bSopenharmony_ci */ 123a8e1175bSopenharmony_cistatic int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx, 124a8e1175bSopenharmony_ci size_t offset, size_t use_len, 125a8e1175bSopenharmony_ci const unsigned char *input, 126a8e1175bSopenharmony_ci unsigned char *output) 127a8e1175bSopenharmony_ci{ 128a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 129a8e1175bSopenharmony_ci unsigned char tmp_buf[16] = { 0 }; 130a8e1175bSopenharmony_ci 131a8e1175bSopenharmony_ci#if defined(MBEDTLS_BLOCK_CIPHER_C) 132a8e1175bSopenharmony_ci ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->ctr, tmp_buf); 133a8e1175bSopenharmony_ci#else 134a8e1175bSopenharmony_ci size_t olen = 0; 135a8e1175bSopenharmony_ci ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, &olen); 136a8e1175bSopenharmony_ci#endif 137a8e1175bSopenharmony_ci if (ret != 0) { 138a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__ERROR; 139a8e1175bSopenharmony_ci mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); 140a8e1175bSopenharmony_ci return ret; 141a8e1175bSopenharmony_ci } 142a8e1175bSopenharmony_ci 143a8e1175bSopenharmony_ci mbedtls_xor(output, input, tmp_buf + offset, use_len); 144a8e1175bSopenharmony_ci 145a8e1175bSopenharmony_ci mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); 146a8e1175bSopenharmony_ci return ret; 147a8e1175bSopenharmony_ci} 148a8e1175bSopenharmony_ci 149a8e1175bSopenharmony_cistatic void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx) 150a8e1175bSopenharmony_ci{ 151a8e1175bSopenharmony_ci ctx->state = CCM_STATE__CLEAR; 152a8e1175bSopenharmony_ci memset(ctx->y, 0, 16); 153a8e1175bSopenharmony_ci memset(ctx->ctr, 0, 16); 154a8e1175bSopenharmony_ci} 155a8e1175bSopenharmony_ci 156a8e1175bSopenharmony_cistatic int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx) 157a8e1175bSopenharmony_ci{ 158a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 159a8e1175bSopenharmony_ci unsigned char i; 160a8e1175bSopenharmony_ci size_t len_left; 161a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BLOCK_CIPHER_C) 162a8e1175bSopenharmony_ci size_t olen; 163a8e1175bSopenharmony_ci#endif 164a8e1175bSopenharmony_ci 165a8e1175bSopenharmony_ci /* length calculation can be done only after both 166a8e1175bSopenharmony_ci * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed 167a8e1175bSopenharmony_ci */ 168a8e1175bSopenharmony_ci if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) { 169a8e1175bSopenharmony_ci return 0; 170a8e1175bSopenharmony_ci } 171a8e1175bSopenharmony_ci 172a8e1175bSopenharmony_ci /* CCM expects non-empty tag. 173a8e1175bSopenharmony_ci * CCM* allows empty tag. For CCM* without tag, ignore plaintext length. 174a8e1175bSopenharmony_ci */ 175a8e1175bSopenharmony_ci if (ctx->tag_len == 0) { 176a8e1175bSopenharmony_ci if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { 177a8e1175bSopenharmony_ci ctx->plaintext_len = 0; 178a8e1175bSopenharmony_ci } else { 179a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 180a8e1175bSopenharmony_ci } 181a8e1175bSopenharmony_ci } 182a8e1175bSopenharmony_ci 183a8e1175bSopenharmony_ci /* 184a8e1175bSopenharmony_ci * First block: 185a8e1175bSopenharmony_ci * 0 .. 0 flags 186a8e1175bSopenharmony_ci * 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts() 187a8e1175bSopenharmony_ci * iv_len+1 .. 15 length 188a8e1175bSopenharmony_ci * 189a8e1175bSopenharmony_ci * With flags as (bits): 190a8e1175bSopenharmony_ci * 7 0 191a8e1175bSopenharmony_ci * 6 add present? 192a8e1175bSopenharmony_ci * 5 .. 3 (t - 2) / 2 193a8e1175bSopenharmony_ci * 2 .. 0 q - 1 194a8e1175bSopenharmony_ci */ 195a8e1175bSopenharmony_ci ctx->y[0] |= (ctx->add_len > 0) << 6; 196a8e1175bSopenharmony_ci ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3; 197a8e1175bSopenharmony_ci ctx->y[0] |= ctx->q - 1; 198a8e1175bSopenharmony_ci 199a8e1175bSopenharmony_ci for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) { 200a8e1175bSopenharmony_ci ctx->y[15-i] = MBEDTLS_BYTE_0(len_left); 201a8e1175bSopenharmony_ci } 202a8e1175bSopenharmony_ci 203a8e1175bSopenharmony_ci if (len_left > 0) { 204a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__ERROR; 205a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 206a8e1175bSopenharmony_ci } 207a8e1175bSopenharmony_ci 208a8e1175bSopenharmony_ci /* Start CBC-MAC with first block*/ 209a8e1175bSopenharmony_ci#if defined(MBEDTLS_BLOCK_CIPHER_C) 210a8e1175bSopenharmony_ci ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); 211a8e1175bSopenharmony_ci#else 212a8e1175bSopenharmony_ci ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); 213a8e1175bSopenharmony_ci#endif 214a8e1175bSopenharmony_ci if (ret != 0) { 215a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__ERROR; 216a8e1175bSopenharmony_ci return ret; 217a8e1175bSopenharmony_ci } 218a8e1175bSopenharmony_ci 219a8e1175bSopenharmony_ci return 0; 220a8e1175bSopenharmony_ci} 221a8e1175bSopenharmony_ci 222a8e1175bSopenharmony_ciint mbedtls_ccm_starts(mbedtls_ccm_context *ctx, 223a8e1175bSopenharmony_ci int mode, 224a8e1175bSopenharmony_ci const unsigned char *iv, 225a8e1175bSopenharmony_ci size_t iv_len) 226a8e1175bSopenharmony_ci{ 227a8e1175bSopenharmony_ci /* Also implies q is within bounds */ 228a8e1175bSopenharmony_ci if (iv_len < 7 || iv_len > 13) { 229a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 230a8e1175bSopenharmony_ci } 231a8e1175bSopenharmony_ci 232a8e1175bSopenharmony_ci ctx->mode = mode; 233a8e1175bSopenharmony_ci ctx->q = 16 - 1 - (unsigned char) iv_len; 234a8e1175bSopenharmony_ci 235a8e1175bSopenharmony_ci /* 236a8e1175bSopenharmony_ci * Prepare counter block for encryption: 237a8e1175bSopenharmony_ci * 0 .. 0 flags 238a8e1175bSopenharmony_ci * 1 .. iv_len nonce (aka iv) 239a8e1175bSopenharmony_ci * iv_len+1 .. 15 counter (initially 1) 240a8e1175bSopenharmony_ci * 241a8e1175bSopenharmony_ci * With flags as (bits): 242a8e1175bSopenharmony_ci * 7 .. 3 0 243a8e1175bSopenharmony_ci * 2 .. 0 q - 1 244a8e1175bSopenharmony_ci */ 245a8e1175bSopenharmony_ci memset(ctx->ctr, 0, 16); 246a8e1175bSopenharmony_ci ctx->ctr[0] = ctx->q - 1; 247a8e1175bSopenharmony_ci memcpy(ctx->ctr + 1, iv, iv_len); 248a8e1175bSopenharmony_ci memset(ctx->ctr + 1 + iv_len, 0, ctx->q); 249a8e1175bSopenharmony_ci ctx->ctr[15] = 1; 250a8e1175bSopenharmony_ci 251a8e1175bSopenharmony_ci /* 252a8e1175bSopenharmony_ci * See ccm_calculate_first_block_if_ready() for block layout description 253a8e1175bSopenharmony_ci */ 254a8e1175bSopenharmony_ci memcpy(ctx->y + 1, iv, iv_len); 255a8e1175bSopenharmony_ci 256a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__STARTED; 257a8e1175bSopenharmony_ci return ccm_calculate_first_block_if_ready(ctx); 258a8e1175bSopenharmony_ci} 259a8e1175bSopenharmony_ci 260a8e1175bSopenharmony_ciint mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, 261a8e1175bSopenharmony_ci size_t total_ad_len, 262a8e1175bSopenharmony_ci size_t plaintext_len, 263a8e1175bSopenharmony_ci size_t tag_len) 264a8e1175bSopenharmony_ci{ 265a8e1175bSopenharmony_ci /* 266a8e1175bSopenharmony_ci * Check length requirements: SP800-38C A.1 267a8e1175bSopenharmony_ci * Additional requirement: a < 2^16 - 2^8 to simplify the code. 268a8e1175bSopenharmony_ci * 'length' checked later (when writing it to the first block) 269a8e1175bSopenharmony_ci * 270a8e1175bSopenharmony_ci * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). 271a8e1175bSopenharmony_ci */ 272a8e1175bSopenharmony_ci if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) { 273a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 274a8e1175bSopenharmony_ci } 275a8e1175bSopenharmony_ci 276a8e1175bSopenharmony_ci if (total_ad_len >= 0xFF00) { 277a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 278a8e1175bSopenharmony_ci } 279a8e1175bSopenharmony_ci 280a8e1175bSopenharmony_ci ctx->plaintext_len = plaintext_len; 281a8e1175bSopenharmony_ci ctx->add_len = total_ad_len; 282a8e1175bSopenharmony_ci ctx->tag_len = tag_len; 283a8e1175bSopenharmony_ci ctx->processed = 0; 284a8e1175bSopenharmony_ci 285a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__LENGTHS_SET; 286a8e1175bSopenharmony_ci return ccm_calculate_first_block_if_ready(ctx); 287a8e1175bSopenharmony_ci} 288a8e1175bSopenharmony_ci 289a8e1175bSopenharmony_ciint mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, 290a8e1175bSopenharmony_ci const unsigned char *add, 291a8e1175bSopenharmony_ci size_t add_len) 292a8e1175bSopenharmony_ci{ 293a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 294a8e1175bSopenharmony_ci size_t use_len, offset; 295a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BLOCK_CIPHER_C) 296a8e1175bSopenharmony_ci size_t olen; 297a8e1175bSopenharmony_ci#endif 298a8e1175bSopenharmony_ci 299a8e1175bSopenharmony_ci if (ctx->state & CCM_STATE__ERROR) { 300a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 301a8e1175bSopenharmony_ci } 302a8e1175bSopenharmony_ci 303a8e1175bSopenharmony_ci if (add_len > 0) { 304a8e1175bSopenharmony_ci if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) { 305a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 306a8e1175bSopenharmony_ci } 307a8e1175bSopenharmony_ci 308a8e1175bSopenharmony_ci if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) { 309a8e1175bSopenharmony_ci if (add_len > ctx->add_len) { 310a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 311a8e1175bSopenharmony_ci } 312a8e1175bSopenharmony_ci 313a8e1175bSopenharmony_ci ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF); 314a8e1175bSopenharmony_ci ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF); 315a8e1175bSopenharmony_ci 316a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__AUTH_DATA_STARTED; 317a8e1175bSopenharmony_ci } else if (ctx->processed + add_len > ctx->add_len) { 318a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 319a8e1175bSopenharmony_ci } 320a8e1175bSopenharmony_ci 321a8e1175bSopenharmony_ci while (add_len > 0) { 322a8e1175bSopenharmony_ci offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1] 323a8e1175bSopenharmony_ci * holding total auth data length */ 324a8e1175bSopenharmony_ci use_len = 16 - offset; 325a8e1175bSopenharmony_ci 326a8e1175bSopenharmony_ci if (use_len > add_len) { 327a8e1175bSopenharmony_ci use_len = add_len; 328a8e1175bSopenharmony_ci } 329a8e1175bSopenharmony_ci 330a8e1175bSopenharmony_ci mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len); 331a8e1175bSopenharmony_ci 332a8e1175bSopenharmony_ci ctx->processed += use_len; 333a8e1175bSopenharmony_ci add_len -= use_len; 334a8e1175bSopenharmony_ci add += use_len; 335a8e1175bSopenharmony_ci 336a8e1175bSopenharmony_ci if (use_len + offset == 16 || ctx->processed == ctx->add_len) { 337a8e1175bSopenharmony_ci#if defined(MBEDTLS_BLOCK_CIPHER_C) 338a8e1175bSopenharmony_ci ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); 339a8e1175bSopenharmony_ci#else 340a8e1175bSopenharmony_ci ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); 341a8e1175bSopenharmony_ci#endif 342a8e1175bSopenharmony_ci if (ret != 0) { 343a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__ERROR; 344a8e1175bSopenharmony_ci return ret; 345a8e1175bSopenharmony_ci } 346a8e1175bSopenharmony_ci } 347a8e1175bSopenharmony_ci } 348a8e1175bSopenharmony_ci 349a8e1175bSopenharmony_ci if (ctx->processed == ctx->add_len) { 350a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__AUTH_DATA_FINISHED; 351a8e1175bSopenharmony_ci ctx->processed = 0; // prepare for mbedtls_ccm_update() 352a8e1175bSopenharmony_ci } 353a8e1175bSopenharmony_ci } 354a8e1175bSopenharmony_ci 355a8e1175bSopenharmony_ci return 0; 356a8e1175bSopenharmony_ci} 357a8e1175bSopenharmony_ci 358a8e1175bSopenharmony_ciint mbedtls_ccm_update(mbedtls_ccm_context *ctx, 359a8e1175bSopenharmony_ci const unsigned char *input, size_t input_len, 360a8e1175bSopenharmony_ci unsigned char *output, size_t output_size, 361a8e1175bSopenharmony_ci size_t *output_len) 362a8e1175bSopenharmony_ci{ 363a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 364a8e1175bSopenharmony_ci unsigned char i; 365a8e1175bSopenharmony_ci size_t use_len, offset; 366a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BLOCK_CIPHER_C) 367a8e1175bSopenharmony_ci size_t olen; 368a8e1175bSopenharmony_ci#endif 369a8e1175bSopenharmony_ci 370a8e1175bSopenharmony_ci unsigned char local_output[16]; 371a8e1175bSopenharmony_ci 372a8e1175bSopenharmony_ci if (ctx->state & CCM_STATE__ERROR) { 373a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 374a8e1175bSopenharmony_ci } 375a8e1175bSopenharmony_ci 376a8e1175bSopenharmony_ci /* Check against plaintext length only if performing operation with 377a8e1175bSopenharmony_ci * authentication 378a8e1175bSopenharmony_ci */ 379a8e1175bSopenharmony_ci if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) { 380a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 381a8e1175bSopenharmony_ci } 382a8e1175bSopenharmony_ci 383a8e1175bSopenharmony_ci if (output_size < input_len) { 384a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 385a8e1175bSopenharmony_ci } 386a8e1175bSopenharmony_ci *output_len = input_len; 387a8e1175bSopenharmony_ci 388a8e1175bSopenharmony_ci ret = 0; 389a8e1175bSopenharmony_ci 390a8e1175bSopenharmony_ci while (input_len > 0) { 391a8e1175bSopenharmony_ci offset = ctx->processed % 16; 392a8e1175bSopenharmony_ci 393a8e1175bSopenharmony_ci use_len = 16 - offset; 394a8e1175bSopenharmony_ci 395a8e1175bSopenharmony_ci if (use_len > input_len) { 396a8e1175bSopenharmony_ci use_len = input_len; 397a8e1175bSopenharmony_ci } 398a8e1175bSopenharmony_ci 399a8e1175bSopenharmony_ci ctx->processed += use_len; 400a8e1175bSopenharmony_ci 401a8e1175bSopenharmony_ci if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \ 402a8e1175bSopenharmony_ci ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) { 403a8e1175bSopenharmony_ci mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len); 404a8e1175bSopenharmony_ci 405a8e1175bSopenharmony_ci if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { 406a8e1175bSopenharmony_ci#if defined(MBEDTLS_BLOCK_CIPHER_C) 407a8e1175bSopenharmony_ci ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); 408a8e1175bSopenharmony_ci#else 409a8e1175bSopenharmony_ci ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); 410a8e1175bSopenharmony_ci#endif 411a8e1175bSopenharmony_ci if (ret != 0) { 412a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__ERROR; 413a8e1175bSopenharmony_ci goto exit; 414a8e1175bSopenharmony_ci } 415a8e1175bSopenharmony_ci } 416a8e1175bSopenharmony_ci 417a8e1175bSopenharmony_ci ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output); 418a8e1175bSopenharmony_ci if (ret != 0) { 419a8e1175bSopenharmony_ci goto exit; 420a8e1175bSopenharmony_ci } 421a8e1175bSopenharmony_ci } 422a8e1175bSopenharmony_ci 423a8e1175bSopenharmony_ci if (ctx->mode == MBEDTLS_CCM_DECRYPT || \ 424a8e1175bSopenharmony_ci ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { 425a8e1175bSopenharmony_ci /* Since output may be in shared memory, we cannot be sure that 426a8e1175bSopenharmony_ci * it will contain what we wrote to it. Therefore, we should avoid using 427a8e1175bSopenharmony_ci * it as input to any operations. 428a8e1175bSopenharmony_ci * Write decrypted data to local_output to avoid using output variable as 429a8e1175bSopenharmony_ci * input in the XOR operation for Y. 430a8e1175bSopenharmony_ci */ 431a8e1175bSopenharmony_ci ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output); 432a8e1175bSopenharmony_ci if (ret != 0) { 433a8e1175bSopenharmony_ci goto exit; 434a8e1175bSopenharmony_ci } 435a8e1175bSopenharmony_ci 436a8e1175bSopenharmony_ci mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len); 437a8e1175bSopenharmony_ci 438a8e1175bSopenharmony_ci memcpy(output, local_output, use_len); 439a8e1175bSopenharmony_ci 440a8e1175bSopenharmony_ci if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { 441a8e1175bSopenharmony_ci#if defined(MBEDTLS_BLOCK_CIPHER_C) 442a8e1175bSopenharmony_ci ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); 443a8e1175bSopenharmony_ci#else 444a8e1175bSopenharmony_ci ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); 445a8e1175bSopenharmony_ci#endif 446a8e1175bSopenharmony_ci if (ret != 0) { 447a8e1175bSopenharmony_ci ctx->state |= CCM_STATE__ERROR; 448a8e1175bSopenharmony_ci goto exit; 449a8e1175bSopenharmony_ci } 450a8e1175bSopenharmony_ci } 451a8e1175bSopenharmony_ci } 452a8e1175bSopenharmony_ci 453a8e1175bSopenharmony_ci if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { 454a8e1175bSopenharmony_ci for (i = 0; i < ctx->q; i++) { 455a8e1175bSopenharmony_ci if (++(ctx->ctr)[15-i] != 0) { 456a8e1175bSopenharmony_ci break; 457a8e1175bSopenharmony_ci } 458a8e1175bSopenharmony_ci } 459a8e1175bSopenharmony_ci } 460a8e1175bSopenharmony_ci 461a8e1175bSopenharmony_ci input_len -= use_len; 462a8e1175bSopenharmony_ci input += use_len; 463a8e1175bSopenharmony_ci output += use_len; 464a8e1175bSopenharmony_ci } 465a8e1175bSopenharmony_ci 466a8e1175bSopenharmony_ciexit: 467a8e1175bSopenharmony_ci mbedtls_platform_zeroize(local_output, 16); 468a8e1175bSopenharmony_ci 469a8e1175bSopenharmony_ci return ret; 470a8e1175bSopenharmony_ci} 471a8e1175bSopenharmony_ci 472a8e1175bSopenharmony_ciint mbedtls_ccm_finish(mbedtls_ccm_context *ctx, 473a8e1175bSopenharmony_ci unsigned char *tag, size_t tag_len) 474a8e1175bSopenharmony_ci{ 475a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 476a8e1175bSopenharmony_ci unsigned char i; 477a8e1175bSopenharmony_ci 478a8e1175bSopenharmony_ci if (ctx->state & CCM_STATE__ERROR) { 479a8e1175bSopenharmony_ci return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 480a8e1175bSopenharmony_ci } 481a8e1175bSopenharmony_ci 482a8e1175bSopenharmony_ci if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) { 483a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 484a8e1175bSopenharmony_ci } 485a8e1175bSopenharmony_ci 486a8e1175bSopenharmony_ci if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) { 487a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_BAD_INPUT; 488a8e1175bSopenharmony_ci } 489a8e1175bSopenharmony_ci 490a8e1175bSopenharmony_ci /* 491a8e1175bSopenharmony_ci * Authentication: reset counter and crypt/mask internal tag 492a8e1175bSopenharmony_ci */ 493a8e1175bSopenharmony_ci for (i = 0; i < ctx->q; i++) { 494a8e1175bSopenharmony_ci ctx->ctr[15-i] = 0; 495a8e1175bSopenharmony_ci } 496a8e1175bSopenharmony_ci 497a8e1175bSopenharmony_ci ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y); 498a8e1175bSopenharmony_ci if (ret != 0) { 499a8e1175bSopenharmony_ci return ret; 500a8e1175bSopenharmony_ci } 501a8e1175bSopenharmony_ci if (tag != NULL) { 502a8e1175bSopenharmony_ci memcpy(tag, ctx->y, tag_len); 503a8e1175bSopenharmony_ci } 504a8e1175bSopenharmony_ci mbedtls_ccm_clear_state(ctx); 505a8e1175bSopenharmony_ci 506a8e1175bSopenharmony_ci return 0; 507a8e1175bSopenharmony_ci} 508a8e1175bSopenharmony_ci 509a8e1175bSopenharmony_ci/* 510a8e1175bSopenharmony_ci * Authenticated encryption or decryption 511a8e1175bSopenharmony_ci */ 512a8e1175bSopenharmony_cistatic int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, 513a8e1175bSopenharmony_ci const unsigned char *iv, size_t iv_len, 514a8e1175bSopenharmony_ci const unsigned char *add, size_t add_len, 515a8e1175bSopenharmony_ci const unsigned char *input, unsigned char *output, 516a8e1175bSopenharmony_ci unsigned char *tag, size_t tag_len) 517a8e1175bSopenharmony_ci{ 518a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 519a8e1175bSopenharmony_ci size_t olen; 520a8e1175bSopenharmony_ci 521a8e1175bSopenharmony_ci if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) { 522a8e1175bSopenharmony_ci return ret; 523a8e1175bSopenharmony_ci } 524a8e1175bSopenharmony_ci 525a8e1175bSopenharmony_ci if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) { 526a8e1175bSopenharmony_ci return ret; 527a8e1175bSopenharmony_ci } 528a8e1175bSopenharmony_ci 529a8e1175bSopenharmony_ci if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) { 530a8e1175bSopenharmony_ci return ret; 531a8e1175bSopenharmony_ci } 532a8e1175bSopenharmony_ci 533a8e1175bSopenharmony_ci if ((ret = mbedtls_ccm_update(ctx, input, length, 534a8e1175bSopenharmony_ci output, length, &olen)) != 0) { 535a8e1175bSopenharmony_ci return ret; 536a8e1175bSopenharmony_ci } 537a8e1175bSopenharmony_ci 538a8e1175bSopenharmony_ci if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) { 539a8e1175bSopenharmony_ci return ret; 540a8e1175bSopenharmony_ci } 541a8e1175bSopenharmony_ci 542a8e1175bSopenharmony_ci return 0; 543a8e1175bSopenharmony_ci} 544a8e1175bSopenharmony_ci 545a8e1175bSopenharmony_ci/* 546a8e1175bSopenharmony_ci * Authenticated encryption 547a8e1175bSopenharmony_ci */ 548a8e1175bSopenharmony_ciint mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, 549a8e1175bSopenharmony_ci const unsigned char *iv, size_t iv_len, 550a8e1175bSopenharmony_ci const unsigned char *add, size_t add_len, 551a8e1175bSopenharmony_ci const unsigned char *input, unsigned char *output, 552a8e1175bSopenharmony_ci unsigned char *tag, size_t tag_len) 553a8e1175bSopenharmony_ci{ 554a8e1175bSopenharmony_ci return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len, 555a8e1175bSopenharmony_ci add, add_len, input, output, tag, tag_len); 556a8e1175bSopenharmony_ci} 557a8e1175bSopenharmony_ci 558a8e1175bSopenharmony_ciint mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, 559a8e1175bSopenharmony_ci const unsigned char *iv, size_t iv_len, 560a8e1175bSopenharmony_ci const unsigned char *add, size_t add_len, 561a8e1175bSopenharmony_ci const unsigned char *input, unsigned char *output, 562a8e1175bSopenharmony_ci unsigned char *tag, size_t tag_len) 563a8e1175bSopenharmony_ci{ 564a8e1175bSopenharmony_ci return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len, 565a8e1175bSopenharmony_ci add, add_len, input, output, tag, tag_len); 566a8e1175bSopenharmony_ci} 567a8e1175bSopenharmony_ci 568a8e1175bSopenharmony_ci/* 569a8e1175bSopenharmony_ci * Authenticated decryption 570a8e1175bSopenharmony_ci */ 571a8e1175bSopenharmony_cistatic int mbedtls_ccm_compare_tags(const unsigned char *tag1, 572a8e1175bSopenharmony_ci const unsigned char *tag2, 573a8e1175bSopenharmony_ci size_t tag_len) 574a8e1175bSopenharmony_ci{ 575a8e1175bSopenharmony_ci /* Check tag in "constant-time" */ 576a8e1175bSopenharmony_ci int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len); 577a8e1175bSopenharmony_ci 578a8e1175bSopenharmony_ci if (diff != 0) { 579a8e1175bSopenharmony_ci return MBEDTLS_ERR_CCM_AUTH_FAILED; 580a8e1175bSopenharmony_ci } 581a8e1175bSopenharmony_ci 582a8e1175bSopenharmony_ci return 0; 583a8e1175bSopenharmony_ci} 584a8e1175bSopenharmony_ci 585a8e1175bSopenharmony_cistatic int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length, 586a8e1175bSopenharmony_ci const unsigned char *iv, size_t iv_len, 587a8e1175bSopenharmony_ci const unsigned char *add, size_t add_len, 588a8e1175bSopenharmony_ci const unsigned char *input, unsigned char *output, 589a8e1175bSopenharmony_ci const unsigned char *tag, size_t tag_len) 590a8e1175bSopenharmony_ci{ 591a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 592a8e1175bSopenharmony_ci unsigned char check_tag[16]; 593a8e1175bSopenharmony_ci 594a8e1175bSopenharmony_ci if ((ret = ccm_auth_crypt(ctx, mode, length, 595a8e1175bSopenharmony_ci iv, iv_len, add, add_len, 596a8e1175bSopenharmony_ci input, output, check_tag, tag_len)) != 0) { 597a8e1175bSopenharmony_ci return ret; 598a8e1175bSopenharmony_ci } 599a8e1175bSopenharmony_ci 600a8e1175bSopenharmony_ci if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) { 601a8e1175bSopenharmony_ci mbedtls_platform_zeroize(output, length); 602a8e1175bSopenharmony_ci return ret; 603a8e1175bSopenharmony_ci } 604a8e1175bSopenharmony_ci 605a8e1175bSopenharmony_ci return 0; 606a8e1175bSopenharmony_ci} 607a8e1175bSopenharmony_ci 608a8e1175bSopenharmony_ciint mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, 609a8e1175bSopenharmony_ci const unsigned char *iv, size_t iv_len, 610a8e1175bSopenharmony_ci const unsigned char *add, size_t add_len, 611a8e1175bSopenharmony_ci const unsigned char *input, unsigned char *output, 612a8e1175bSopenharmony_ci const unsigned char *tag, size_t tag_len) 613a8e1175bSopenharmony_ci{ 614a8e1175bSopenharmony_ci return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length, 615a8e1175bSopenharmony_ci iv, iv_len, add, add_len, 616a8e1175bSopenharmony_ci input, output, tag, tag_len); 617a8e1175bSopenharmony_ci} 618a8e1175bSopenharmony_ci 619a8e1175bSopenharmony_ciint mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, 620a8e1175bSopenharmony_ci const unsigned char *iv, size_t iv_len, 621a8e1175bSopenharmony_ci const unsigned char *add, size_t add_len, 622a8e1175bSopenharmony_ci const unsigned char *input, unsigned char *output, 623a8e1175bSopenharmony_ci const unsigned char *tag, size_t tag_len) 624a8e1175bSopenharmony_ci{ 625a8e1175bSopenharmony_ci return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length, 626a8e1175bSopenharmony_ci iv, iv_len, add, add_len, 627a8e1175bSopenharmony_ci input, output, tag, tag_len); 628a8e1175bSopenharmony_ci} 629a8e1175bSopenharmony_ci#endif /* !MBEDTLS_CCM_ALT */ 630a8e1175bSopenharmony_ci 631a8e1175bSopenharmony_ci#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) 632a8e1175bSopenharmony_ci/* 633a8e1175bSopenharmony_ci * Examples 1 to 3 from SP800-38C Appendix C 634a8e1175bSopenharmony_ci */ 635a8e1175bSopenharmony_ci 636a8e1175bSopenharmony_ci#define NB_TESTS 3 637a8e1175bSopenharmony_ci#define CCM_SELFTEST_PT_MAX_LEN 24 638a8e1175bSopenharmony_ci#define CCM_SELFTEST_CT_MAX_LEN 32 639a8e1175bSopenharmony_ci/* 640a8e1175bSopenharmony_ci * The data is the same for all tests, only the used length changes 641a8e1175bSopenharmony_ci */ 642a8e1175bSopenharmony_cistatic const unsigned char key_test_data[] = { 643a8e1175bSopenharmony_ci 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 644a8e1175bSopenharmony_ci 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f 645a8e1175bSopenharmony_ci}; 646a8e1175bSopenharmony_ci 647a8e1175bSopenharmony_cistatic const unsigned char iv_test_data[] = { 648a8e1175bSopenharmony_ci 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 649a8e1175bSopenharmony_ci 0x18, 0x19, 0x1a, 0x1b 650a8e1175bSopenharmony_ci}; 651a8e1175bSopenharmony_ci 652a8e1175bSopenharmony_cistatic const unsigned char ad_test_data[] = { 653a8e1175bSopenharmony_ci 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 654a8e1175bSopenharmony_ci 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 655a8e1175bSopenharmony_ci 0x10, 0x11, 0x12, 0x13 656a8e1175bSopenharmony_ci}; 657a8e1175bSopenharmony_ci 658a8e1175bSopenharmony_cistatic const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = { 659a8e1175bSopenharmony_ci 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 660a8e1175bSopenharmony_ci 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 661a8e1175bSopenharmony_ci 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 662a8e1175bSopenharmony_ci}; 663a8e1175bSopenharmony_ci 664a8e1175bSopenharmony_cistatic const size_t iv_len_test_data[NB_TESTS] = { 7, 8, 12 }; 665a8e1175bSopenharmony_cistatic const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 }; 666a8e1175bSopenharmony_cistatic const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 }; 667a8e1175bSopenharmony_cistatic const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 }; 668a8e1175bSopenharmony_ci 669a8e1175bSopenharmony_cistatic const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { 670a8e1175bSopenharmony_ci { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, 671a8e1175bSopenharmony_ci { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, 672a8e1175bSopenharmony_ci 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, 673a8e1175bSopenharmony_ci 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, 674a8e1175bSopenharmony_ci { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, 675a8e1175bSopenharmony_ci 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, 676a8e1175bSopenharmony_ci 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, 677a8e1175bSopenharmony_ci 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } 678a8e1175bSopenharmony_ci}; 679a8e1175bSopenharmony_ci 680a8e1175bSopenharmony_ciint mbedtls_ccm_self_test(int verbose) 681a8e1175bSopenharmony_ci{ 682a8e1175bSopenharmony_ci mbedtls_ccm_context ctx; 683a8e1175bSopenharmony_ci /* 684a8e1175bSopenharmony_ci * Some hardware accelerators require the input and output buffers 685a8e1175bSopenharmony_ci * would be in RAM, because the flash is not accessible. 686a8e1175bSopenharmony_ci * Use buffers on the stack to hold the test vectors data. 687a8e1175bSopenharmony_ci */ 688a8e1175bSopenharmony_ci unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; 689a8e1175bSopenharmony_ci unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; 690a8e1175bSopenharmony_ci size_t i; 691a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 692a8e1175bSopenharmony_ci 693a8e1175bSopenharmony_ci mbedtls_ccm_init(&ctx); 694a8e1175bSopenharmony_ci 695a8e1175bSopenharmony_ci if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data, 696a8e1175bSopenharmony_ci 8 * sizeof(key_test_data)) != 0) { 697a8e1175bSopenharmony_ci if (verbose != 0) { 698a8e1175bSopenharmony_ci mbedtls_printf(" CCM: setup failed"); 699a8e1175bSopenharmony_ci } 700a8e1175bSopenharmony_ci 701a8e1175bSopenharmony_ci return 1; 702a8e1175bSopenharmony_ci } 703a8e1175bSopenharmony_ci 704a8e1175bSopenharmony_ci for (i = 0; i < NB_TESTS; i++) { 705a8e1175bSopenharmony_ci if (verbose != 0) { 706a8e1175bSopenharmony_ci mbedtls_printf(" CCM-AES #%u: ", (unsigned int) i + 1); 707a8e1175bSopenharmony_ci } 708a8e1175bSopenharmony_ci 709a8e1175bSopenharmony_ci memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN); 710a8e1175bSopenharmony_ci memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN); 711a8e1175bSopenharmony_ci memcpy(plaintext, msg_test_data, msg_len_test_data[i]); 712a8e1175bSopenharmony_ci 713a8e1175bSopenharmony_ci ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i], 714a8e1175bSopenharmony_ci iv_test_data, iv_len_test_data[i], 715a8e1175bSopenharmony_ci ad_test_data, add_len_test_data[i], 716a8e1175bSopenharmony_ci plaintext, ciphertext, 717a8e1175bSopenharmony_ci ciphertext + msg_len_test_data[i], 718a8e1175bSopenharmony_ci tag_len_test_data[i]); 719a8e1175bSopenharmony_ci 720a8e1175bSopenharmony_ci if (ret != 0 || 721a8e1175bSopenharmony_ci memcmp(ciphertext, res_test_data[i], 722a8e1175bSopenharmony_ci msg_len_test_data[i] + tag_len_test_data[i]) != 0) { 723a8e1175bSopenharmony_ci if (verbose != 0) { 724a8e1175bSopenharmony_ci mbedtls_printf("failed\n"); 725a8e1175bSopenharmony_ci } 726a8e1175bSopenharmony_ci 727a8e1175bSopenharmony_ci return 1; 728a8e1175bSopenharmony_ci } 729a8e1175bSopenharmony_ci memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN); 730a8e1175bSopenharmony_ci 731a8e1175bSopenharmony_ci ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i], 732a8e1175bSopenharmony_ci iv_test_data, iv_len_test_data[i], 733a8e1175bSopenharmony_ci ad_test_data, add_len_test_data[i], 734a8e1175bSopenharmony_ci ciphertext, plaintext, 735a8e1175bSopenharmony_ci ciphertext + msg_len_test_data[i], 736a8e1175bSopenharmony_ci tag_len_test_data[i]); 737a8e1175bSopenharmony_ci 738a8e1175bSopenharmony_ci if (ret != 0 || 739a8e1175bSopenharmony_ci memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) { 740a8e1175bSopenharmony_ci if (verbose != 0) { 741a8e1175bSopenharmony_ci mbedtls_printf("failed\n"); 742a8e1175bSopenharmony_ci } 743a8e1175bSopenharmony_ci 744a8e1175bSopenharmony_ci return 1; 745a8e1175bSopenharmony_ci } 746a8e1175bSopenharmony_ci 747a8e1175bSopenharmony_ci if (verbose != 0) { 748a8e1175bSopenharmony_ci mbedtls_printf("passed\n"); 749a8e1175bSopenharmony_ci } 750a8e1175bSopenharmony_ci } 751a8e1175bSopenharmony_ci 752a8e1175bSopenharmony_ci mbedtls_ccm_free(&ctx); 753a8e1175bSopenharmony_ci 754a8e1175bSopenharmony_ci if (verbose != 0) { 755a8e1175bSopenharmony_ci mbedtls_printf("\n"); 756a8e1175bSopenharmony_ci } 757a8e1175bSopenharmony_ci 758a8e1175bSopenharmony_ci return 0; 759a8e1175bSopenharmony_ci} 760a8e1175bSopenharmony_ci 761a8e1175bSopenharmony_ci#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 762a8e1175bSopenharmony_ci 763a8e1175bSopenharmony_ci#endif /* MBEDTLS_CCM_C */ 764