diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-05-22 14:10:59 +0300 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-05-22 17:42:20 +0200 |
commit | eed4042fa028b3f73bad6a768f5b0a82f642e545 (patch) | |
tree | 0a3323950d742e618cefb8644d6af7d82b1b9558 | |
parent | f2986f03d1ae59f973bae56ce4333e5457003de5 (diff) | |
download | libgcrypt-eed4042fa028b3f73bad6a768f5b0a82f642e545.tar.gz |
Convert bulk CTR and CBC selftest functions in Camellia to generic selftest helper functions
* cipher/Makefile.am (libcipher_la_SOURCES): Add cipher-selftest files.
* cipher/camellia-glue.c (selftest_ctr_128, selftest_cbc_128): Change
to use the new selftest helper functions.
* cipher/cipher-selftest.c: New.
* cipher/cipher-selftest.h: New.
--
Convert selftest functions into generic helper functions for code sharing.
[v2]: use syslog for more detailed selftest error messages
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
-rw-r--r-- | cipher/Makefile.am | 1 | ||||
-rw-r--r-- | cipher/camellia-glue.c | 168 | ||||
-rw-r--r-- | cipher/cipher-selftest.c | 291 | ||||
-rw-r--r-- | cipher/cipher-selftest.h | 54 |
4 files changed, 357 insertions, 157 deletions
diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 00e44291..0808bd20 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -40,6 +40,7 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES) libcipher_la_SOURCES = \ cipher.c cipher-internal.h \ cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \ +cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h \ md.c \ kdf.c kdf-internal.h \ diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index e9e2bf2e..4c724a9b 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -63,6 +63,7 @@ #include "cipher.h" #include "camellia.h" #include "bufhelp.h" +#include "cipher-selftest.h" /* Helper macro to force alignment to 16 bytes. */ #ifdef HAVE_GCC_ATTRIBUTE_ALIGNED @@ -313,93 +314,12 @@ static const char* selftest_ctr_128 (void) { const int nblocks = 16+1; - CAMELLIA_context ctx ATTR_ALIGNED_16; - unsigned char plaintext[nblocks*16] ATTR_ALIGNED_16; - unsigned char ciphertext[nblocks*16] ATTR_ALIGNED_16; - unsigned char plaintext2[nblocks*16] ATTR_ALIGNED_16; - unsigned char iv[16] ATTR_ALIGNED_16; - unsigned char iv2[16] ATTR_ALIGNED_16; - int i, j, diff; - - static const unsigned char key[16] ATTR_ALIGNED_16 = { - 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, - 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21 - }; - static char error_str[128]; - - camellia_setkey (&ctx, key, sizeof (key)); - - /* Test single block code path */ - memset(iv, 0xff, sizeof(iv)); - for (i = 0; i < 16; i++) - plaintext[i] = i; - - /* CTR manually. */ - camellia_encrypt (&ctx, ciphertext, iv); - for (i = 0; i < 16; i++) - ciphertext[i] ^= plaintext[i]; - for (i = 16; i > 0; i--) - { - iv[i-1]++; - if (iv[i-1]) - break; - } - - memset(iv2, 0xff, sizeof(iv2)); - _gcry_camellia_ctr_enc (&ctx, iv2, plaintext2, ciphertext, 1); - - if (memcmp(plaintext2, plaintext, 16)) - return "CAMELLIA-128-CTR test failed (plaintext mismatch)"; - - if (memcmp(iv2, iv, 16)) - return "CAMELLIA-128-CTR test failed (IV mismatch)"; - - /* Test parallelized code paths */ - for (diff = 0; diff < nblocks; diff++) { - memset(iv, 0xff, sizeof(iv)); - iv[15] -= diff; - - for (i = 0; i < sizeof(plaintext); i++) - plaintext[i] = i; - - /* Create CTR ciphertext manually. */ - for (i = 0; i < sizeof(plaintext); i+=16) - { - camellia_encrypt (&ctx, &ciphertext[i], iv); - for (j = 0; j < 16; j++) - ciphertext[i+j] ^= plaintext[i+j]; - for (j = 16; j > 0; j--) - { - iv[j-1]++; - if (iv[j-1]) - break; - } - } - - /* Decrypt using bulk CTR and compare result. */ - memset(iv2, 0xff, sizeof(iv2)); - iv2[15] -= diff; - - _gcry_camellia_ctr_enc (&ctx, iv2, plaintext2, ciphertext, - sizeof(ciphertext) / CAMELLIA_BLOCK_SIZE); - - if (memcmp(plaintext2, plaintext, sizeof(plaintext))) - { - snprintf(error_str, sizeof(error_str), - "CAMELLIA-128-CTR test failed (plaintext mismatch, diff: %d)", - diff); - return error_str; - } - if (memcmp(iv2, iv, sizeof(iv))) - { - snprintf(error_str, sizeof(error_str), - "CAMELLIA-128-CTR test failed (IV mismatch, diff: %d)", - diff); - return error_str; - } - } + const int blocksize = CAMELLIA_BLOCK_SIZE; + const int context_size = sizeof(CAMELLIA_context); - return NULL; + return _gcry_selftest_helper_ctr_128("CAMELLIA", &camellia_setkey, + &camellia_encrypt, &_gcry_camellia_ctr_enc, nblocks, blocksize, + context_size); } /* Run the self-tests for CAMELLIA-CBC-128, tests bulk CBC decryption. @@ -408,78 +328,12 @@ static const char* selftest_cbc_128 (void) { const int nblocks = 16+2; - CAMELLIA_context ctx ATTR_ALIGNED_16; - unsigned char plaintext[nblocks*16] ATTR_ALIGNED_16; - unsigned char ciphertext[nblocks*16] ATTR_ALIGNED_16; - unsigned char plaintext2[nblocks*16] ATTR_ALIGNED_16; - unsigned char iv[16] ATTR_ALIGNED_16; - unsigned char iv2[16] ATTR_ALIGNED_16; - int i, j; - - static const unsigned char key[16] ATTR_ALIGNED_16 = { - 0x66,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, - 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x22 - }; - static char error_str[128]; - - camellia_setkey (&ctx, key, sizeof (key)); - - /* Test single block code path */ - memset(iv, 0x4e, sizeof(iv)); - memset(iv2, 0x4e, sizeof(iv2)); - for (i = 0; i < 16; i++) - plaintext[i] = i; - - /* CBC manually. */ - for (i = 0; i < 16; i++) - ciphertext[i] = iv[i] ^ plaintext[i]; - camellia_encrypt (&ctx, ciphertext, ciphertext); - memcpy(iv, ciphertext, sizeof(iv)); - - /* CBC decrypt. */ - _gcry_camellia_cbc_dec (&ctx, iv2, plaintext2, ciphertext, 1); - - if (memcmp(plaintext2, plaintext, 16)) - return "CAMELLIA-128-CBC test failed (plaintext mismatch)"; + const int blocksize = CAMELLIA_BLOCK_SIZE; + const int context_size = sizeof(CAMELLIA_context); - if (memcmp(iv2, iv, 16)) - return "CAMELLIA-128-CBC test failed (IV mismatch)"; - - /* Test parallelized code paths */ - memset(iv, 0x5f, sizeof(iv)); - memset(iv2, 0x5f, sizeof(iv2)); - - for (i = 0; i < sizeof(plaintext); i++) - plaintext[i] = i; - - /* Create CBC ciphertext manually. */ - for (i = 0; i < sizeof(plaintext); i+=16) - { - for (j = 0; j < 16; j++) - ciphertext[i+j] = iv[j] ^ plaintext[i+j]; - camellia_encrypt (&ctx, &ciphertext[i], &ciphertext[i]); - memcpy(iv, &ciphertext[i], sizeof(iv)); - } - - /* Decrypt using bulk CBC and compare result. */ - _gcry_camellia_cbc_dec (&ctx, iv2, plaintext2, ciphertext, - sizeof(ciphertext) / CAMELLIA_BLOCK_SIZE); - - if (memcmp(plaintext2, plaintext, sizeof(plaintext))) - { - snprintf(error_str, sizeof(error_str), - "CAMELLIA-128-CBC test failed (plaintext mismatch, " - "parallel path)"); - return error_str; - } - if (memcmp(iv2, iv, sizeof(iv))) - { - snprintf(error_str, sizeof(error_str), - "CAMELLIA-128-CBC test failed (IV mismatch, parallel path)"); - return error_str; - } - - return NULL; + return _gcry_selftest_helper_cbc_128("CAMELLIA", &camellia_setkey, + &camellia_encrypt, &_gcry_camellia_cbc_dec, nblocks, blocksize, + context_size); } static const char * diff --git a/cipher/cipher-selftest.c b/cipher/cipher-selftest.c new file mode 100644 index 00000000..50c77520 --- /dev/null +++ b/cipher/cipher-selftest.c @@ -0,0 +1,291 @@ +/* cipher-selftest.c - Helper functions for bulk encryption selftests. + * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#ifdef HAVE_SYSLOG +# include <syslog.h> +#endif /*HAVE_SYSLOG*/ + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" +#include "bufhelp.h" +#include "cipher-selftest.h" + +#ifdef HAVE_STDINT_H +# include <stdint.h> /* uintptr_t */ +#elif defined(HAVE_INTTYPES_H) +# include <inttypes.h> +#else +/* In this case, uintptr_t is provided by config.h. */ +#endif + +/* Helper macro to force alignment to 16 bytes. */ +#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED +# define ATTR_ALIGNED_16 __attribute__ ((aligned (16))) +#else +# define ATTR_ALIGNED_16 +#endif + + +/* Run the self-tests for <block cipher>-CBC-128, tests bulk CBC + decryption. Returns NULL on success. */ +const char * +_gcry_selftest_helper_cbc_128 (const char *cipher, gcry_cipher_setkey_t setkey, + gcry_cipher_encrypt_t encrypt_one, + gcry_cipher_bulk_cbc_dec_t bulk_cbc_dec, + const int nblocks, const int blocksize, + const int context_size) +{ + int i, offs; + unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem; + unsigned int ctx_aligned_size, memsize; + + static const unsigned char key[16] ATTR_ALIGNED_16 = { + 0x66,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, + 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x22 + }; + + /* Allocate buffers, align elements to 16 bytes. */ + ctx_aligned_size = context_size + 15; + ctx_aligned_size -= ctx_aligned_size & 0xf; + + memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 3) + 16; + + mem = gcry_calloc (1, memsize); + if (!mem) + return "failed to allocate memory"; + + offs = (16 - ((uintptr_t)mem & 15)) & 15; + ctx = (void*)(mem + offs); + iv = ctx + ctx_aligned_size; + iv2 = iv + blocksize; + plaintext = iv2 + blocksize; + plaintext2 = plaintext + nblocks * blocksize; + ciphertext = plaintext2 + nblocks * blocksize; + + /* Initialize ctx */ + setkey (ctx, key, sizeof(key)); + + /* Test single block code path */ + memset (iv, 0x4e, blocksize); + memset (iv2, 0x4e, blocksize); + for (i = 0; i < blocksize; i++) + plaintext[i] = i; + + /* CBC manually. */ + buf_xor (ciphertext, iv, plaintext, blocksize); + encrypt_one (ctx, ciphertext, ciphertext); + memcpy (iv, ciphertext, blocksize); + + /* CBC decrypt. */ + bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, 1); + if (memcmp (plaintext2, plaintext, 16)) + { + gcry_free (mem); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s-128-CBC test failed (plaintext mismatch)", cipher); +#endif + return "selftest for 128 bit CBC failed - see syslog for details"; + } + + if (memcmp (iv2, iv, 16)) + { + gcry_free (mem); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s-128-CBC test failed (IV mismatch)", cipher); +#endif + return "selftest for 128 bit CBC failed - see syslog for details"; + } + + /* Test parallelized code paths */ + memset (iv, 0x5f, blocksize); + memset (iv2, 0x5f, blocksize); + + for (i = 0; i < nblocks * blocksize; i++) + plaintext[i] = i; + + /* Create CBC ciphertext manually. */ + for (i = 0; i < nblocks * blocksize; i+=blocksize) + { + buf_xor (&ciphertext[i], iv, &plaintext[i], blocksize); + encrypt_one (ctx, &ciphertext[i], &ciphertext[i]); + memcpy (iv, &ciphertext[i], blocksize); + } + + /* Decrypt using bulk CBC and compare result. */ + bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, nblocks); + + if (memcmp (plaintext2, plaintext, nblocks * blocksize)) + { + gcry_free (mem); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s-128-CBC test failed (plaintext mismatch, parallel path)", + cipher); +#endif + return "selftest for 128 bit CBC failed - see syslog for details"; + } + if (memcmp (iv2, iv, blocksize)) + { + gcry_free (mem); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s-128-CBC test failed (IV mismatch, parallel path)", + cipher); +#endif + return "selftest for 128 bit CBC failed - see syslog for details"; + } + + gcry_free (mem); + return NULL; +} + +/* Run the self-tests for <block cipher>-CTR-128, tests IV increment of bulk CTR + encryption. Returns NULL on success. */ +const char * +_gcry_selftest_helper_ctr_128 (const char *cipher, gcry_cipher_setkey_t setkey, + gcry_cipher_encrypt_t encrypt_one, + gcry_cipher_bulk_ctr_enc_t bulk_ctr_enc, + const int nblocks, const int blocksize, + const int context_size) +{ + int i, j, offs, diff; + unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem; + unsigned int ctx_aligned_size, memsize; + + static const unsigned char key[16] ATTR_ALIGNED_16 = { + 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, + 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21 + }; + + /* Allocate buffers, align elements to 16 bytes. */ + ctx_aligned_size = context_size + 15; + ctx_aligned_size -= ctx_aligned_size & 0xf; + + memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 3) + 16; + + mem = gcry_calloc (1, memsize); + if (!mem) + return "failed to allocate memory"; + + offs = (16 - ((uintptr_t)mem & 15)) & 15; + ctx = (void*)(mem + offs); + iv = ctx + ctx_aligned_size; + iv2 = iv + blocksize; + plaintext = iv2 + blocksize; + plaintext2 = plaintext + nblocks * blocksize; + ciphertext = plaintext2 + nblocks * blocksize; + + /* Initialize ctx */ + setkey (ctx, key, sizeof(key)); + + /* Test single block code path */ + memset (iv, 0xff, blocksize); + for (i = 0; i < blocksize; i++) + plaintext[i] = i; + + /* CTR manually. */ + encrypt_one (ctx, ciphertext, iv); + for (i = 0; i < blocksize; i++) + ciphertext[i] ^= plaintext[i]; + for (i = blocksize; i > 0; i--) + { + iv[i-1]++; + if (iv[i-1]) + break; + } + + memset (iv2, 0xff, blocksize); + bulk_ctr_enc (ctx, iv2, plaintext2, ciphertext, 1); + + if (memcmp (plaintext2, plaintext, blocksize)) + { + gcry_free (mem); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s-128-CTR test failed (plaintext mismatch)", cipher); +#endif + return "selftest for 128 bit CTR failed - see syslog for details"; + } + + if (memcmp (iv2, iv, blocksize)) + { + gcry_free (mem); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s-128-CTR test failed (IV mismatch)", cipher); +#endif + return "selftest for 128 bit CTR failed - see syslog for details"; + } + + /* Test parallelized code paths */ + for (diff = 0; diff < nblocks; diff++) { + memset(iv, 0xff, blocksize); + iv[blocksize-1] -= diff; + + for (i = 0; i < blocksize * nblocks; i++) + plaintext[i] = i; + + /* Create CTR ciphertext manually. */ + for (i = 0; i < blocksize * nblocks; i+=blocksize) + { + encrypt_one (ctx, &ciphertext[i], iv); + for (j = 0; j < blocksize; j++) + ciphertext[i+j] ^= plaintext[i+j]; + for (j = blocksize; j > 0; j--) + { + iv[j-1]++; + if (iv[j-1]) + break; + } + } + + /* Decrypt using bulk CTR and compare result. */ + memset(iv2, 0xff, blocksize); + iv2[blocksize-1] -= diff; + + bulk_ctr_enc (ctx, iv2, plaintext2, ciphertext, nblocks); + + if (memcmp (plaintext2, plaintext, blocksize * nblocks)) + { + gcry_free (mem); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s-128-CTR test failed (plaintext mismatch, diff: %d)", cipher, + diff); +#endif + return "selftest for 128 bit CTR failed - see syslog for details"; + } + if (memcmp(iv2, iv, blocksize)) + { + gcry_free (mem); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s-128-CTR test failed (IV mismatch, diff: %d)", cipher, diff); +#endif + return "selftest for 128 bit CTR failed - see syslog for details"; + } + } + + gcry_free (mem); + return NULL; +} diff --git a/cipher/cipher-selftest.h b/cipher/cipher-selftest.h new file mode 100644 index 00000000..89d79c25 --- /dev/null +++ b/cipher/cipher-selftest.h @@ -0,0 +1,54 @@ +/* cipher-selftest.h - Helper functions for bulk encryption selftests. + * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef G10_SELFTEST_HELP_H +#define G10_SELFTEST_HELP_H + +#include <config.h> +#include "types.h" +#include "g10lib.h" +#include "cipher.h" + +typedef void (*gcry_cipher_bulk_cbc_dec_t)(void *context, unsigned char *iv, + void *outbuf_arg, + const void *inbuf_arg, + unsigned int nblocks); + +typedef void (*gcry_cipher_bulk_ctr_enc_t)(void *context, unsigned char *iv, + void *outbuf_arg, + const void *inbuf_arg, + unsigned int nblocks); + +/* Helper function for bulk CBC decryption selftest */ +const char * +_gcry_selftest_helper_cbc_128 (const char *cipher, gcry_cipher_setkey_t setkey, + gcry_cipher_encrypt_t encrypt_one, + gcry_cipher_bulk_cbc_dec_t bulk_cbc_dec, + const int nblocks, const int blocksize, + const int context_size); + +/* Helper function for bulk CTR encryption selftest */ +const char * +_gcry_selftest_helper_ctr_128 (const char *cipher, gcry_cipher_setkey_t setkey, + gcry_cipher_encrypt_t encrypt_one, + gcry_cipher_bulk_ctr_enc_t bulk_ctr_enc, + const int nblocks, const int blocksize, + const int context_size); + +#endif /*G10_SELFTEST_HELP_H*/ |