summaryrefslogtreecommitdiff
path: root/src/dh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dh.c')
-rw-r--r--src/dh.c131
1 files changed, 131 insertions, 0 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)
{