[PATCH v2 2/4] Convert bulk CTR and CBC selftest functions in Camellia to generic selftest helper functions
Jussi Kivilinna
jussi.kivilinna at iki.fi
Wed May 22 13:10:59 CEST 2013
* 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 at iki.fi>
---
cipher/Makefile.am | 1
cipher/camellia-glue.c | 168 ++-------------------------
cipher/cipher-selftest.c | 291 ++++++++++++++++++++++++++++++++++++++++++++++
cipher/cipher-selftest.h | 54 +++++++++
4 files changed, 357 insertions(+), 157 deletions(-)
create mode 100644 cipher/cipher-selftest.c
create mode 100644 cipher/cipher-selftest.h
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index 00e4429..0808bd2 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 e9e2bf2..4c724a9 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 0000000..50c7752
--- /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 at 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 0000000..89d79c2
--- /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 at 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*/
More information about the Gcrypt-devel
mailing list