summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2009-11-18 17:30:31 +0000
committerStef Walter <stef@memberwebs.com>2009-11-18 17:30:31 +0000
commit9b25b05d7aa4a816cfa06f4750cb600cb94e27b7 (patch)
tree8b8b7a0c032a7bc838cd9f1233733e44e40b91f4
parentf4b12883579af918653904d3f1351d9a454d5e6f (diff)
Add support for checking AES keys and DH derive
-rw-r--r--src/dh.c131
-rw-r--r--src/key.c257
-rw-r--r--src/p11-tests-lib.h2
3 files changed, 383 insertions, 7 deletions
diff --git a/src/dh.c b/src/dh.c
index 3325caa..7016498 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -7,6 +7,137 @@
#include <openssl/dh.h>
+static int
+compare_secret_values (void *one, size_t n_one, void *two, size_t n_two)
+{
+ if (n_one > n_two)
+ return memcmp (one + (n_one - n_two), two, n_two);
+ else
+ return memcmp (one, two + (n_two - n_one), n_one);
+}
+
+static DH*
+generate_peer_dh (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key)
+{
+ CK_ATTRIBUTE attrs[2];
+ CK_BYTE prime[16384];
+ CK_BYTE base[1024];
+ DH *dh;
+
+ attrs[0].type = CKA_PRIME;
+ attrs[0].ulValueLen = sizeof (prime);
+ attrs[0].pValue = prime;
+
+ attrs[1].type = CKA_BASE;
+ attrs[1].ulValueLen = sizeof (base);
+ attrs[1].pValue = base;
+
+ if (!p11t_object_get (session, key, attrs, 2))
+ return NULL;
+
+ if(attrs[0].ulValueLen == CK_INVALID ||
+ attrs[1].ulValueLen == CK_INVALID)
+ return NULL;
+
+ dh = DH_new ();
+ dh->p = BN_bin2bn (prime, attrs[0].ulValueLen, NULL);
+ dh->g = BN_bin2bn (base, attrs[1].ulValueLen, NULL);
+ assert(dh && dh->p && dh->g);
+
+ if (!DH_generate_key (dh)) {
+ DH_free (dh);
+ return NULL;
+ }
+
+ return dh;
+}
+
+int
+test_dh_private_derive (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE pub, CK_OBJECT_HANDLE prv)
+{
+ CK_ATTRIBUTE attrs[3];
+ CK_KEY_TYPE key_type = CKK_AES;
+ CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
+ CK_BYTE buffer[16384];
+ CK_BYTE value[16384];
+ CK_OBJECT_HANDLE derived;
+ CK_MECHANISM mech;
+ BIGNUM *our_pub;
+ CK_RV rv;
+ DH *dh;
+
+ P11T_SECTION("C_DeriveKey");
+
+ /* Setup peer's DH */
+ dh = generate_peer_dh (session, pub);
+ if (dh == NULL)
+ p11t_check_warn ("Couldn't retrieve DH parameters from DH pub key");
+
+ /* Dig out our public key */
+ attrs[0].type = CKA_VALUE;
+ attrs[0].pValue = value;
+ attrs[0].ulValueLen = sizeof (value);
+ if (p11t_object_get (session, pub, attrs, 1)) {
+ our_pub = BN_bin2bn (value, attrs[0].ulValueLen, NULL);
+ } else {
+ p11t_check_warn ("Couldn't retrieve DH public value from DH pub key");
+ our_pub = NULL;
+ }
+
+ mech.mechanism = CKM_DH_PKCS_DERIVE;
+ mech.pParameter = buffer;
+ mech.ulParameterLen = BN_num_bytes (dh->pub_key);
+ BN_bn2bin (dh->pub_key, buffer);
+
+ /* TODO: How can we know this key type is supported? */
+ attrs[0].type = CKA_KEY_TYPE;
+ attrs[0].pValue = &key_type;
+ attrs[0].ulValueLen = sizeof (key_type);
+
+ attrs[1].type = CKA_CLASS;
+ attrs[1].pValue = &klass;
+ attrs[1].ulValueLen = sizeof (klass);
+
+ rv = (p11t_module_funcs->C_DeriveKey) (session, &mech, prv, attrs, 2, &derived);
+ P11T_CHECK_RV ("CKM_DH_PKCS_DERIVE", rv, CKR_OK);
+
+ /* Compare to our generated key */
+ attrs[0].type = CKA_VALUE;
+ attrs[0].pValue = value;
+ attrs[0].ulValueLen = sizeof (value);
+ if (p11t_object_get (session, derived, attrs, 1) && attrs[0].ulValueLen != (CK_ULONG)-1 &&
+ dh != NULL && our_pub != NULL) {
+ if (!DH_compute_key (buffer, our_pub, dh))
+ assert (0);
+ if (compare_secret_values (value, attrs[0].ulValueLen, buffer, DH_size (dh)) != 0)
+ P11T_CHECK_FAIL_MSG ("CKM_DH_PKCS_DERIVE", "Derived key has wrong secret value");
+ }
+
+ BN_free (our_pub);
+ DH_free (dh);
+
+ return p11t_key_test (session, derived, CKO_SECRET_KEY);
+}
+
+int
+p11t_dh_test_key_pair (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE pub, CK_OBJECT_HANDLE prv)
+{
+ CK_ULONG mechanisms[128];
+ CK_ATTRIBUTE attr = { CKA_ALLOWED_MECHANISMS, mechanisms, sizeof (mechanisms) };
+ CK_ULONG i;
+
+ /* Let's see if it support derivation */
+ if (!p11t_object_get (session, prv, &attr, 1))
+ return STOP;
+
+ for (i = 0; i < attr.ulValueLen / sizeof (CK_ULONG); ++i) {
+ if (mechanisms[i] == CKM_DH_PKCS_DERIVE)
+ test_dh_private_derive (session, pub, prv);
+ }
+
+ return CONTINUE;
+}
+
static void
test_dh_key_pair_gen (CK_SLOT_ID slot, CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR info)
{
diff --git a/src/key.c b/src/key.c
index a305215..41f66f4 100644
--- a/src/key.c
+++ b/src/key.c
@@ -1,6 +1,8 @@
#include "p11-tests-lib.h"
+#include <string.h>
+
/* ----------------------------------------------------------------------------------
* TESTS
*/
@@ -266,6 +268,102 @@ test_private_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
}
static int
+test_secret_attributes (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
+{
+ CK_ATTRIBUTE attr;
+ CK_BBOOL bval;
+ CK_RV rv;
+
+ attr.type = CKA_SENSITIVE;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_SENSITIVE", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_SENSITIVE", bval);
+
+ attr.type = CKA_ENCRYPT;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_ENCRYPT", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_ENCRYPT", bval);
+
+ attr.type = CKA_DECRYPT;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_DECRYPT", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_DECRYPT", bval);
+
+ attr.type = CKA_SIGN;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_SIGN", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_SIGN", bval);
+
+ attr.type = CKA_VERIFY;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_VERIFY", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_VERIFY", bval);
+
+ attr.type = CKA_WRAP;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_WRAP", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_WRAP", bval);
+
+ attr.type = CKA_UNWRAP;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_UNWRAP", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_UNWRAP", bval);
+
+ attr.type = CKA_EXTRACTABLE;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_EXTRACTABLE", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_EXTRACTABLE", bval);
+
+ attr.type = CKA_ALWAYS_SENSITIVE;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_ALWAYS_SENSITIVE", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_ALWAYS_SENSITIVE", bval);
+
+ attr.type = CKA_NEVER_EXTRACTABLE;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_NEVER_EXTRACTABLE", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_NEVER_EXTRACTABLE", bval);
+
+ if(p11t_test_unexpected) {
+ attr.type = CKA_WRAP_WITH_TRUSTED;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_WRAP_WITH_TRUSTED", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_WRAP_WITH_TRUSTED", bval);
+ }
+
+ attr.type = CKA_TRUSTED;
+ attr.pValue = &bval;
+ attr.ulValueLen = sizeof (bval);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_TRUSTED", rv, CKR_OK);
+ P11T_CHECK_BOOL ("CKA_TRUSTED", bval);
+
+ return CONTINUE;
+}
+
+static int
test_rsa_public(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
{
CK_ATTRIBUTE attr;
@@ -702,6 +800,73 @@ test_dh_private (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
return CONTINUE;
}
+static int
+test_aes_secret (session, object)
+{
+ CK_ATTRIBUTE attr;
+ CK_BYTE buffer[16384];
+ CK_BYTE check[1024];
+ EVP_CIPHER_CTX ctx;
+ CK_ULONG length;
+ void *plaintext;
+ int outlen;
+ CK_RV rv;
+
+ P11T_SECTION ("CKK_AES Secret");
+
+ attr.type = CKA_CHECK_VALUE;
+ attr.pValue = check;
+ attr.ulValueLen = sizeof (check);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_CHECK_VALUE", rv, CKR_OK);
+ if (attr.ulValueLen != 3)
+ P11T_CHECK_FAIL_MSG ("CKA_CHECK_VALUE", "Should be 3 bytes");
+
+ attr.type = CKA_VALUE_LEN;
+ attr.pValue = &length;
+ attr.ulValueLen = sizeof (length);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ P11T_CHECK_RV ("CKA_VALUE_LEN", rv, CKR_OK);
+
+ attr.type = CKA_VALUE;
+ attr.pValue = buffer;
+ attr.ulValueLen = sizeof (buffer);
+ rv = (p11t_module_funcs->C_GetAttributeValue) (session, object, &attr, 1);
+ if (rv != CKR_ATTRIBUTE_SENSITIVE) {
+ P11T_CHECK_RV ("CKA_VALUE", rv, CKR_OK);
+
+ if (length != attr.ulValueLen)
+ P11T_CHECK_FAIL_MSG ("CKA_VALUE_LEN", "Should match the length of CKA_VALUE");
+
+ switch (attr.ulValueLen) {
+ case 16:
+ EVP_EncryptInit (&ctx, EVP_aes_128_ecb (), buffer, NULL);
+ break;
+ case 24:
+ EVP_EncryptInit (&ctx, EVP_aes_192_ecb (), buffer, NULL);
+ break;
+ case 32:
+ EVP_EncryptInit (&ctx, EVP_aes_256_ecb (), buffer, NULL);
+ break;
+ default:
+ P11T_CHECK_FAIL_MSG ("CKA_VALUE", "Length should be 16, 24 or 32 bytes");
+ break;
+ };
+
+ plaintext = calloc (attr.ulValueLen, 1);
+ if (!EVP_EncryptUpdate (&ctx, buffer, &outlen, plaintext, attr.ulValueLen))
+ assert (0);
+ assert (outlen == attr.ulValueLen);
+
+ EVP_CIPHER_CTX_cleanup (&ctx);
+
+ if (memcmp (check, buffer, 3) != 0)
+ P11T_CHECK_FAIL_MSG ("CKA_CHECK_VALUE", "Check value is not correct");
+
+ }
+
+ return CONTINUE;
+}
static int
test_rsa_public_create(CK_SESSION_HANDLE session, CK_BBOOL token, RSA *rsa, CK_OBJECT_HANDLE_PTR result)
@@ -1127,19 +1292,83 @@ test_dh_create(CK_SESSION_HANDLE session, CK_BBOOL token)
test_dh_public_create (session, token, dh, &pub);
test_dh_private_create (session, token, dh, &prv);
+ if (pub != 0 && prv != 0)
+ p11t_dh_test_key_pair (session, pub, prv);
+
+ P11T_SECTION ("C_DestroyObject");
+
+ rv = (p11t_module_funcs->C_DestroyObject) (session, pub);
+ P11T_CHECK_RV ("DH Public Key", rv, CKR_OK);
+ rv = (p11t_module_funcs->C_DestroyObject) (session, prv);
+ P11T_CHECK_RV ("DH Private Key", rv, CKR_OK);
+
+ DH_free (dh);
+ return CONTINUE;
+}
+
+static int
+test_aes_secret_create (CK_SESSION_HANDLE session, CK_BBOOL token, void *value,
+ size_t length, CK_OBJECT_HANDLE_PTR result)
+{
+ CK_OBJECT_HANDLE object;
+ CK_ATTRIBUTE attrs[10];
+ CK_KEY_TYPE key_type = CKK_AES;
+ CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
+ CK_RV rv;
+
+ P11T_SECTION("C_CreateObject");
+
+ /* Fill in all the attributes */
+ attrs[0].type = CKA_TOKEN;
+ attrs[0].pValue = &token;
+ attrs[0].ulValueLen = sizeof (token);
+
+ attrs[1].type = CKA_CLASS;
+ attrs[1].ulValueLen = sizeof (klass);
+ attrs[1].pValue = &klass;
+
+ attrs[2].type = CKA_LABEL;
+ attrs[2].pValue = "Test AES Secret Key";
+ attrs[2].ulValueLen = 20;
+
+ attrs[3].type = CKA_KEY_TYPE;
+ attrs[3].pValue = &key_type;
+ attrs[3].ulValueLen = sizeof (key_type);
+
+ attrs[4].type = CKA_VALUE;
+ attrs[4].ulValueLen = length;
+ attrs[4].pValue = value;
+
+ rv = (p11t_module_funcs->C_CreateObject) (session, attrs, 5, &object);
+ if (rv == CKR_TEMPLATE_INCOMPLETE)
+ return CONTINUE;
+ P11T_CHECK_RV ("AES Secret Key", rv, CKR_OK);
+
+ p11t_key_test (session, object, CKO_SECRET_KEY);
+ *result = object;
+ return CONTINUE;
+}
+
+static int
+test_aes_create (CK_SESSION_HANDLE session, CK_BBOOL token)
+{
+ CK_OBJECT_HANDLE key;
+ CK_RV rv;
+
+ key = 0;
+ if (!test_aes_secret_create (session, token, "0123456789ABCDEF", 16, &key))
+ return STOP;
+
#if 0
if (pub != 0)
- p11t_dh_test_public_key (session, pub);
- if (prv != 0)
- p11t_dh_test_private_key (session, prv);
+ p11t_aes_test_secret_key (session, key);
#endif
- P11T_SECTION("C_DestroyObject");
+ P11T_SECTION ("C_DestroyObject");
- rv = (p11t_module_funcs->C_DestroyObject)(session, pub);
- P11T_CHECK_RV("DH Public Key", rv, CKR_OK);
+ rv = (p11t_module_funcs->C_DestroyObject) (session, key);
+ P11T_CHECK_RV ("AES Secret Key", rv, CKR_OK);
- DH_free (dh);
return CONTINUE;
}
@@ -1216,6 +1445,10 @@ p11t_key_test (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, CK_OBJECT_CLA
test_dsa_public (session, object);
else if (key_type == CKK_DH)
test_dh_public (session, object);
+ } else if (key_class == CKO_SECRET_KEY) {
+ test_secret_attributes (session, object);
+ if (key_type == CKK_AES)
+ test_aes_secret (session, object);
}
}
@@ -1268,6 +1501,16 @@ p11t_key_tests(void)
test_dsa_create (session, CK_FALSE);
test_dh_create (session, CK_FALSE);
}
+
+ klass = CKO_SECRET_KEY;
+ objects = p11t_object_find (session, attrs, 1, &n_objects);
+ for (i = 0; objects && i < n_objects; ++i)
+ p11t_key_test (session, objects[i], klass);
+ free (objects);
+
+ if (p11t_test_write_session) {
+ test_aes_create (session, CK_FALSE);
+ }
}
p11t_session_close(session);
diff --git a/src/p11-tests-lib.h b/src/p11-tests-lib.h
index 500f75c..c7368d9 100644
--- a/src/p11-tests-lib.h
+++ b/src/p11-tests-lib.h
@@ -18,6 +18,7 @@
#include <openssl/rsa.h>
#include <openssl/dsa.h>
+#include <openssl/evp.h>
#define CK_INVALID ((CK_ULONG)-1)
@@ -140,6 +141,7 @@ int p11t_dh_test_generate_pair (CK_SESSION_HANDLE session);
void p11t_dh_tests (void);
int p11t_dh_test_generate_pair (CK_SESSION_HANDLE session);
+int p11t_dh_test_key_pair (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE pub, CK_OBJECT_HANDLE prv);
/* -------------------------------------------------------------------
* key.c