1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * NIST SP800-38D compliant GCM implementation 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 57901324dSJerome Forissier * SPDX-License-Identifier: Apache-2.0 6817466cbSJens Wiklander * 7817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8817466cbSJens Wiklander * not use this file except in compliance with the License. 9817466cbSJens Wiklander * You may obtain a copy of the License at 10817466cbSJens Wiklander * 11817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12817466cbSJens Wiklander * 13817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16817466cbSJens Wiklander * See the License for the specific language governing permissions and 17817466cbSJens Wiklander * limitations under the License. 18817466cbSJens Wiklander */ 19817466cbSJens Wiklander 20817466cbSJens Wiklander /* 21817466cbSJens Wiklander * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf 22817466cbSJens Wiklander * 23817466cbSJens Wiklander * See also: 24817466cbSJens Wiklander * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf 25817466cbSJens Wiklander * 26817466cbSJens Wiklander * We use the algorithm described as Shoup's method with 4-bit tables in 27817466cbSJens Wiklander * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. 28817466cbSJens Wiklander */ 29817466cbSJens Wiklander 307901324dSJerome Forissier #include "common.h" 31817466cbSJens Wiklander 32817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 33817466cbSJens Wiklander 34817466cbSJens Wiklander #include "mbedtls/gcm.h" 35*32b31808SJens Wiklander #include "mbedtls/platform.h" 363d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 3711fa71b9SJerome Forissier #include "mbedtls/error.h" 38817466cbSJens Wiklander 39817466cbSJens Wiklander #include <string.h> 40817466cbSJens Wiklander 41817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C) 42*32b31808SJens Wiklander #include "aesni.h" 43817466cbSJens Wiklander #endif 44817466cbSJens Wiklander 45*32b31808SJens Wiklander #if defined(MBEDTLS_AESCE_C) 46*32b31808SJens Wiklander #include "aesce.h" 47*32b31808SJens Wiklander #endif 48817466cbSJens Wiklander 493d3b0591SJens Wiklander #if !defined(MBEDTLS_GCM_ALT) 503d3b0591SJens Wiklander 51817466cbSJens Wiklander /* 52817466cbSJens Wiklander * Initialize a context 53817466cbSJens Wiklander */ 54817466cbSJens Wiklander void mbedtls_gcm_init(mbedtls_gcm_context *ctx) 55817466cbSJens Wiklander { 56817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_gcm_context)); 57817466cbSJens Wiklander } 58817466cbSJens Wiklander 59817466cbSJens Wiklander /* 60817466cbSJens Wiklander * Precompute small multiples of H, that is set 61817466cbSJens Wiklander * HH[i] || HL[i] = H times i, 62817466cbSJens Wiklander * where i is seen as a field element as in [MGV], ie high-order bits 63817466cbSJens Wiklander * correspond to low powers of P. The result is stored in the same way, that 64817466cbSJens Wiklander * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL 65817466cbSJens Wiklander * corresponds to P^127. 66817466cbSJens Wiklander */ 67817466cbSJens Wiklander static int gcm_gen_table(mbedtls_gcm_context *ctx) 68817466cbSJens Wiklander { 69817466cbSJens Wiklander int ret, i, j; 70817466cbSJens Wiklander uint64_t hi, lo; 71817466cbSJens Wiklander uint64_t vl, vh; 72817466cbSJens Wiklander unsigned char h[16]; 73817466cbSJens Wiklander size_t olen = 0; 74817466cbSJens Wiklander 75817466cbSJens Wiklander memset(h, 0, 16); 76*32b31808SJens Wiklander if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) { 77*32b31808SJens Wiklander return ret; 78*32b31808SJens Wiklander } 79817466cbSJens Wiklander 80817466cbSJens Wiklander /* pack h as two 64-bits ints, big-endian */ 81039e02dfSJerome Forissier hi = MBEDTLS_GET_UINT32_BE(h, 0); 82039e02dfSJerome Forissier lo = MBEDTLS_GET_UINT32_BE(h, 4); 83817466cbSJens Wiklander vh = (uint64_t) hi << 32 | lo; 84817466cbSJens Wiklander 85039e02dfSJerome Forissier hi = MBEDTLS_GET_UINT32_BE(h, 8); 86039e02dfSJerome Forissier lo = MBEDTLS_GET_UINT32_BE(h, 12); 87817466cbSJens Wiklander vl = (uint64_t) hi << 32 | lo; 88817466cbSJens Wiklander 89817466cbSJens Wiklander /* 8 = 1000 corresponds to 1 in GF(2^128) */ 90817466cbSJens Wiklander ctx->HL[8] = vl; 91817466cbSJens Wiklander ctx->HH[8] = vh; 92817466cbSJens Wiklander 93*32b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE) 94817466cbSJens Wiklander /* With CLMUL support, we need only h, not the rest of the table */ 95*32b31808SJens Wiklander if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { 96*32b31808SJens Wiklander return 0; 97*32b31808SJens Wiklander } 98*32b31808SJens Wiklander #endif 99*32b31808SJens Wiklander 100*32b31808SJens Wiklander #if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) 101*32b31808SJens Wiklander if (mbedtls_aesce_has_support()) { 102*32b31808SJens Wiklander return 0; 103*32b31808SJens Wiklander } 104817466cbSJens Wiklander #endif 105817466cbSJens Wiklander 106817466cbSJens Wiklander /* 0 corresponds to 0 in GF(2^128) */ 107817466cbSJens Wiklander ctx->HH[0] = 0; 108817466cbSJens Wiklander ctx->HL[0] = 0; 109817466cbSJens Wiklander 110*32b31808SJens Wiklander for (i = 4; i > 0; i >>= 1) { 111817466cbSJens Wiklander uint32_t T = (vl & 1) * 0xe1000000U; 112817466cbSJens Wiklander vl = (vh << 63) | (vl >> 1); 113817466cbSJens Wiklander vh = (vh >> 1) ^ ((uint64_t) T << 32); 114817466cbSJens Wiklander 115817466cbSJens Wiklander ctx->HL[i] = vl; 116817466cbSJens Wiklander ctx->HH[i] = vh; 117817466cbSJens Wiklander } 118817466cbSJens Wiklander 119*32b31808SJens Wiklander for (i = 2; i <= 8; i *= 2) { 120817466cbSJens Wiklander uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; 121817466cbSJens Wiklander vh = *HiH; 122817466cbSJens Wiklander vl = *HiL; 123*32b31808SJens Wiklander for (j = 1; j < i; j++) { 124817466cbSJens Wiklander HiH[j] = vh ^ ctx->HH[j]; 125817466cbSJens Wiklander HiL[j] = vl ^ ctx->HL[j]; 126817466cbSJens Wiklander } 127817466cbSJens Wiklander } 128817466cbSJens Wiklander 129*32b31808SJens Wiklander return 0; 130817466cbSJens Wiklander } 131817466cbSJens Wiklander 132817466cbSJens Wiklander int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, 133817466cbSJens Wiklander mbedtls_cipher_id_t cipher, 134817466cbSJens Wiklander const unsigned char *key, 135817466cbSJens Wiklander unsigned int keybits) 136817466cbSJens Wiklander { 13711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 138817466cbSJens Wiklander const mbedtls_cipher_info_t *cipher_info; 139817466cbSJens Wiklander 140*32b31808SJens Wiklander if (keybits != 128 && keybits != 192 && keybits != 256) { 141*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT; 142*32b31808SJens Wiklander } 1433d3b0591SJens Wiklander 14411fa71b9SJerome Forissier cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, 14511fa71b9SJerome Forissier MBEDTLS_MODE_ECB); 146*32b31808SJens Wiklander if (cipher_info == NULL) { 147*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT; 148*32b31808SJens Wiklander } 149817466cbSJens Wiklander 150*32b31808SJens Wiklander if (cipher_info->block_size != 16) { 151*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT; 152*32b31808SJens Wiklander } 153817466cbSJens Wiklander 154817466cbSJens Wiklander mbedtls_cipher_free(&ctx->cipher_ctx); 155817466cbSJens Wiklander 156*32b31808SJens Wiklander if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { 157*32b31808SJens Wiklander return ret; 158817466cbSJens Wiklander } 159817466cbSJens Wiklander 160*32b31808SJens Wiklander if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, 161*32b31808SJens Wiklander MBEDTLS_ENCRYPT)) != 0) { 162*32b31808SJens Wiklander return ret; 163*32b31808SJens Wiklander } 164817466cbSJens Wiklander 165*32b31808SJens Wiklander if ((ret = gcm_gen_table(ctx)) != 0) { 166*32b31808SJens Wiklander return ret; 167*32b31808SJens Wiklander } 168*32b31808SJens Wiklander 169*32b31808SJens Wiklander return 0; 170817466cbSJens Wiklander } 171817466cbSJens Wiklander 172817466cbSJens Wiklander /* 173817466cbSJens Wiklander * Shoup's method for multiplication use this table with 174817466cbSJens Wiklander * last4[x] = x times P^128 175817466cbSJens Wiklander * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] 176817466cbSJens Wiklander */ 177817466cbSJens Wiklander static const uint64_t last4[16] = 178817466cbSJens Wiklander { 179817466cbSJens Wiklander 0x0000, 0x1c20, 0x3840, 0x2460, 180817466cbSJens Wiklander 0x7080, 0x6ca0, 0x48c0, 0x54e0, 181817466cbSJens Wiklander 0xe100, 0xfd20, 0xd940, 0xc560, 182817466cbSJens Wiklander 0x9180, 0x8da0, 0xa9c0, 0xb5e0 183817466cbSJens Wiklander }; 184817466cbSJens Wiklander 185817466cbSJens Wiklander /* 186817466cbSJens Wiklander * Sets output to x times H using the precomputed tables. 187817466cbSJens Wiklander * x and output are seen as elements of GF(2^128) as in [MGV]. 188817466cbSJens Wiklander */ 189817466cbSJens Wiklander static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16], 190817466cbSJens Wiklander unsigned char output[16]) 191817466cbSJens Wiklander { 192817466cbSJens Wiklander int i = 0; 193817466cbSJens Wiklander unsigned char lo, hi, rem; 194817466cbSJens Wiklander uint64_t zh, zl; 195817466cbSJens Wiklander 196*32b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE) 197817466cbSJens Wiklander if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { 198817466cbSJens Wiklander unsigned char h[16]; 199817466cbSJens Wiklander 200*32b31808SJens Wiklander /* mbedtls_aesni_gcm_mult needs big-endian input */ 201039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0); 202039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4); 203039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8); 204039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12); 205817466cbSJens Wiklander 206817466cbSJens Wiklander mbedtls_aesni_gcm_mult(output, x, h); 207817466cbSJens Wiklander return; 208817466cbSJens Wiklander } 209*32b31808SJens Wiklander #endif /* MBEDTLS_AESNI_HAVE_CODE */ 210*32b31808SJens Wiklander 211*32b31808SJens Wiklander #if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) 212*32b31808SJens Wiklander if (mbedtls_aesce_has_support()) { 213*32b31808SJens Wiklander unsigned char h[16]; 214*32b31808SJens Wiklander 215*32b31808SJens Wiklander /* mbedtls_aesce_gcm_mult needs big-endian input */ 216*32b31808SJens Wiklander MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0); 217*32b31808SJens Wiklander MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4); 218*32b31808SJens Wiklander MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8); 219*32b31808SJens Wiklander MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12); 220*32b31808SJens Wiklander 221*32b31808SJens Wiklander mbedtls_aesce_gcm_mult(output, x, h); 222*32b31808SJens Wiklander return; 223*32b31808SJens Wiklander } 224*32b31808SJens Wiklander #endif 225817466cbSJens Wiklander 226817466cbSJens Wiklander lo = x[15] & 0xf; 227817466cbSJens Wiklander 228817466cbSJens Wiklander zh = ctx->HH[lo]; 229817466cbSJens Wiklander zl = ctx->HL[lo]; 230817466cbSJens Wiklander 231*32b31808SJens Wiklander for (i = 15; i >= 0; i--) { 232817466cbSJens Wiklander lo = x[i] & 0xf; 23311fa71b9SJerome Forissier hi = (x[i] >> 4) & 0xf; 234817466cbSJens Wiklander 235*32b31808SJens Wiklander if (i != 15) { 236817466cbSJens Wiklander rem = (unsigned char) zl & 0xf; 237817466cbSJens Wiklander zl = (zh << 60) | (zl >> 4); 238817466cbSJens Wiklander zh = (zh >> 4); 239817466cbSJens Wiklander zh ^= (uint64_t) last4[rem] << 48; 240817466cbSJens Wiklander zh ^= ctx->HH[lo]; 241817466cbSJens Wiklander zl ^= ctx->HL[lo]; 242817466cbSJens Wiklander 243817466cbSJens Wiklander } 244817466cbSJens Wiklander 245817466cbSJens Wiklander rem = (unsigned char) zl & 0xf; 246817466cbSJens Wiklander zl = (zh << 60) | (zl >> 4); 247817466cbSJens Wiklander zh = (zh >> 4); 248817466cbSJens Wiklander zh ^= (uint64_t) last4[rem] << 48; 249817466cbSJens Wiklander zh ^= ctx->HH[hi]; 250817466cbSJens Wiklander zl ^= ctx->HL[hi]; 251817466cbSJens Wiklander } 252817466cbSJens Wiklander 253039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0); 254039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(zh, output, 4); 255039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8); 256039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(zl, output, 12); 257817466cbSJens Wiklander } 258817466cbSJens Wiklander 259817466cbSJens Wiklander int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, 260817466cbSJens Wiklander int mode, 261*32b31808SJens Wiklander const unsigned char *iv, size_t iv_len) 262817466cbSJens Wiklander { 26311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 264817466cbSJens Wiklander unsigned char work_buf[16]; 265817466cbSJens Wiklander const unsigned char *p; 266817466cbSJens Wiklander size_t use_len, olen = 0; 267039e02dfSJerome Forissier uint64_t iv_bits; 268817466cbSJens Wiklander 269*32b31808SJens Wiklander /* IV is limited to 2^64 bits, so 2^61 bytes */ 270817466cbSJens Wiklander /* IV is not allowed to be zero length */ 271*32b31808SJens Wiklander if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) { 272*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT; 273817466cbSJens Wiklander } 274817466cbSJens Wiklander 275817466cbSJens Wiklander memset(ctx->y, 0x00, sizeof(ctx->y)); 276817466cbSJens Wiklander memset(ctx->buf, 0x00, sizeof(ctx->buf)); 277817466cbSJens Wiklander 278817466cbSJens Wiklander ctx->mode = mode; 279817466cbSJens Wiklander ctx->len = 0; 280817466cbSJens Wiklander ctx->add_len = 0; 281817466cbSJens Wiklander 282*32b31808SJens Wiklander if (iv_len == 12) { 283817466cbSJens Wiklander memcpy(ctx->y, iv, iv_len); 284817466cbSJens Wiklander ctx->y[15] = 1; 285*32b31808SJens Wiklander } else { 286817466cbSJens Wiklander memset(work_buf, 0x00, 16); 287039e02dfSJerome Forissier iv_bits = (uint64_t) iv_len * 8; 288039e02dfSJerome Forissier MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8); 289817466cbSJens Wiklander 290817466cbSJens Wiklander p = iv; 291*32b31808SJens Wiklander while (iv_len > 0) { 292817466cbSJens Wiklander use_len = (iv_len < 16) ? iv_len : 16; 293817466cbSJens Wiklander 294*32b31808SJens Wiklander mbedtls_xor(ctx->y, ctx->y, p, use_len); 295817466cbSJens Wiklander 296817466cbSJens Wiklander gcm_mult(ctx, ctx->y, ctx->y); 297817466cbSJens Wiklander 298817466cbSJens Wiklander iv_len -= use_len; 299817466cbSJens Wiklander p += use_len; 300817466cbSJens Wiklander } 301817466cbSJens Wiklander 302*32b31808SJens Wiklander mbedtls_xor(ctx->y, ctx->y, work_buf, 16); 303817466cbSJens Wiklander 304817466cbSJens Wiklander gcm_mult(ctx, ctx->y, ctx->y); 305817466cbSJens Wiklander } 306817466cbSJens Wiklander 30711fa71b9SJerome Forissier if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, 308*32b31808SJens Wiklander ctx->base_ectr, &olen)) != 0) { 309*32b31808SJens Wiklander return ret; 310817466cbSJens Wiklander } 311817466cbSJens Wiklander 312*32b31808SJens Wiklander return 0; 313*32b31808SJens Wiklander } 314*32b31808SJens Wiklander 315*32b31808SJens Wiklander /** 316*32b31808SJens Wiklander * mbedtls_gcm_context::buf contains the partial state of the computation of 317*32b31808SJens Wiklander * the authentication tag. 318*32b31808SJens Wiklander * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate 319*32b31808SJens Wiklander * different stages of the computation: 320*32b31808SJens Wiklander * * len == 0 && add_len == 0: initial state 321*32b31808SJens Wiklander * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have 322*32b31808SJens Wiklander * a partial block of AD that has been 323*32b31808SJens Wiklander * xored in but not yet multiplied in. 324*32b31808SJens Wiklander * * len == 0 && add_len % 16 == 0: the authentication tag is correct if 325*32b31808SJens Wiklander * the data ends now. 326*32b31808SJens Wiklander * * len % 16 != 0: the first `len % 16` bytes have 327*32b31808SJens Wiklander * a partial block of ciphertext that has 328*32b31808SJens Wiklander * been xored in but not yet multiplied in. 329*32b31808SJens Wiklander * * len > 0 && len % 16 == 0: the authentication tag is correct if 330*32b31808SJens Wiklander * the data ends now. 331*32b31808SJens Wiklander */ 332*32b31808SJens Wiklander int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx, 333*32b31808SJens Wiklander const unsigned char *add, size_t add_len) 334817466cbSJens Wiklander { 335*32b31808SJens Wiklander const unsigned char *p; 336*32b31808SJens Wiklander size_t use_len, offset; 337817466cbSJens Wiklander 338*32b31808SJens Wiklander /* IV is limited to 2^64 bits, so 2^61 bytes */ 339*32b31808SJens Wiklander if ((uint64_t) add_len >> 61 != 0) { 340*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT; 341*32b31808SJens Wiklander } 342817466cbSJens Wiklander 343*32b31808SJens Wiklander offset = ctx->add_len % 16; 344*32b31808SJens Wiklander p = add; 345*32b31808SJens Wiklander 346*32b31808SJens Wiklander if (offset != 0) { 347*32b31808SJens Wiklander use_len = 16 - offset; 348*32b31808SJens Wiklander if (use_len > add_len) { 349*32b31808SJens Wiklander use_len = add_len; 350*32b31808SJens Wiklander } 351*32b31808SJens Wiklander 352*32b31808SJens Wiklander mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len); 353*32b31808SJens Wiklander 354*32b31808SJens Wiklander if (offset + use_len == 16) { 355817466cbSJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf); 356*32b31808SJens Wiklander } 357817466cbSJens Wiklander 358*32b31808SJens Wiklander ctx->add_len += use_len; 359817466cbSJens Wiklander add_len -= use_len; 360817466cbSJens Wiklander p += use_len; 361817466cbSJens Wiklander } 362817466cbSJens Wiklander 363*32b31808SJens Wiklander ctx->add_len += add_len; 364817466cbSJens Wiklander 365*32b31808SJens Wiklander while (add_len >= 16) { 366*32b31808SJens Wiklander mbedtls_xor(ctx->buf, ctx->buf, p, 16); 367817466cbSJens Wiklander 368817466cbSJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf); 369817466cbSJens Wiklander 370*32b31808SJens Wiklander add_len -= 16; 371*32b31808SJens Wiklander p += 16; 372*32b31808SJens Wiklander } 373*32b31808SJens Wiklander 374*32b31808SJens Wiklander if (add_len > 0) { 375*32b31808SJens Wiklander mbedtls_xor(ctx->buf, ctx->buf, p, add_len); 376*32b31808SJens Wiklander } 377*32b31808SJens Wiklander 378*32b31808SJens Wiklander return 0; 379*32b31808SJens Wiklander } 380*32b31808SJens Wiklander 381*32b31808SJens Wiklander /* Increment the counter. */ 382*32b31808SJens Wiklander static void gcm_incr(unsigned char y[16]) 383*32b31808SJens Wiklander { 384*32b31808SJens Wiklander size_t i; 385*32b31808SJens Wiklander for (i = 16; i > 12; i--) { 386*32b31808SJens Wiklander if (++y[i - 1] != 0) { 387*32b31808SJens Wiklander break; 388*32b31808SJens Wiklander } 389*32b31808SJens Wiklander } 390*32b31808SJens Wiklander } 391*32b31808SJens Wiklander 392*32b31808SJens Wiklander /* Calculate and apply the encryption mask. Process use_len bytes of data, 393*32b31808SJens Wiklander * starting at position offset in the mask block. */ 394*32b31808SJens Wiklander static int gcm_mask(mbedtls_gcm_context *ctx, 395*32b31808SJens Wiklander unsigned char ectr[16], 396*32b31808SJens Wiklander size_t offset, size_t use_len, 397*32b31808SJens Wiklander const unsigned char *input, 398*32b31808SJens Wiklander unsigned char *output) 399*32b31808SJens Wiklander { 400*32b31808SJens Wiklander size_t olen = 0; 401*32b31808SJens Wiklander int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 402*32b31808SJens Wiklander 403*32b31808SJens Wiklander if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, 404*32b31808SJens Wiklander &olen)) != 0) { 405*32b31808SJens Wiklander mbedtls_platform_zeroize(ectr, 16); 406*32b31808SJens Wiklander return ret; 407*32b31808SJens Wiklander } 408*32b31808SJens Wiklander 409*32b31808SJens Wiklander if (ctx->mode == MBEDTLS_GCM_DECRYPT) { 410*32b31808SJens Wiklander mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len); 411*32b31808SJens Wiklander } 412*32b31808SJens Wiklander mbedtls_xor(output, ectr + offset, input, use_len); 413*32b31808SJens Wiklander if (ctx->mode == MBEDTLS_GCM_ENCRYPT) { 414*32b31808SJens Wiklander mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len); 415*32b31808SJens Wiklander } 416*32b31808SJens Wiklander 417*32b31808SJens Wiklander return 0; 418*32b31808SJens Wiklander } 419*32b31808SJens Wiklander 420*32b31808SJens Wiklander int mbedtls_gcm_update(mbedtls_gcm_context *ctx, 421*32b31808SJens Wiklander const unsigned char *input, size_t input_length, 422*32b31808SJens Wiklander unsigned char *output, size_t output_size, 423*32b31808SJens Wiklander size_t *output_length) 424*32b31808SJens Wiklander { 425*32b31808SJens Wiklander int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 426*32b31808SJens Wiklander const unsigned char *p = input; 427*32b31808SJens Wiklander unsigned char *out_p = output; 428*32b31808SJens Wiklander size_t offset; 429*32b31808SJens Wiklander unsigned char ectr[16] = { 0 }; 430*32b31808SJens Wiklander 431*32b31808SJens Wiklander if (output_size < input_length) { 432*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL; 433*32b31808SJens Wiklander } 434*32b31808SJens Wiklander *output_length = input_length; 435*32b31808SJens Wiklander 436*32b31808SJens Wiklander /* Exit early if input_length==0 so that we don't do any pointer arithmetic 437*32b31808SJens Wiklander * on a potentially null pointer. 438*32b31808SJens Wiklander * Returning early also means that the last partial block of AD remains 439*32b31808SJens Wiklander * untouched for mbedtls_gcm_finish */ 440*32b31808SJens Wiklander if (input_length == 0) { 441*32b31808SJens Wiklander return 0; 442*32b31808SJens Wiklander } 443*32b31808SJens Wiklander 444*32b31808SJens Wiklander if (output > input && (size_t) (output - input) < input_length) { 445*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT; 446*32b31808SJens Wiklander } 447*32b31808SJens Wiklander 448*32b31808SJens Wiklander /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes 449*32b31808SJens Wiklander * Also check for possible overflow */ 450*32b31808SJens Wiklander if (ctx->len + input_length < ctx->len || 451*32b31808SJens Wiklander (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) { 452*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT; 453*32b31808SJens Wiklander } 454*32b31808SJens Wiklander 455*32b31808SJens Wiklander if (ctx->len == 0 && ctx->add_len % 16 != 0) { 456*32b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf); 457*32b31808SJens Wiklander } 458*32b31808SJens Wiklander 459*32b31808SJens Wiklander offset = ctx->len % 16; 460*32b31808SJens Wiklander if (offset != 0) { 461*32b31808SJens Wiklander size_t use_len = 16 - offset; 462*32b31808SJens Wiklander if (use_len > input_length) { 463*32b31808SJens Wiklander use_len = input_length; 464*32b31808SJens Wiklander } 465*32b31808SJens Wiklander 466*32b31808SJens Wiklander if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) { 467*32b31808SJens Wiklander return ret; 468*32b31808SJens Wiklander } 469*32b31808SJens Wiklander 470*32b31808SJens Wiklander if (offset + use_len == 16) { 471*32b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf); 472*32b31808SJens Wiklander } 473*32b31808SJens Wiklander 474*32b31808SJens Wiklander ctx->len += use_len; 475*32b31808SJens Wiklander input_length -= use_len; 476817466cbSJens Wiklander p += use_len; 477817466cbSJens Wiklander out_p += use_len; 478817466cbSJens Wiklander } 479817466cbSJens Wiklander 480*32b31808SJens Wiklander ctx->len += input_length; 481*32b31808SJens Wiklander 482*32b31808SJens Wiklander while (input_length >= 16) { 483*32b31808SJens Wiklander gcm_incr(ctx->y); 484*32b31808SJens Wiklander if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) { 485*32b31808SJens Wiklander return ret; 486*32b31808SJens Wiklander } 487*32b31808SJens Wiklander 488*32b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf); 489*32b31808SJens Wiklander 490*32b31808SJens Wiklander input_length -= 16; 491*32b31808SJens Wiklander p += 16; 492*32b31808SJens Wiklander out_p += 16; 493*32b31808SJens Wiklander } 494*32b31808SJens Wiklander 495*32b31808SJens Wiklander if (input_length > 0) { 496*32b31808SJens Wiklander gcm_incr(ctx->y); 497*32b31808SJens Wiklander if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) { 498*32b31808SJens Wiklander return ret; 499*32b31808SJens Wiklander } 500*32b31808SJens Wiklander } 501*32b31808SJens Wiklander 502*32b31808SJens Wiklander mbedtls_platform_zeroize(ectr, sizeof(ectr)); 503*32b31808SJens Wiklander return 0; 504817466cbSJens Wiklander } 505817466cbSJens Wiklander 506817466cbSJens Wiklander int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, 507*32b31808SJens Wiklander unsigned char *output, size_t output_size, 508*32b31808SJens Wiklander size_t *output_length, 509*32b31808SJens Wiklander unsigned char *tag, size_t tag_len) 510817466cbSJens Wiklander { 511817466cbSJens Wiklander unsigned char work_buf[16]; 5123d3b0591SJens Wiklander uint64_t orig_len; 5133d3b0591SJens Wiklander uint64_t orig_add_len; 5143d3b0591SJens Wiklander 515*32b31808SJens Wiklander /* We never pass any output in finish(). The output parameter exists only 516*32b31808SJens Wiklander * for the sake of alternative implementations. */ 517*32b31808SJens Wiklander (void) output; 518*32b31808SJens Wiklander (void) output_size; 519*32b31808SJens Wiklander *output_length = 0; 5203d3b0591SJens Wiklander 5213d3b0591SJens Wiklander orig_len = ctx->len * 8; 5223d3b0591SJens Wiklander orig_add_len = ctx->add_len * 8; 523817466cbSJens Wiklander 524*32b31808SJens Wiklander if (ctx->len == 0 && ctx->add_len % 16 != 0) { 525*32b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf); 526*32b31808SJens Wiklander } 527*32b31808SJens Wiklander 528*32b31808SJens Wiklander if (tag_len > 16 || tag_len < 4) { 529*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT; 530*32b31808SJens Wiklander } 531*32b31808SJens Wiklander 532*32b31808SJens Wiklander if (ctx->len % 16 != 0) { 533*32b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf); 534*32b31808SJens Wiklander } 535817466cbSJens Wiklander 536817466cbSJens Wiklander memcpy(tag, ctx->base_ectr, tag_len); 537817466cbSJens Wiklander 538*32b31808SJens Wiklander if (orig_len || orig_add_len) { 539817466cbSJens Wiklander memset(work_buf, 0x00, 16); 540817466cbSJens Wiklander 541039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0); 542039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4); 543039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8); 544039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12); 545817466cbSJens Wiklander 546*32b31808SJens Wiklander mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16); 547817466cbSJens Wiklander 548817466cbSJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf); 549817466cbSJens Wiklander 550*32b31808SJens Wiklander mbedtls_xor(tag, tag, ctx->buf, tag_len); 551817466cbSJens Wiklander } 552817466cbSJens Wiklander 553*32b31808SJens Wiklander return 0; 554817466cbSJens Wiklander } 555817466cbSJens Wiklander 556817466cbSJens Wiklander int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, 557817466cbSJens Wiklander int mode, 558817466cbSJens Wiklander size_t length, 559817466cbSJens Wiklander const unsigned char *iv, 560817466cbSJens Wiklander size_t iv_len, 561817466cbSJens Wiklander const unsigned char *add, 562817466cbSJens Wiklander size_t add_len, 563817466cbSJens Wiklander const unsigned char *input, 564817466cbSJens Wiklander unsigned char *output, 565817466cbSJens Wiklander size_t tag_len, 566817466cbSJens Wiklander unsigned char *tag) 567817466cbSJens Wiklander { 56811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 569*32b31808SJens Wiklander size_t olen; 570817466cbSJens Wiklander 571*32b31808SJens Wiklander if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) { 572*32b31808SJens Wiklander return ret; 573*32b31808SJens Wiklander } 5743d3b0591SJens Wiklander 575*32b31808SJens Wiklander if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) { 576*32b31808SJens Wiklander return ret; 577*32b31808SJens Wiklander } 578817466cbSJens Wiklander 579*32b31808SJens Wiklander if ((ret = mbedtls_gcm_update(ctx, input, length, 580*32b31808SJens Wiklander output, length, &olen)) != 0) { 581*32b31808SJens Wiklander return ret; 582*32b31808SJens Wiklander } 583817466cbSJens Wiklander 584*32b31808SJens Wiklander if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) { 585*32b31808SJens Wiklander return ret; 586*32b31808SJens Wiklander } 587817466cbSJens Wiklander 588*32b31808SJens Wiklander return 0; 589817466cbSJens Wiklander } 590817466cbSJens Wiklander 591817466cbSJens Wiklander int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, 592817466cbSJens Wiklander size_t length, 593817466cbSJens Wiklander const unsigned char *iv, 594817466cbSJens Wiklander size_t iv_len, 595817466cbSJens Wiklander const unsigned char *add, 596817466cbSJens Wiklander size_t add_len, 597817466cbSJens Wiklander const unsigned char *tag, 598817466cbSJens Wiklander size_t tag_len, 599817466cbSJens Wiklander const unsigned char *input, 600817466cbSJens Wiklander unsigned char *output) 601817466cbSJens Wiklander { 60211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 603817466cbSJens Wiklander unsigned char check_tag[16]; 604817466cbSJens Wiklander size_t i; 605817466cbSJens Wiklander int diff; 606817466cbSJens Wiklander 607817466cbSJens Wiklander if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length, 608817466cbSJens Wiklander iv, iv_len, add, add_len, 609*32b31808SJens Wiklander input, output, tag_len, check_tag)) != 0) { 610*32b31808SJens Wiklander return ret; 611817466cbSJens Wiklander } 612817466cbSJens Wiklander 613817466cbSJens Wiklander /* Check tag in "constant-time" */ 614*32b31808SJens Wiklander for (diff = 0, i = 0; i < tag_len; i++) { 615817466cbSJens Wiklander diff |= tag[i] ^ check_tag[i]; 616817466cbSJens Wiklander } 617817466cbSJens Wiklander 618*32b31808SJens Wiklander if (diff != 0) { 619*32b31808SJens Wiklander mbedtls_platform_zeroize(output, length); 620*32b31808SJens Wiklander return MBEDTLS_ERR_GCM_AUTH_FAILED; 621*32b31808SJens Wiklander } 622*32b31808SJens Wiklander 623*32b31808SJens Wiklander return 0; 624817466cbSJens Wiklander } 625817466cbSJens Wiklander 626817466cbSJens Wiklander void mbedtls_gcm_free(mbedtls_gcm_context *ctx) 627817466cbSJens Wiklander { 628*32b31808SJens Wiklander if (ctx == NULL) { 6293d3b0591SJens Wiklander return; 630*32b31808SJens Wiklander } 631817466cbSJens Wiklander mbedtls_cipher_free(&ctx->cipher_ctx); 6323d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context)); 633817466cbSJens Wiklander } 634817466cbSJens Wiklander 6353d3b0591SJens Wiklander #endif /* !MBEDTLS_GCM_ALT */ 6363d3b0591SJens Wiklander 637817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 638817466cbSJens Wiklander /* 639817466cbSJens Wiklander * AES-GCM test vectors from: 640817466cbSJens Wiklander * 641817466cbSJens Wiklander * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip 642817466cbSJens Wiklander */ 643817466cbSJens Wiklander #define MAX_TESTS 6 644817466cbSJens Wiklander 64511fa71b9SJerome Forissier static const int key_index_test_data[MAX_TESTS] = 646817466cbSJens Wiklander { 0, 0, 1, 1, 1, 1 }; 647817466cbSJens Wiklander 64811fa71b9SJerome Forissier static const unsigned char key_test_data[MAX_TESTS][32] = 649817466cbSJens Wiklander { 650817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 651817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 652817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 653817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 654817466cbSJens Wiklander { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 655817466cbSJens Wiklander 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 656817466cbSJens Wiklander 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 657817466cbSJens Wiklander 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, 658817466cbSJens Wiklander }; 659817466cbSJens Wiklander 66011fa71b9SJerome Forissier static const size_t iv_len_test_data[MAX_TESTS] = 661817466cbSJens Wiklander { 12, 12, 12, 12, 8, 60 }; 662817466cbSJens Wiklander 66311fa71b9SJerome Forissier static const int iv_index_test_data[MAX_TESTS] = 664817466cbSJens Wiklander { 0, 0, 1, 1, 1, 2 }; 665817466cbSJens Wiklander 66611fa71b9SJerome Forissier static const unsigned char iv_test_data[MAX_TESTS][64] = 667817466cbSJens Wiklander { 668817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 669817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00 }, 670817466cbSJens Wiklander { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 671817466cbSJens Wiklander 0xde, 0xca, 0xf8, 0x88 }, 672817466cbSJens Wiklander { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 673817466cbSJens Wiklander 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, 674817466cbSJens Wiklander 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 675817466cbSJens Wiklander 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, 676817466cbSJens Wiklander 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 677817466cbSJens Wiklander 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 678817466cbSJens Wiklander 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, 679817466cbSJens Wiklander 0xa6, 0x37, 0xb3, 0x9b }, 680817466cbSJens Wiklander }; 681817466cbSJens Wiklander 68211fa71b9SJerome Forissier static const size_t add_len_test_data[MAX_TESTS] = 683817466cbSJens Wiklander { 0, 0, 0, 20, 20, 20 }; 684817466cbSJens Wiklander 68511fa71b9SJerome Forissier static const int add_index_test_data[MAX_TESTS] = 686817466cbSJens Wiklander { 0, 0, 0, 1, 1, 1 }; 687817466cbSJens Wiklander 68811fa71b9SJerome Forissier static const unsigned char additional_test_data[MAX_TESTS][64] = 689817466cbSJens Wiklander { 690817466cbSJens Wiklander { 0x00 }, 691817466cbSJens Wiklander { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 692817466cbSJens Wiklander 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 693817466cbSJens Wiklander 0xab, 0xad, 0xda, 0xd2 }, 694817466cbSJens Wiklander }; 695817466cbSJens Wiklander 69611fa71b9SJerome Forissier static const size_t pt_len_test_data[MAX_TESTS] = 697817466cbSJens Wiklander { 0, 16, 64, 60, 60, 60 }; 698817466cbSJens Wiklander 69911fa71b9SJerome Forissier static const int pt_index_test_data[MAX_TESTS] = 700817466cbSJens Wiklander { 0, 0, 1, 1, 1, 1 }; 701817466cbSJens Wiklander 70211fa71b9SJerome Forissier static const unsigned char pt_test_data[MAX_TESTS][64] = 703817466cbSJens Wiklander { 704817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 705817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 706817466cbSJens Wiklander { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 707817466cbSJens Wiklander 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 708817466cbSJens Wiklander 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 709817466cbSJens Wiklander 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 710817466cbSJens Wiklander 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 711817466cbSJens Wiklander 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 712817466cbSJens Wiklander 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 713817466cbSJens Wiklander 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, 714817466cbSJens Wiklander }; 715817466cbSJens Wiklander 71611fa71b9SJerome Forissier static const unsigned char ct_test_data[MAX_TESTS * 3][64] = 717817466cbSJens Wiklander { 718817466cbSJens Wiklander { 0x00 }, 719817466cbSJens Wiklander { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 720817466cbSJens Wiklander 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, 721817466cbSJens Wiklander { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 722817466cbSJens Wiklander 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 723817466cbSJens Wiklander 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 724817466cbSJens Wiklander 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 725817466cbSJens Wiklander 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 726817466cbSJens Wiklander 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 727817466cbSJens Wiklander 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 728817466cbSJens Wiklander 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, 729817466cbSJens Wiklander { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 730817466cbSJens Wiklander 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 731817466cbSJens Wiklander 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 732817466cbSJens Wiklander 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 733817466cbSJens Wiklander 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 734817466cbSJens Wiklander 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 735817466cbSJens Wiklander 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 736817466cbSJens Wiklander 0x3d, 0x58, 0xe0, 0x91 }, 737817466cbSJens Wiklander { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 738817466cbSJens Wiklander 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, 739817466cbSJens Wiklander 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 740817466cbSJens Wiklander 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, 741817466cbSJens Wiklander 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 742817466cbSJens Wiklander 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 743817466cbSJens Wiklander 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, 744817466cbSJens Wiklander 0xc2, 0x3f, 0x45, 0x98 }, 745817466cbSJens Wiklander { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 746817466cbSJens Wiklander 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, 747817466cbSJens Wiklander 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 748817466cbSJens Wiklander 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, 749817466cbSJens Wiklander 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 750817466cbSJens Wiklander 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 751817466cbSJens Wiklander 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 752817466cbSJens Wiklander 0x4c, 0x34, 0xae, 0xe5 }, 753817466cbSJens Wiklander { 0x00 }, 754817466cbSJens Wiklander { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 755817466cbSJens Wiklander 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, 756817466cbSJens Wiklander { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 757817466cbSJens Wiklander 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 758817466cbSJens Wiklander 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 759817466cbSJens Wiklander 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 760817466cbSJens Wiklander 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 761817466cbSJens Wiklander 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 762817466cbSJens Wiklander 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 763817466cbSJens Wiklander 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, 764817466cbSJens Wiklander { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 765817466cbSJens Wiklander 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 766817466cbSJens Wiklander 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 767817466cbSJens Wiklander 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 768817466cbSJens Wiklander 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 769817466cbSJens Wiklander 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 770817466cbSJens Wiklander 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 771817466cbSJens Wiklander 0xcc, 0xda, 0x27, 0x10 }, 772817466cbSJens Wiklander { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 773817466cbSJens Wiklander 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, 774817466cbSJens Wiklander 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, 775817466cbSJens Wiklander 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, 776817466cbSJens Wiklander 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, 777817466cbSJens Wiklander 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, 778817466cbSJens Wiklander 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, 779817466cbSJens Wiklander 0xa0, 0xf0, 0x62, 0xf7 }, 780817466cbSJens Wiklander { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 781817466cbSJens Wiklander 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, 782817466cbSJens Wiklander 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, 783817466cbSJens Wiklander 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, 784817466cbSJens Wiklander 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, 785817466cbSJens Wiklander 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, 786817466cbSJens Wiklander 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, 787817466cbSJens Wiklander 0xe9, 0xb7, 0x37, 0x3b }, 788817466cbSJens Wiklander { 0x00 }, 789817466cbSJens Wiklander { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 790817466cbSJens Wiklander 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, 791817466cbSJens Wiklander { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 792817466cbSJens Wiklander 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 793817466cbSJens Wiklander 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 794817466cbSJens Wiklander 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 795817466cbSJens Wiklander 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 796817466cbSJens Wiklander 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 797817466cbSJens Wiklander 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 798817466cbSJens Wiklander 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, 799817466cbSJens Wiklander { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 800817466cbSJens Wiklander 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 801817466cbSJens Wiklander 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 802817466cbSJens Wiklander 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 803817466cbSJens Wiklander 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 804817466cbSJens Wiklander 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 805817466cbSJens Wiklander 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 806817466cbSJens Wiklander 0xbc, 0xc9, 0xf6, 0x62 }, 807817466cbSJens Wiklander { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 808817466cbSJens Wiklander 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, 809817466cbSJens Wiklander 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 810817466cbSJens Wiklander 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, 811817466cbSJens Wiklander 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 812817466cbSJens Wiklander 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 813817466cbSJens Wiklander 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, 814817466cbSJens Wiklander 0xf4, 0x7c, 0x9b, 0x1f }, 815817466cbSJens Wiklander { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 816817466cbSJens Wiklander 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, 817817466cbSJens Wiklander 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 818817466cbSJens Wiklander 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, 819817466cbSJens Wiklander 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 820817466cbSJens Wiklander 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 821817466cbSJens Wiklander 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, 822817466cbSJens Wiklander 0x44, 0xae, 0x7e, 0x3f }, 823817466cbSJens Wiklander }; 824817466cbSJens Wiklander 82511fa71b9SJerome Forissier static const unsigned char tag_test_data[MAX_TESTS * 3][16] = 826817466cbSJens Wiklander { 827817466cbSJens Wiklander { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 828817466cbSJens Wiklander 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, 829817466cbSJens Wiklander { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 830817466cbSJens Wiklander 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, 831817466cbSJens Wiklander { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 832817466cbSJens Wiklander 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, 833817466cbSJens Wiklander { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 834817466cbSJens Wiklander 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, 835817466cbSJens Wiklander { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 836817466cbSJens Wiklander 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, 837817466cbSJens Wiklander { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 838817466cbSJens Wiklander 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, 839817466cbSJens Wiklander { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 840817466cbSJens Wiklander 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, 841817466cbSJens Wiklander { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 842817466cbSJens Wiklander 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, 843817466cbSJens Wiklander { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, 844817466cbSJens Wiklander 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, 845817466cbSJens Wiklander { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, 846817466cbSJens Wiklander 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, 847817466cbSJens Wiklander { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, 848817466cbSJens Wiklander 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, 849817466cbSJens Wiklander { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 850817466cbSJens Wiklander 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, 851817466cbSJens Wiklander { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 852817466cbSJens Wiklander 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, 853817466cbSJens Wiklander { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 854817466cbSJens Wiklander 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, 855817466cbSJens Wiklander { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 856817466cbSJens Wiklander 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, 857817466cbSJens Wiklander { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 858817466cbSJens Wiklander 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, 859817466cbSJens Wiklander { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 860817466cbSJens Wiklander 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, 861817466cbSJens Wiklander { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 862817466cbSJens Wiklander 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, 863817466cbSJens Wiklander }; 864817466cbSJens Wiklander 865817466cbSJens Wiklander int mbedtls_gcm_self_test(int verbose) 866817466cbSJens Wiklander { 867817466cbSJens Wiklander mbedtls_gcm_context ctx; 868817466cbSJens Wiklander unsigned char buf[64]; 869817466cbSJens Wiklander unsigned char tag_buf[16]; 870817466cbSJens Wiklander int i, j, ret; 871817466cbSJens Wiklander mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; 872*32b31808SJens Wiklander size_t olen; 873817466cbSJens Wiklander 874*32b31808SJens Wiklander if (verbose != 0) { 875*32b31808SJens Wiklander #if defined(MBEDTLS_GCM_ALT) 876*32b31808SJens Wiklander mbedtls_printf(" GCM note: alternative implementation.\n"); 877*32b31808SJens Wiklander #else /* MBEDTLS_GCM_ALT */ 878*32b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE) 879*32b31808SJens Wiklander if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { 880*32b31808SJens Wiklander mbedtls_printf(" GCM note: using AESNI.\n"); 881*32b31808SJens Wiklander } else 882*32b31808SJens Wiklander #endif 883*32b31808SJens Wiklander mbedtls_printf(" GCM note: built-in implementation.\n"); 884*32b31808SJens Wiklander #endif /* MBEDTLS_GCM_ALT */ 885*32b31808SJens Wiklander } 886*32b31808SJens Wiklander 887*32b31808SJens Wiklander for (j = 0; j < 3; j++) { 888817466cbSJens Wiklander int key_len = 128 + 64 * j; 889817466cbSJens Wiklander 890*32b31808SJens Wiklander for (i = 0; i < MAX_TESTS; i++) { 8913d3b0591SJens Wiklander mbedtls_gcm_init(&ctx); 8923d3b0591SJens Wiklander 893*32b31808SJens Wiklander if (verbose != 0) { 894817466cbSJens Wiklander mbedtls_printf(" AES-GCM-%3d #%d (%s): ", 895817466cbSJens Wiklander key_len, i, "enc"); 896*32b31808SJens Wiklander } 897817466cbSJens Wiklander 89811fa71b9SJerome Forissier ret = mbedtls_gcm_setkey(&ctx, cipher, 89911fa71b9SJerome Forissier key_test_data[key_index_test_data[i]], 9003d3b0591SJens Wiklander key_len); 9013d3b0591SJens Wiklander /* 9023d3b0591SJens Wiklander * AES-192 is an optional feature that may be unavailable when 9033d3b0591SJens Wiklander * there is an alternative underlying implementation i.e. when 9043d3b0591SJens Wiklander * MBEDTLS_AES_ALT is defined. 9053d3b0591SJens Wiklander */ 906*32b31808SJens Wiklander if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) { 9073d3b0591SJens Wiklander mbedtls_printf("skipped\n"); 9083d3b0591SJens Wiklander break; 909*32b31808SJens Wiklander } else if (ret != 0) { 9103d3b0591SJens Wiklander goto exit; 9113d3b0591SJens Wiklander } 912817466cbSJens Wiklander 913817466cbSJens Wiklander ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, 91411fa71b9SJerome Forissier pt_len_test_data[i], 91511fa71b9SJerome Forissier iv_test_data[iv_index_test_data[i]], 91611fa71b9SJerome Forissier iv_len_test_data[i], 91711fa71b9SJerome Forissier additional_test_data[add_index_test_data[i]], 91811fa71b9SJerome Forissier add_len_test_data[i], 91911fa71b9SJerome Forissier pt_test_data[pt_index_test_data[i]], 92011fa71b9SJerome Forissier buf, 16, tag_buf); 9217901324dSJerome Forissier #if defined(MBEDTLS_GCM_ALT) 9227901324dSJerome Forissier /* Allow alternative implementations to only support 12-byte nonces. */ 9237901324dSJerome Forissier if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && 924*32b31808SJens Wiklander iv_len_test_data[i] != 12) { 9257901324dSJerome Forissier mbedtls_printf("skipped\n"); 9267901324dSJerome Forissier break; 9277901324dSJerome Forissier } 9287901324dSJerome Forissier #endif /* defined(MBEDTLS_GCM_ALT) */ 929*32b31808SJens Wiklander if (ret != 0) { 9303d3b0591SJens Wiklander goto exit; 931*32b31808SJens Wiklander } 932817466cbSJens Wiklander 93311fa71b9SJerome Forissier if (memcmp(buf, ct_test_data[j * 6 + i], 93411fa71b9SJerome Forissier pt_len_test_data[i]) != 0 || 935*32b31808SJens Wiklander memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { 9363d3b0591SJens Wiklander ret = 1; 9373d3b0591SJens Wiklander goto exit; 938817466cbSJens Wiklander } 939817466cbSJens Wiklander 940817466cbSJens Wiklander mbedtls_gcm_free(&ctx); 941817466cbSJens Wiklander 942*32b31808SJens Wiklander if (verbose != 0) { 943817466cbSJens Wiklander mbedtls_printf("passed\n"); 944*32b31808SJens Wiklander } 945817466cbSJens Wiklander 9463d3b0591SJens Wiklander mbedtls_gcm_init(&ctx); 9473d3b0591SJens Wiklander 948*32b31808SJens Wiklander if (verbose != 0) { 949817466cbSJens Wiklander mbedtls_printf(" AES-GCM-%3d #%d (%s): ", 950817466cbSJens Wiklander key_len, i, "dec"); 951*32b31808SJens Wiklander } 952817466cbSJens Wiklander 95311fa71b9SJerome Forissier ret = mbedtls_gcm_setkey(&ctx, cipher, 95411fa71b9SJerome Forissier key_test_data[key_index_test_data[i]], 9553d3b0591SJens Wiklander key_len); 956*32b31808SJens Wiklander if (ret != 0) { 9573d3b0591SJens Wiklander goto exit; 958*32b31808SJens Wiklander } 959817466cbSJens Wiklander 960817466cbSJens Wiklander ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT, 96111fa71b9SJerome Forissier pt_len_test_data[i], 96211fa71b9SJerome Forissier iv_test_data[iv_index_test_data[i]], 96311fa71b9SJerome Forissier iv_len_test_data[i], 96411fa71b9SJerome Forissier additional_test_data[add_index_test_data[i]], 96511fa71b9SJerome Forissier add_len_test_data[i], 96611fa71b9SJerome Forissier ct_test_data[j * 6 + i], buf, 16, tag_buf); 967817466cbSJens Wiklander 968*32b31808SJens Wiklander if (ret != 0) { 9693d3b0591SJens Wiklander goto exit; 970*32b31808SJens Wiklander } 9713d3b0591SJens Wiklander 97211fa71b9SJerome Forissier if (memcmp(buf, pt_test_data[pt_index_test_data[i]], 97311fa71b9SJerome Forissier pt_len_test_data[i]) != 0 || 974*32b31808SJens Wiklander memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { 9753d3b0591SJens Wiklander ret = 1; 9763d3b0591SJens Wiklander goto exit; 977817466cbSJens Wiklander } 978817466cbSJens Wiklander 979817466cbSJens Wiklander mbedtls_gcm_free(&ctx); 980817466cbSJens Wiklander 981*32b31808SJens Wiklander if (verbose != 0) { 982817466cbSJens Wiklander mbedtls_printf("passed\n"); 983*32b31808SJens Wiklander } 984817466cbSJens Wiklander 9853d3b0591SJens Wiklander mbedtls_gcm_init(&ctx); 9863d3b0591SJens Wiklander 987*32b31808SJens Wiklander if (verbose != 0) { 988817466cbSJens Wiklander mbedtls_printf(" AES-GCM-%3d #%d split (%s): ", 989817466cbSJens Wiklander key_len, i, "enc"); 990*32b31808SJens Wiklander } 991817466cbSJens Wiklander 99211fa71b9SJerome Forissier ret = mbedtls_gcm_setkey(&ctx, cipher, 99311fa71b9SJerome Forissier key_test_data[key_index_test_data[i]], 9943d3b0591SJens Wiklander key_len); 995*32b31808SJens Wiklander if (ret != 0) { 9963d3b0591SJens Wiklander goto exit; 997*32b31808SJens Wiklander } 998817466cbSJens Wiklander 999817466cbSJens Wiklander ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT, 100011fa71b9SJerome Forissier iv_test_data[iv_index_test_data[i]], 1001*32b31808SJens Wiklander iv_len_test_data[i]); 1002*32b31808SJens Wiklander if (ret != 0) { 1003*32b31808SJens Wiklander goto exit; 1004*32b31808SJens Wiklander } 1005*32b31808SJens Wiklander 1006*32b31808SJens Wiklander ret = mbedtls_gcm_update_ad(&ctx, 100711fa71b9SJerome Forissier additional_test_data[add_index_test_data[i]], 100811fa71b9SJerome Forissier add_len_test_data[i]); 1009*32b31808SJens Wiklander if (ret != 0) { 10103d3b0591SJens Wiklander goto exit; 1011*32b31808SJens Wiklander } 1012817466cbSJens Wiklander 1013*32b31808SJens Wiklander if (pt_len_test_data[i] > 32) { 101411fa71b9SJerome Forissier size_t rest_len = pt_len_test_data[i] - 32; 1015*32b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx, 101611fa71b9SJerome Forissier pt_test_data[pt_index_test_data[i]], 1017*32b31808SJens Wiklander 32, 1018*32b31808SJens Wiklander buf, sizeof(buf), &olen); 1019*32b31808SJens Wiklander if (ret != 0) { 10203d3b0591SJens Wiklander goto exit; 1021*32b31808SJens Wiklander } 1022*32b31808SJens Wiklander if (olen != 32) { 1023*32b31808SJens Wiklander goto exit; 1024*32b31808SJens Wiklander } 1025817466cbSJens Wiklander 1026*32b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx, 102711fa71b9SJerome Forissier pt_test_data[pt_index_test_data[i]] + 32, 1028*32b31808SJens Wiklander rest_len, 1029*32b31808SJens Wiklander buf + 32, sizeof(buf) - 32, &olen); 1030*32b31808SJens Wiklander if (ret != 0) { 10313d3b0591SJens Wiklander goto exit; 1032817466cbSJens Wiklander } 1033*32b31808SJens Wiklander if (olen != rest_len) { 10343d3b0591SJens Wiklander goto exit; 1035817466cbSJens Wiklander } 1036*32b31808SJens Wiklander } else { 1037*32b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx, 1038*32b31808SJens Wiklander pt_test_data[pt_index_test_data[i]], 1039*32b31808SJens Wiklander pt_len_test_data[i], 1040*32b31808SJens Wiklander buf, sizeof(buf), &olen); 1041*32b31808SJens Wiklander if (ret != 0) { 1042*32b31808SJens Wiklander goto exit; 1043*32b31808SJens Wiklander } 1044*32b31808SJens Wiklander if (olen != pt_len_test_data[i]) { 1045*32b31808SJens Wiklander goto exit; 1046*32b31808SJens Wiklander } 1047*32b31808SJens Wiklander } 1048817466cbSJens Wiklander 1049*32b31808SJens Wiklander ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16); 1050*32b31808SJens Wiklander if (ret != 0) { 10513d3b0591SJens Wiklander goto exit; 1052*32b31808SJens Wiklander } 10533d3b0591SJens Wiklander 105411fa71b9SJerome Forissier if (memcmp(buf, ct_test_data[j * 6 + i], 105511fa71b9SJerome Forissier pt_len_test_data[i]) != 0 || 1056*32b31808SJens Wiklander memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { 10573d3b0591SJens Wiklander ret = 1; 10583d3b0591SJens Wiklander goto exit; 1059817466cbSJens Wiklander } 1060817466cbSJens Wiklander 1061817466cbSJens Wiklander mbedtls_gcm_free(&ctx); 1062817466cbSJens Wiklander 1063*32b31808SJens Wiklander if (verbose != 0) { 1064817466cbSJens Wiklander mbedtls_printf("passed\n"); 1065*32b31808SJens Wiklander } 1066817466cbSJens Wiklander 10673d3b0591SJens Wiklander mbedtls_gcm_init(&ctx); 10683d3b0591SJens Wiklander 1069*32b31808SJens Wiklander if (verbose != 0) { 1070817466cbSJens Wiklander mbedtls_printf(" AES-GCM-%3d #%d split (%s): ", 1071817466cbSJens Wiklander key_len, i, "dec"); 1072*32b31808SJens Wiklander } 1073817466cbSJens Wiklander 107411fa71b9SJerome Forissier ret = mbedtls_gcm_setkey(&ctx, cipher, 107511fa71b9SJerome Forissier key_test_data[key_index_test_data[i]], 10763d3b0591SJens Wiklander key_len); 1077*32b31808SJens Wiklander if (ret != 0) { 10783d3b0591SJens Wiklander goto exit; 1079*32b31808SJens Wiklander } 1080817466cbSJens Wiklander 1081817466cbSJens Wiklander ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, 108211fa71b9SJerome Forissier iv_test_data[iv_index_test_data[i]], 1083*32b31808SJens Wiklander iv_len_test_data[i]); 1084*32b31808SJens Wiklander if (ret != 0) { 1085*32b31808SJens Wiklander goto exit; 1086*32b31808SJens Wiklander } 1087*32b31808SJens Wiklander ret = mbedtls_gcm_update_ad(&ctx, 108811fa71b9SJerome Forissier additional_test_data[add_index_test_data[i]], 108911fa71b9SJerome Forissier add_len_test_data[i]); 1090*32b31808SJens Wiklander if (ret != 0) { 10913d3b0591SJens Wiklander goto exit; 1092*32b31808SJens Wiklander } 1093817466cbSJens Wiklander 1094*32b31808SJens Wiklander if (pt_len_test_data[i] > 32) { 109511fa71b9SJerome Forissier size_t rest_len = pt_len_test_data[i] - 32; 1096*32b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx, 1097*32b31808SJens Wiklander ct_test_data[j * 6 + i], 32, 1098*32b31808SJens Wiklander buf, sizeof(buf), &olen); 1099*32b31808SJens Wiklander if (ret != 0) { 11003d3b0591SJens Wiklander goto exit; 1101*32b31808SJens Wiklander } 1102*32b31808SJens Wiklander if (olen != 32) { 1103*32b31808SJens Wiklander goto exit; 1104*32b31808SJens Wiklander } 1105817466cbSJens Wiklander 1106*32b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx, 110711fa71b9SJerome Forissier ct_test_data[j * 6 + i] + 32, 1108*32b31808SJens Wiklander rest_len, 1109*32b31808SJens Wiklander buf + 32, sizeof(buf) - 32, &olen); 1110*32b31808SJens Wiklander if (ret != 0) { 11113d3b0591SJens Wiklander goto exit; 1112817466cbSJens Wiklander } 1113*32b31808SJens Wiklander if (olen != rest_len) { 11143d3b0591SJens Wiklander goto exit; 1115817466cbSJens Wiklander } 1116*32b31808SJens Wiklander } else { 1117*32b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx, 1118*32b31808SJens Wiklander ct_test_data[j * 6 + i], 1119*32b31808SJens Wiklander pt_len_test_data[i], 1120*32b31808SJens Wiklander buf, sizeof(buf), &olen); 1121*32b31808SJens Wiklander if (ret != 0) { 1122*32b31808SJens Wiklander goto exit; 1123*32b31808SJens Wiklander } 1124*32b31808SJens Wiklander if (olen != pt_len_test_data[i]) { 1125*32b31808SJens Wiklander goto exit; 1126*32b31808SJens Wiklander } 1127*32b31808SJens Wiklander } 1128817466cbSJens Wiklander 1129*32b31808SJens Wiklander ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16); 1130*32b31808SJens Wiklander if (ret != 0) { 11313d3b0591SJens Wiklander goto exit; 1132*32b31808SJens Wiklander } 11333d3b0591SJens Wiklander 113411fa71b9SJerome Forissier if (memcmp(buf, pt_test_data[pt_index_test_data[i]], 113511fa71b9SJerome Forissier pt_len_test_data[i]) != 0 || 1136*32b31808SJens Wiklander memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { 11373d3b0591SJens Wiklander ret = 1; 11383d3b0591SJens Wiklander goto exit; 1139817466cbSJens Wiklander } 1140817466cbSJens Wiklander 1141817466cbSJens Wiklander mbedtls_gcm_free(&ctx); 1142817466cbSJens Wiklander 1143*32b31808SJens Wiklander if (verbose != 0) { 1144817466cbSJens Wiklander mbedtls_printf("passed\n"); 1145817466cbSJens Wiklander } 1146817466cbSJens Wiklander } 1147*32b31808SJens Wiklander } 1148817466cbSJens Wiklander 1149*32b31808SJens Wiklander if (verbose != 0) { 1150817466cbSJens Wiklander mbedtls_printf("\n"); 1151*32b31808SJens Wiklander } 1152817466cbSJens Wiklander 11533d3b0591SJens Wiklander ret = 0; 11543d3b0591SJens Wiklander 11553d3b0591SJens Wiklander exit: 1156*32b31808SJens Wiklander if (ret != 0) { 1157*32b31808SJens Wiklander if (verbose != 0) { 11583d3b0591SJens Wiklander mbedtls_printf("failed\n"); 1159*32b31808SJens Wiklander } 11603d3b0591SJens Wiklander mbedtls_gcm_free(&ctx); 11613d3b0591SJens Wiklander } 11623d3b0591SJens Wiklander 1163*32b31808SJens Wiklander return ret; 1164817466cbSJens Wiklander } 1165817466cbSJens Wiklander 1166817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 1167817466cbSJens Wiklander 1168817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1169