The branch, master has been updated via 71cb574 libcli/smb: try to negotiate SMB2_ENCRYPTION_AES128_GCM via 778ff0c libcli/smb: support SMB2_ENCRYPTION_AES128_GCM in smb2_signing_[de|en]crypt_pdu() via 03bf8fe lib/crypto: add aes_gcm_128 support. via 6fb2a98 libcli/smb: prepare smb2_signing_[de|en]crypt_pdu() to support multiple ciphers via eef76b9 s3:smb2_server: pass xconn->smb2.server.cipher to smb2_signing_[de|en]ncrypt_pdu() via 1ed30a6 s3:smb2_server: check xconn->smb2.server.cipher instead of xconn->smb2.server.capabilities via b460459 s3:smb2_negprot: remember xconn->smb2.server.cipher via 2ed2f00 libcli/smb: pass the negotiated cipher to smb2_signing_[de|en]ncrypt_pdu() via ed38abb libcli/smb: pass 'uint16_t cipher_id' to smb2_signing_[de|en]crypt_pdu() via 1ab23ac libcli/smb: use conn->smb2.server.cipher != 0 instead of conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION from d81d77a lib/util: Protect time_basic.h against multiple inclusion
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 71cb5749f4d7a542a1dccb250f91c58fd2bbf54c Author: Stefan Metzmacher <me...@samba.org> Date: Tue Oct 7 15:59:48 2014 +0200 libcli/smb: try to negotiate SMB2_ENCRYPTION_AES128_GCM Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Thu Oct 16 21:53:32 CEST 2014 on sn-devel-104 commit 778ff0c65c5a9260e8a8b3ff152411b4751992a7 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Oct 13 09:53:12 2014 +0200 libcli/smb: support SMB2_ENCRYPTION_AES128_GCM in smb2_signing_[de|en]crypt_pdu() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 03bf8fe4fc78b9f0c7093835a776728089387884 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Oct 7 14:48:26 2014 +0200 lib/crypto: add aes_gcm_128 support. Pair-Programmed-With: Michael Adam <ob...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> Signed-off-by: Michael Adam <ob...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 6fb2a982d7088ec9560756c49147783255add79a Author: Stefan Metzmacher <me...@samba.org> Date: Tue Oct 7 09:56:00 2014 +0200 libcli/smb: prepare smb2_signing_[de|en]crypt_pdu() to support multiple ciphers Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit eef76b9cb3695c69487176c3ec84acab368fa725 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Oct 7 09:54:35 2014 +0200 s3:smb2_server: pass xconn->smb2.server.cipher to smb2_signing_[de|en]ncrypt_pdu() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 1ed30a6ba7beab8cd3a4a1cfce3724cdc61dbcab Author: Stefan Metzmacher <me...@samba.org> Date: Mon Oct 13 11:07:01 2014 +0200 s3:smb2_server: check xconn->smb2.server.cipher instead of xconn->smb2.server.capabilities SMB 3.10 and later won't have SMB2_CAP_ENCRYPTION anymore. xconn->smb2.server.cipher == 0 is the indication that we don't support encryption on the connection. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit b4604590b0f4c485e6c283070c36678b2bf9f052 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Oct 13 11:07:01 2014 +0200 s3:smb2_negprot: remember xconn->smb2.server.cipher For now we always use SMB2_ENCRYPTION_AES128_CCM or 0. 0 is the indication that we don't support encryption on the connection. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 2ed2f00831e6f9ba42912da58cb854e393c6938b Author: Stefan Metzmacher <me...@samba.org> Date: Tue Oct 7 09:54:35 2014 +0200 libcli/smb: pass the negotiated cipher to smb2_signing_[de|en]ncrypt_pdu() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit ed38abb0a9cb5bf442731923097293dbae6bf191 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Oct 7 09:51:58 2014 +0200 libcli/smb: pass 'uint16_t cipher_id' to smb2_signing_[de|en]crypt_pdu() enum protocol_types protocol was unused before and cipher_id is unused as well for now. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 1ab23ac1e7c1f9a6f5c341c3b97b6035a17a762c Author: Stefan Metzmacher <me...@samba.org> Date: Mon Oct 13 10:39:45 2014 +0200 libcli/smb: use conn->smb2.server.cipher != 0 instead of conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION SMB 3.10 servers don't report SMB2_CAP_ENCRYPTION anymore. So using conn->smb2.server.cipher != 0 is a more consistent way to decide if encryption is supported on the connection. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: lib/crypto/aes_gcm_128.c | 221 +++++++++++++++++++++++++ lib/crypto/aes_gcm_128.h | 52 ++++++ lib/crypto/aes_gcm_128_test.c | 366 +++++++++++++++++++++++++++++++++++++++++ lib/crypto/crypto.h | 1 + lib/crypto/wscript_build | 4 +- libcli/smb/smb2_signing.c | 118 ++++++++++---- libcli/smb/smb2_signing.h | 4 +- libcli/smb/smbXcli_base.c | 47 ++---- source3/smbd/globals.h | 1 + source3/smbd/smb2_negprot.c | 4 + source3/smbd/smb2_server.c | 12 +- source3/smbd/smb2_sesssetup.c | 2 +- source3/smbd/smb2_tcon.c | 2 +- source4/torture/local/local.c | 2 + 14 files changed, 763 insertions(+), 73 deletions(-) create mode 100644 lib/crypto/aes_gcm_128.c create mode 100644 lib/crypto/aes_gcm_128.h create mode 100644 lib/crypto/aes_gcm_128_test.c Changeset truncated at 500 lines: diff --git a/lib/crypto/aes_gcm_128.c b/lib/crypto/aes_gcm_128.c new file mode 100644 index 0000000..f59d659 --- /dev/null +++ b/lib/crypto/aes_gcm_128.c @@ -0,0 +1,221 @@ +/* + AES-GCM-128 + + Copyright (C) Stefan Metzmacher 2014 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "../lib/crypto/crypto.h" +#include "lib/util/byteorder.h" + +static inline void aes_gcm_128_inc32(uint8_t inout[AES_BLOCK_SIZE]) +{ + uint32_t v; + + v = RIVAL(inout, AES_BLOCK_SIZE - 4); + v += 1; + RSIVAL(inout, AES_BLOCK_SIZE - 4, v); +} + +static inline void aes_gcm_128_xor(const uint8_t in1[AES_BLOCK_SIZE], + const uint8_t in2[AES_BLOCK_SIZE], + uint8_t out[AES_BLOCK_SIZE]) +{ + uint8_t i; + + for (i = 0; i < AES_BLOCK_SIZE; i++) { + out[i] = in1[i] ^ in2[i]; + } +} + +static inline void aes_gcm_128_rightshift(uint8_t x[AES_BLOCK_SIZE]) +{ + int8_t i; + + for (i = AES_BLOCK_SIZE - 1; i >=0; i--) { + x[i] >>= 1; + if (i > 0) { + x[i] |= (x[i-1] & 1) << 7; + } + } +} + +static inline void aes_gcm_128_mul(const uint8_t x[AES_BLOCK_SIZE], + const uint8_t y[AES_BLOCK_SIZE], + uint8_t z[AES_BLOCK_SIZE]) +{ + uint8_t i; + uint8_t v[AES_BLOCK_SIZE]; + /* 11100001 || 0^120 */ + static const uint8_t r[AES_BLOCK_SIZE] = { + 0xE1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + + memset(z, 0, AES_BLOCK_SIZE); + memcpy(v, y, AES_BLOCK_SIZE); + + for (i = 0; i < AES_BLOCK_SIZE; i++) { + uint8_t mask; + for (mask = 0x80; mask != 0 ; mask >>= 1) { + uint8_t v_lsb = v[AES_BLOCK_SIZE-1] & 1; + if (x[i] & mask) { + aes_gcm_128_xor(z, v, z); + } + + aes_gcm_128_rightshift(v); + if (v_lsb != 0) { + aes_gcm_128_xor(v, r, v); + } + } + } +} + +static inline void aes_gcm_128_ghash_block(struct aes_gcm_128_context *ctx, + const uint8_t in[AES_BLOCK_SIZE]) +{ + aes_gcm_128_xor(ctx->Y, in, ctx->y.block); + aes_gcm_128_mul(ctx->y.block, ctx->H, ctx->Y); +} + +void aes_gcm_128_init(struct aes_gcm_128_context *ctx, + const uint8_t K[AES_BLOCK_SIZE], + const uint8_t IV[AES_GCM_128_IV_SIZE]) +{ + ZERO_STRUCTP(ctx); + + AES_set_encrypt_key(K, 128, &ctx->aes_key); + + /* + * Step 1: generate H (ctx->Y is the zero block here) + */ + AES_encrypt(ctx->Y, ctx->H, &ctx->aes_key); + + /* + * Step 2: generate J0 + */ + memcpy(ctx->J0, IV, AES_GCM_128_IV_SIZE); + aes_gcm_128_inc32(ctx->J0); + + /* + * We need to prepare CB with J0. + */ + memcpy(ctx->CB, ctx->J0, AES_BLOCK_SIZE); + ctx->c.ofs = AES_BLOCK_SIZE; +} + +static inline void aes_gcm_128_update_tmp(struct aes_gcm_128_context *ctx, + struct aes_gcm_128_tmp *tmp, + const uint8_t *v, size_t v_len) +{ + tmp->total += v_len; + + if (tmp->ofs > 0) { + size_t copy = MIN(AES_BLOCK_SIZE - tmp->ofs, v_len); + + memcpy(tmp->block + tmp->ofs, v, copy); + tmp->ofs += copy; + v += copy; + v_len -= copy; + } + + if (tmp->ofs == AES_BLOCK_SIZE) { + aes_gcm_128_ghash_block(ctx, tmp->block); + tmp->ofs = 0; + } + + while (v_len >= AES_BLOCK_SIZE) { + aes_gcm_128_ghash_block(ctx, v); + v += AES_BLOCK_SIZE; + v_len -= AES_BLOCK_SIZE; + } + + if (v_len == 0) { + return; + } + + ZERO_STRUCT(tmp->block); + memcpy(tmp->block, v, v_len); + tmp->ofs = v_len; +} + +void aes_gcm_128_updateA(struct aes_gcm_128_context *ctx, + const uint8_t *a, size_t a_len) +{ + aes_gcm_128_update_tmp(ctx, &ctx->A, a, a_len); +} + +void aes_gcm_128_updateC(struct aes_gcm_128_context *ctx, + const uint8_t *c, size_t c_len) +{ + if (ctx->A.ofs > 0) { + aes_gcm_128_ghash_block(ctx, ctx->A.block); + ctx->A.ofs = 0; + } + + aes_gcm_128_update_tmp(ctx, &ctx->C, c, c_len); +} + +static inline void aes_gcm_128_crypt_tmp(struct aes_gcm_128_context *ctx, + struct aes_gcm_128_tmp *tmp, + uint8_t *m, size_t m_len) +{ + tmp->total += m_len; + + while (m_len > 0) { + if (tmp->ofs == AES_BLOCK_SIZE) { + aes_gcm_128_inc32(ctx->CB); + AES_encrypt(ctx->CB, tmp->block, &ctx->aes_key); + tmp->ofs = 0; + } + + m[0] ^= tmp->block[tmp->ofs]; + m += 1; + m_len -= 1; + tmp->ofs += 1; + } +} + +void aes_gcm_128_crypt(struct aes_gcm_128_context *ctx, + uint8_t *m, size_t m_len) +{ + aes_gcm_128_crypt_tmp(ctx, &ctx->c, m, m_len); +} + +void aes_gcm_128_digest(struct aes_gcm_128_context *ctx, + uint8_t T[AES_BLOCK_SIZE]) +{ + if (ctx->A.ofs > 0) { + aes_gcm_128_ghash_block(ctx, ctx->A.block); + ctx->A.ofs = 0; + } + + if (ctx->C.ofs > 0) { + aes_gcm_128_ghash_block(ctx, ctx->C.block); + ctx->C.ofs = 0; + } + + RSBVAL(ctx->AC, 0, ctx->A.total * 8); + RSBVAL(ctx->AC, 8, ctx->C.total * 8); + aes_gcm_128_ghash_block(ctx, ctx->AC); + + AES_encrypt(ctx->J0, ctx->c.block, &ctx->aes_key); + aes_gcm_128_xor(ctx->c.block, ctx->Y, T); + + ZERO_STRUCTP(ctx); +} diff --git a/lib/crypto/aes_gcm_128.h b/lib/crypto/aes_gcm_128.h new file mode 100644 index 0000000..278b6db --- /dev/null +++ b/lib/crypto/aes_gcm_128.h @@ -0,0 +1,52 @@ +/* + AES-GCM-128 + + Copyright (C) Stefan Metzmacher 2014 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef LIB_CRYPTO_AES_GCM_128_H +#define LIB_CRYPTO_AES_GCM_128_H + +#define AES_GCM_128_IV_SIZE (12) + +struct aes_gcm_128_context { + AES_KEY aes_key; + uint8_t H[AES_BLOCK_SIZE]; + uint8_t J0[AES_BLOCK_SIZE]; + uint8_t CB[AES_BLOCK_SIZE]; + uint8_t Y[AES_BLOCK_SIZE]; + uint8_t AC[AES_BLOCK_SIZE]; + + struct aes_gcm_128_tmp { + uint8_t block[AES_BLOCK_SIZE]; + size_t ofs; + size_t total; + } A, C, c, y; +}; + +void aes_gcm_128_init(struct aes_gcm_128_context *ctx, + const uint8_t K[AES_BLOCK_SIZE], + const uint8_t IV[AES_GCM_128_IV_SIZE]); +void aes_gcm_128_updateA(struct aes_gcm_128_context *ctx, + const uint8_t *a, size_t a_len); +void aes_gcm_128_updateC(struct aes_gcm_128_context *ctx, + const uint8_t *c, size_t c_len); +void aes_gcm_128_crypt(struct aes_gcm_128_context *ctx, + uint8_t *m, size_t m_len); +void aes_gcm_128_digest(struct aes_gcm_128_context *ctx, + uint8_t T[AES_BLOCK_SIZE]); + +#endif /* LIB_CRYPTO_AES_GCM_128_H */ diff --git a/lib/crypto/aes_gcm_128_test.c b/lib/crypto/aes_gcm_128_test.c new file mode 100644 index 0000000..703ad86 --- /dev/null +++ b/lib/crypto/aes_gcm_128_test.c @@ -0,0 +1,366 @@ +/* + AES-GCM-128 tests + + Copyright (C) Stefan Metzmacher 2014 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "replace.h" +#include "../lib/util/samba_util.h" +#include "../lib/crypto/crypto.h" + +struct torture_context; +bool torture_local_crypto_aes_gcm_128(struct torture_context *torture); + +/* + This uses the test values from ... +*/ +bool torture_local_crypto_aes_gcm_128(struct torture_context *torture) +{ + bool ret = true; + uint32_t i; + struct { + DATA_BLOB K; + DATA_BLOB IV; + DATA_BLOB A; + DATA_BLOB P; + DATA_BLOB C; + DATA_BLOB T; + } testarray[5]; + + TALLOC_CTX *tctx = talloc_new(torture); + if (!tctx) { return false; }; + + ZERO_STRUCT(testarray); + + testarray[0].K = strhex_to_data_blob(tctx, + "00000000000000000000000000000000"); + testarray[0].IV = strhex_to_data_blob(tctx, + "000000000000000000000000"); + testarray[0].A = data_blob_null; + testarray[0].P = data_blob_null; + testarray[0].C = data_blob_null; + testarray[0].T = strhex_to_data_blob(tctx, + "58e2fccefa7e3061367f1d57a4e7455a"); + + testarray[1].K = strhex_to_data_blob(tctx, + "00000000000000000000000000000000"); + testarray[1].IV = strhex_to_data_blob(tctx, + "000000000000000000000000"); + testarray[1].A = data_blob_null; + testarray[1].P = strhex_to_data_blob(tctx, + "00000000000000000000000000000000"); + testarray[1].C = strhex_to_data_blob(tctx, + "0388dace60b6a392f328c2b971b2fe78"); + testarray[1].T = strhex_to_data_blob(tctx, + "ab6e47d42cec13bdf53a67b21257bddf"); + + testarray[2].K = strhex_to_data_blob(tctx, + "feffe9928665731c6d6a8f9467308308"); + testarray[2].IV = strhex_to_data_blob(tctx, + "cafebabefacedbaddecaf888"); + testarray[2].A = data_blob_null; + testarray[2].P = strhex_to_data_blob(tctx, + "d9313225f88406e5a55909c5aff5269a" + "86a7a9531534f7da2e4c303d8a318a72" + "1c3c0c95956809532fcf0e2449a6b525" + "b16aedf5aa0de657ba637b391aafd255"); + testarray[2].C = strhex_to_data_blob(tctx, + "42831ec2217774244b7221b784d0d49c" + "e3aa212f2c02a4e035c17e2329aca12e" + "21d514b25466931c7d8f6a5aac84aa05" + "1ba30b396a0aac973d58e091473f5985"); + testarray[2].T = strhex_to_data_blob(tctx, + "4d5c2af327cd64a62cf35abd2ba6fab4"); + + testarray[3].K = strhex_to_data_blob(tctx, + "feffe9928665731c6d6a8f9467308308"); + testarray[3].IV = strhex_to_data_blob(tctx, + "cafebabefacedbaddecaf888"); + testarray[3].A = strhex_to_data_blob(tctx, + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2"); + testarray[3].P = strhex_to_data_blob(tctx, + "d9313225f88406e5a55909c5aff5269a" + "86a7a9531534f7da2e4c303d8a318a72" + "1c3c0c95956809532fcf0e2449a6b525" + "b16aedf5aa0de657ba637b39"); + testarray[3].C = strhex_to_data_blob(tctx, + "42831ec2217774244b7221b784d0d49c" + "e3aa212f2c02a4e035c17e2329aca12e" + "21d514b25466931c7d8f6a5aac84aa05" + "1ba30b396a0aac973d58e091"); + testarray[3].T = strhex_to_data_blob(tctx, + "5bc94fbc3221a5db94fae95ae7121a47"); + + for (i=1; testarray[i].T.length != 0; i++) { + struct aes_gcm_128_context ctx; + uint8_t T[AES_BLOCK_SIZE]; + DATA_BLOB C; + int e; + + C = data_blob_dup_talloc(tctx, testarray[i].P); + + aes_gcm_128_init(&ctx, testarray[i].K.data, testarray[i].IV.data); + aes_gcm_128_updateA(&ctx, + testarray[i].A.data, + testarray[i].A.length); + aes_gcm_128_crypt(&ctx, C.data, C.length); + aes_gcm_128_updateC(&ctx, C.data, C.length); + aes_gcm_128_digest(&ctx, T); + + e = memcmp(testarray[i].T.data, T, sizeof(T)); + if (e != 0) { + printf("%s: aes_gcm_128 test[%u]: failed\n", __location__, i); + printf("K\n"); + dump_data(0, testarray[i].K.data, testarray[i].K.length); + printf("IV\n"); + dump_data(0, testarray[i].IV.data, testarray[i].IV.length); + printf("A\n"); + dump_data(0, testarray[i].A.data, testarray[i].A.length); + printf("P\n"); + dump_data(0, testarray[i].P.data, testarray[i].P.length); + printf("C1\n"); + dump_data(0, testarray[i].C.data, testarray[i].C.length); + printf("C2\n"); + dump_data(0, C.data, C.length); + printf("T1\n"); + dump_data(0, testarray[i].T.data, testarray[i].T.length); + printf("T2\n"); + dump_data(0, T, sizeof(T)); + ret = false; + goto fail; + } + + e = memcmp(testarray[i].C.data, C.data, C.length); + if (e != 0) { + printf("%s: aes_gcm_128 test[%u]: failed\n", __location__, i); + printf("K\n"); + dump_data(0, testarray[i].K.data, testarray[i].K.length); + printf("IV\n"); + dump_data(0, testarray[i].IV.data, testarray[i].IV.length); + printf("A\n"); + dump_data(0, testarray[i].A.data, testarray[i].A.length); + printf("P\n"); + dump_data(0, testarray[i].P.data, testarray[i].P.length); + printf("C1\n"); + dump_data(0, testarray[i].C.data, testarray[i].C.length); + printf("C2\n"); + dump_data(0, C.data, C.length); + printf("T1\n"); + dump_data(0, testarray[i].T.data, testarray[i].T.length); + printf("T2\n"); + dump_data(0, T, sizeof(T)); + ret = false; + goto fail; + } + } + + for (i=1; testarray[i].T.length != 0; i++) { + struct aes_gcm_128_context ctx; + uint8_t T[AES_BLOCK_SIZE]; + DATA_BLOB C; + int e; + size_t j; + + C = data_blob_dup_talloc(tctx, testarray[i].P); + + aes_gcm_128_init(&ctx, testarray[i].K.data, testarray[i].IV.data); + for (j=0; j < testarray[i].A.length; j++) { + aes_gcm_128_updateA(&ctx, &testarray[i].A.data[j], 1); + } + for (j=0; j < C.length; j++) { + aes_gcm_128_crypt(&ctx, &C.data[j], 1); + aes_gcm_128_updateC(&ctx, &C.data[j], 1); + } + aes_gcm_128_digest(&ctx, T); + + e = memcmp(testarray[i].T.data, T, sizeof(T)); + if (e != 0) { + printf("%s: aes_gcm_128 test[%u]: failed\n", __location__, i); + printf("K\n"); + dump_data(0, testarray[i].K.data, testarray[i].K.length); + printf("IV\n"); + dump_data(0, testarray[i].IV.data, testarray[i].IV.length); + printf("A\n"); + dump_data(0, testarray[i].A.data, testarray[i].A.length); + printf("P\n"); + dump_data(0, testarray[i].P.data, testarray[i].P.length); + printf("C1\n"); + dump_data(0, testarray[i].C.data, testarray[i].C.length); + printf("C2\n"); + dump_data(0, C.data, C.length); + printf("T1\n"); + dump_data(0, testarray[i].T.data, testarray[i].T.length); + printf("T2\n"); + dump_data(0, T, sizeof(T)); + ret = false; + goto fail; -- Samba Shared Repository