summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-10-21 19:23:53 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-10-21 19:23:53 +0200
commitc92c0a92db339e284920cabd2b1ca3b2bb073de1 (patch)
tree31620b8c002698744187bae5f518e2879973005b
parentec3cc7df67c59dee1f47765dcee202045b87bb1c (diff)
downloadncrypto-c92c0a92db339e284920cabd2b1ca3b2bb073de1.tar.gz
ncrypto-c92c0a92db339e284920cabd2b1ca3b2bb073de1.tar.xz
ncrypto-c92c0a92db339e284920cabd2b1ca3b2bb073de1.zip
Add symmetric key generation
-rw-r--r--include/ncrypto/ncrypto.h2
-rw-r--r--lib/ncrypto_local.c106
-rw-r--r--tests/symm_ciphers.c108
3 files changed, 208 insertions, 8 deletions
diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h
index b23a8c4..aef6bb4 100644
--- a/include/ncrypto/ncrypto.h
+++ b/include/ncrypto/ncrypto.h
@@ -57,6 +57,8 @@ struct ncr_symm_key;
CK_RV ncr_symm_key_create (struct ncr_symm_key **key, CK_KEY_TYPE type,
const void *value, size_t value_size);
+CK_RV ncr_symm_key_generate (struct ncr_symm_key **key, CK_MECHANISM_TYPE mech,
+ size_t value_size);
CK_RV ncr_symm_key_destroy (struct ncr_symm_key *key);
/* Asymmetric keys */
diff --git a/lib/ncrypto_local.c b/lib/ncrypto_local.c
index 8f570b6..f311d63 100644
--- a/lib/ncrypto_local.c
+++ b/lib/ncrypto_local.c
@@ -86,6 +86,112 @@ ncr_symm_key_create (struct ncr_symm_key **key, CK_KEY_TYPE type,
return CKR_OK;
}
+/* Return non-zero if the key is unusable */
+#define DES_KEY_SIZE 8
+static int
+des3_fixup_key (uint8_t value[static 3 * DES_KEY_SIZE])
+{
+ static const uint8_t weak_keys[][DES_KEY_SIZE] =
+ {
+ "\x01\x01\x01\x01\x01\x01\x01\x01",
+ "\x1F\x1F\x1F\x1F\x0E\x0E\x0E\x0E",
+ "\xE0\xE0\xE0\xE0\xF1\xF1\xF1\xF1",
+ "\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE",
+ "\x01\xFE\x01\xFE\x01\xFE\x01\xFE",
+ "\xFE\x01\xFE\x01\xFE\x01\xFE\x01",
+ "\x1F\xE0\x1F\xE0\x0E\xF1\x0E\xF1",
+ "\xE0\x1F\xE0\x1F\xF1\x0E\xF1\x0E",
+ "\x01\xE0\x01\xE0\x01\xF1\x01\xF1",
+ "\xE0\x01\xE0\x01\xF1\x01\xF1\x01",
+ "\x1F\xFE\x1F\xFE\x0E\xFE\x0E\xFE",
+ "\xFE\x1F\xFE\x1F\xFE\x0E\xFE\x0E",
+ "\x01\x1F\x01\x1F\x01\x0E\x01\x0E",
+ "\x1F\x01\x1F\x01\x0E\x01\x0E\x01",
+ "\xE0\xFE\xE0\xFE\xF1\xFE\xF1\xFE",
+ "\xFE\xE0\xFE\xE0\xFE\xF1\xFE\xF1"
+ };
+
+ size_t i;
+
+ for (i = 0; i < 3; i++)
+ {
+ uint8_t *key;
+ size_t j;
+
+ key = value + i * 8;
+ for (j = 0; j < DES_KEY_SIZE; j++)
+ {
+ uint8_t v;
+
+ v = key[i];
+ v ^= v >> 4; /* v & 0x0F has the same parity as key[i] */
+ v ^= v >> 2; /* v & 0x03 has the same parity as key[i] */
+ v ^= v >> 1; /* v & 0x01 has the same parity as key[i] */
+ key[i] ^= (v & 0x01) ^ 0x01; /* Ensure odd parity */
+ }
+ for (j = 0; j < G_N_ELEMENTS (weak_keys); j++)
+ {
+ if (memcmp (key, weak_keys[j], DES_KEY_SIZE) == 0)
+ return 1;
+ }
+ }
+ return 0;
+}
+#undef DES_KEY_SIZE
+
+CK_RV
+ncr_symm_key_generate (struct ncr_symm_key **key, CK_MECHANISM_TYPE mech,
+ size_t value_size)
+{
+ struct ncr_symm_key *k;
+ CK_KEY_TYPE type;
+ CK_RV res;
+
+ g_return_val_if_fail (key != NULL, CKR_ARGUMENTS_BAD);
+ /* FIXME: PKCS#11 modules should refuse keys with incorrect parity here */
+
+ switch (mech)
+ {
+ case CKM_AES_KEY_GEN:
+ type = CKK_AES;
+ g_return_val_if_fail (value_size == 16 || value_size == 24
+ || value_size == 32, CKR_TEMPLATE_INCONSISTENT);
+ break;
+
+ case CKM_DES3_KEY_GEN:
+ type = CKK_DES3;
+ g_return_val_if_fail (value_size == 24 || value_size == 0,
+ CKR_TEMPLATE_INCONSISTENT);
+ value_size = 24;
+ break;
+
+ default:
+ g_return_val_if_reached (CKR_MECHANISM_INVALID);
+ }
+ k = malloc (sizeof (*k) + value_size);
+ if (k == NULL)
+ return CKR_HOST_MEMORY;
+
+ k->type = type;
+ k->size = value_size;
+ regenerate:
+ res = ncr_get_random_bytes (k->value, value_size);
+ if (res != CKR_OK)
+ {
+ ncr_symm_key_destroy (k);
+ return res;
+ }
+
+ if (type == CKK_DES3)
+ {
+ if (des3_fixup_key (k->value) != 0)
+ goto regenerate;
+ }
+
+ *key = k;
+ return CKR_OK;
+}
+
CK_RV
ncr_symm_key_destroy (struct ncr_symm_key *key)
{
diff --git a/tests/symm_ciphers.c b/tests/symm_ciphers.c
index d4e673d..87fb7a2 100644
--- a/tests/symm_ciphers.c
+++ b/tests/symm_ciphers.c
@@ -36,6 +36,7 @@ Red Hat author: Miloslav Trmač <mitr@redhat.com> */
struct tv
{
CK_MECHANISM_TYPE mech;
+ CK_MECHANISM_TYPE key_gen_mech;
CK_KEY_TYPE key_type;
const uint8_t *key;
size_t key_size;
@@ -50,36 +51,36 @@ struct tv
/* FIXME: Test CBC_PAD as well. */
static const struct tv tvs[] =
{
-#define TV(M, K, KEY, IV, IN, OUT) \
+#define TV(M, GM, K, KEY, IV, IN, OUT) \
{ \
- (M), (K), (const uint8_t *)(KEY), sizeof (KEY) - 1, \
+ (M), (GM), (K), (const uint8_t *)(KEY), sizeof (KEY) - 1, \
(const uint8_t *)(IV), sizeof (IV) - 1, (const uint8_t *)(IN), \
sizeof (IN) - 1, (const uint8_t *)(OUT), sizeof (OUT) - 1 \
}
- TV (CKM_AES_ECB, CKK_AES,
+ TV (CKM_AES_ECB, CKM_AES_KEY_GEN, CKK_AES,
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", "",
"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF",
"\x69\xC4\xE0\xD8\x6A\x7B\x04\x30\xD8\xCD\xB7\x80\x70\xB4\xC5\x5A"),
- TV (CKM_AES_ECB, CKK_AES,
+ TV (CKM_AES_ECB, CKM_AES_KEY_GEN, CKK_AES,
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17",
"", "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF",
"\xDD\xA9\x7C\xA4\x86\x4C\xDF\xE0\x6E\xAF\x70\xA0\xEC\x0D\x71\x91"),
- TV (CKM_AES_ECB, CKK_AES,
+ TV (CKM_AES_ECB, CKM_AES_KEY_GEN, CKK_AES,
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
"", "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF",
"\x8E\xA2\xB7\xCA\x51\x67\x45\xBF\xEA\xFC\x49\x90\x4B\x49\x60\x89"),
- TV (CKM_AES_CBC, CKK_AES,
+ TV (CKM_AES_CBC, CKM_AES_KEY_GEN, CKK_AES,
"\x2B\x7E\x15\x16\x28\xAE\xD2\xA6\xAB\xF7\x15\x88\x09\xCF\x4F\x3C",
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
"\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51\x30\xC8\x1C\x46\xA3\x5C\xE4\x11\xE5\xFB\xC1\x19\x1A\x0A\x52\xEF\xF6\x9F\x24\x45\xDF\x4F\x9B\x17\xAD\x2B\x41\x7B\xE6\x6C\x37\x10",
"\x76\x49\xAB\xAC\x81\x19\xB2\x46\xCE\xE9\x8E\x9B\x12\xE9\x19\x7D\x50\x86\xCB\x9B\x50\x72\x19\xEE\x95\xDB\x11\x3A\x91\x76\x78\xB2\x73\xBE\xD6\xB8\xE3\xC1\x74\x3B\x71\x16\xE6\x9E\x22\x22\x95\x16\x3F\xF1\xCA\xA1\x68\x1F\xAC\x09\x12\x0E\xCA\x30\x75\x86\xE1\xA7"),
- TV (CKM_AES_CBC, CKK_AES,
+ TV (CKM_AES_CBC, CKM_AES_KEY_GEN, CKK_AES,
"\x8E\x73\xB0\xF7\xDA\x0E\x64\x52\xC8\x10\xF3\x2B\x80\x90\x79\xE5\x62\xF8\xEA\xD2\x52\x2C\x6B\x7B",
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
"\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51\x30\xC8\x1C\x46\xA3\x5C\xE4\x11\xE5\xFB\xC1\x19\x1A\x0A\x52\xEF\xF6\x9F\x24\x45\xDF\x4F\x9B\x17\xAD\x2B\x41\x7B\xE6\x6C\x37\x10",
"\x4F\x02\x1D\xB2\x43\xBC\x63\x3D\x71\x78\x18\x3A\x9F\xA0\x71\xE8\xB4\xD9\xAD\xA9\xAD\x7D\xED\xF4\xE5\xE7\x38\x76\x3F\x69\x14\x5A\x57\x1B\x24\x20\x12\xFB\x7A\xE0\x7F\xA9\xBA\xAC\x3D\xF1\x02\xE0\x08\xB0\xE2\x79\x88\x59\x88\x81\xD9\x20\xA9\xE6\x4F\x56\x15\xCD"),
- TV (CKM_AES_CBC, CKK_AES,
+ TV (CKM_AES_CBC, CKM_AES_KEY_GEN, CKK_AES,
"\x60\x3D\xEB\x10\x15\xCA\x71\xBE\x2B\x73\xAE\xF0\x85\x7D\x77\x81\x1F\x35\x2C\x07\x3B\x61\x08\xD7\x2D\x98\x10\xA3\x09\x14\xDF\xF4",
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
"\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51\x30\xC8\x1C\x46\xA3\x5C\xE4\x11\xE5\xFB\xC1\x19\x1A\x0A\x52\xEF\xF6\x9F\x24\x45\xDF\x4F\x9B\x17\xAD\x2B\x41\x7B\xE6\x6C\x37\x10",
@@ -192,5 +193,96 @@ main (void)
assert (res == CKR_OK);
}
+ for (i = 0; i < G_N_ELEMENTS (tvs); i++)
+ {
+ res = ncr_symm_cipher_alloc (&sess, tvs[i].mech);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_key_generate (&key, tvs[i].key_gen_mech, tvs[i].key_size);
+ assert (res == CKR_OK);
+
+ for (j = 0; j < 2; j++)
+ {
+ res = ncr_symm_cipher_encrypt_init (sess, key, tvs[i].iv,
+ tvs[i].iv_size);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_cipher_encrypt_update (sess, dest, &dest_size,
+ tvs[i].input,
+ tvs[i].input_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_cipher_encrypt_final (sess, dest, &dest_size,
+ NULL, 0);
+ assert (res == CKR_OK);
+ assert (dest_size == 0);
+
+ res = ncr_symm_cipher_decrypt_init (sess, key, tvs[i].iv,
+ tvs[i].iv_size);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_cipher_decrypt_update (sess, dest, &dest_size, dest,
+ tvs[i].output_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].input_size);
+ assert (memcmp (dest, tvs[i].input, dest_size) == 0);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_cipher_decrypt_final (sess, dest, &dest_size,
+ NULL, 0);
+ assert (res == CKR_OK);
+ assert (dest_size == 0);
+ }
+
+ res = ncr_symm_key_destroy (key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_cipher_free (sess);
+ assert (res == CKR_OK);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (tvs); i++)
+ {
+ res = ncr_symm_cipher_alloc (&sess, tvs[i].mech);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_key_generate (&key, tvs[i].key_gen_mech, tvs[i].key_size);
+ assert (res == CKR_OK);
+
+ for (j = 0; j < 2; j++)
+ {
+ res = ncr_symm_cipher_encrypt_init (sess, key, tvs[i].iv,
+ tvs[i].iv_size);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_cipher_encrypt (sess, dest, &dest_size, tvs[i].input,
+ tvs[i].input_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+
+ res = ncr_symm_cipher_decrypt_init (sess, key, tvs[i].iv,
+ tvs[i].iv_size);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_cipher_decrypt (sess, dest, &dest_size, dest,
+ tvs[i].output_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].input_size);
+ assert (memcmp (dest, tvs[i].input, dest_size) == 0);
+ }
+
+ res = ncr_symm_key_destroy (key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_cipher_free (sess);
+ assert (res == CKR_OK);
+ }
+
return EXIT_SUCCESS;
}