summaryrefslogtreecommitdiffstats
path: root/lib
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 /lib
parentec3cc7df67c59dee1f47765dcee202045b87bb1c (diff)
downloadncrypto-c92c0a92db339e284920cabd2b1ca3b2bb073de1.tar.gz
ncrypto-c92c0a92db339e284920cabd2b1ca3b2bb073de1.tar.xz
ncrypto-c92c0a92db339e284920cabd2b1ca3b2bb073de1.zip
Add symmetric key generation
Diffstat (limited to 'lib')
-rw-r--r--lib/ncrypto_local.c106
1 files changed, 106 insertions, 0 deletions
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)
{