pkcs11: We have to create our own hashes for some signature schemes.
authorTobias Brunner <tobias@strongswan.org>
Wed, 2 Nov 2011 18:23:05 +0000 (19:23 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 2 Nov 2011 19:27:55 +0000 (20:27 +0100)
src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h
src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
src/libstrongswan/plugins/pkcs11/pkcs11_public_key.h

index fda6ae3..a354070 100644 (file)
@@ -103,18 +103,42 @@ METHOD(private_key_t, get_keysize, int,
 /**
  * See header.
  */
-CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme)
+CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme,
+                                                                                                hash_algorithm_t *hash)
 {
        static struct {
                signature_scheme_t scheme;
                CK_MECHANISM mechanism;
+               hash_algorithm_t hash;
        } mappings[] = {
-               {SIGN_RSA_EMSA_PKCS1_NULL,              {CKM_RSA_PKCS,                          NULL, 0}},
-               {SIGN_RSA_EMSA_PKCS1_SHA1,              {CKM_SHA1_RSA_PKCS,                     NULL, 0}},
-               {SIGN_RSA_EMSA_PKCS1_SHA256,    {CKM_SHA256_RSA_PKCS,           NULL, 0}},
-               {SIGN_RSA_EMSA_PKCS1_SHA384,    {CKM_SHA384_RSA_PKCS,           NULL, 0}},
-               {SIGN_RSA_EMSA_PKCS1_SHA512,    {CKM_SHA512_RSA_PKCS,           NULL, 0}},
-               {SIGN_RSA_EMSA_PKCS1_MD5,               {CKM_MD5_RSA_PKCS,                      NULL, 0}},
+               {SIGN_RSA_EMSA_PKCS1_NULL,              {CKM_RSA_PKCS,                  NULL, 0},
+                                                                                                                  HASH_UNKNOWN},
+               {SIGN_RSA_EMSA_PKCS1_SHA1,              {CKM_SHA1_RSA_PKCS,             NULL, 0},
+                                                                                                                  HASH_UNKNOWN},
+               {SIGN_RSA_EMSA_PKCS1_SHA256,    {CKM_SHA256_RSA_PKCS,   NULL, 0},
+                                                                                                                  HASH_UNKNOWN},
+               {SIGN_RSA_EMSA_PKCS1_SHA384,    {CKM_SHA384_RSA_PKCS,   NULL, 0},
+                                                                                                                  HASH_UNKNOWN},
+               {SIGN_RSA_EMSA_PKCS1_SHA512,    {CKM_SHA512_RSA_PKCS,   NULL, 0},
+                                                                                                                  HASH_UNKNOWN},
+               {SIGN_RSA_EMSA_PKCS1_MD5,               {CKM_MD5_RSA_PKCS,              NULL, 0},
+                                                                                                                  HASH_UNKNOWN},
+               {SIGN_ECDSA_WITH_NULL,                  {CKM_ECDSA,                             NULL, 0},
+                                                                                                                  HASH_UNKNOWN},
+               {SIGN_ECDSA_WITH_SHA1_DER,              {CKM_ECDSA_SHA1,                NULL, 0},
+                                                                                                                  HASH_UNKNOWN},
+               {SIGN_ECDSA_WITH_SHA256_DER,    {CKM_ECDSA,                             NULL, 0},
+                                                                                                                       HASH_SHA256},
+               {SIGN_ECDSA_WITH_SHA384_DER,    {CKM_ECDSA,                             NULL, 0},
+                                                                                                                       HASH_SHA384},
+               {SIGN_ECDSA_WITH_SHA512_DER,    {CKM_ECDSA,                             NULL, 0},
+                                                                                                                       HASH_SHA512},
+               {SIGN_ECDSA_256,                                {CKM_ECDSA,                             NULL, 0},
+                                                                                                                       HASH_SHA256},
+               {SIGN_ECDSA_384,                                {CKM_ECDSA,                             NULL, 0},
+                                                                                                                       HASH_SHA384},
+               {SIGN_ECDSA_521,                                {CKM_ECDSA,                             NULL, 0},
+                                                                                                                       HASH_SHA512},
        };
        int i;
 
@@ -122,6 +146,10 @@ CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme)
        {
                if (mappings[i].scheme == scheme)
                {
+                       if (hash)
+                       {
+                               *hash = mappings[i].hash;
+                       }
                        return &mappings[i].mechanism;
                }
        }
@@ -198,8 +226,10 @@ METHOD(private_key_t, sign, bool,
        CK_BYTE_PTR buf;
        CK_ULONG len;
        CK_RV rv;
+       hash_algorithm_t hash_alg;
+       chunk_t hash = chunk_empty;
 
-       mechanism = pkcs11_signature_scheme_to_mech(scheme);
+       mechanism = pkcs11_signature_scheme_to_mech(scheme, &hash_alg);
        if (!mechanism)
        {
                DBG1(DBG_LIB, "signature scheme %N not supported",
@@ -225,10 +255,27 @@ METHOD(private_key_t, sign, bool,
                DBG1(DBG_LIB, "C_SignInit() failed: %N", ck_rv_names, rv);
                return FALSE;
        }
+       if (hash_alg != HASH_UNKNOWN)
+       {
+               hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+               if (!hasher)
+               {
+                       this->lib->f->C_CloseSession(session);
+                       return FALSE;
+               }
+               hasher->allocate_hash(hasher, data, &hash);
+               hasher->destroy(hasher);
+               data = hash;
+       }
        len = (get_keysize(this) + 7) / 8;
+       if (this->type == KEY_ECDSA)
+       {       /* signature is twice the length of the base point order */
+               len *= 2;
+       }
        buf = malloc(len);
        rv = this->lib->f->C_Sign(session, data.ptr, data.len, buf, &len);
        this->lib->f->C_CloseSession(session);
+       chunk_free(&hash);
        if (rv != CKR_OK)
        {
                DBG1(DBG_LIB, "C_Sign() failed: %N", ck_rv_names, rv);
index 428913f..1e4ec30 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2010 Martin Willi
  * Copyright (C) 2010 revosec AG
  *
@@ -46,14 +49,18 @@ struct pkcs11_private_key_t {
  *
  * @param type         type of the key
  * @param args         builder_part_t argument list
- * @return                     loaded key, NULL on failure
+ * @return                     loaded key, NULL on failure
  */
 pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t type, va_list args);
 
 /**
  * Get the Cryptoki mechanism for a signature scheme.
+ *
+ * @param scheme               signature scheme
+ * @param hash                 hash algorithm to apply first (HASH_UNKNOWN if none)
  */
-CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme);
+CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme,
+                                                                                                hash_algorithm_t *hash);
 
 /**
  * Get the Cryptoki mechanism for a encryption scheme.
index 0be7b05..2a3a511 100644 (file)
@@ -204,8 +204,10 @@ METHOD(public_key_t, verify, bool,
        CK_MECHANISM_PTR mechanism;
        CK_SESSION_HANDLE session;
        CK_RV rv;
+       hash_algorithm_t hash_alg;
+       chunk_t hash = chunk_empty;
 
-       mechanism = pkcs11_signature_scheme_to_mech(scheme);
+       mechanism = pkcs11_signature_scheme_to_mech(scheme, &hash_alg);
        if (!mechanism)
        {
                DBG1(DBG_LIB, "signature scheme %N not supported",
@@ -230,8 +232,21 @@ METHOD(public_key_t, verify, bool,
                DBG1(DBG_LIB, "C_VerifyInit() failed: %N", ck_rv_names, rv);
                return FALSE;
        }
+       if (hash_alg != HASH_UNKNOWN)
+       {
+               hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+               if (!hasher)
+               {
+                       this->lib->f->C_CloseSession(session);
+                       return FALSE;
+               }
+               hasher->allocate_hash(hasher, data, &hash);
+               hasher->destroy(hasher);
+               data = hash;
+       }
        rv = this->lib->f->C_Verify(session, data.ptr, data.len, sig.ptr, sig.len);
        this->lib->f->C_CloseSession(session);
+       chunk_free(&hash);
        if (rv != CKR_OK)
        {
                DBG1(DBG_LIB, "C_Verify() failed: %N", ck_rv_names, rv);
index 4fd9462..b3ea725 100644 (file)
@@ -42,7 +42,7 @@ struct pkcs11_public_key_t {
  *
  * @param type         type of the key
  * @param args         builder_part_t argument list
- * @return                     loaded key, NULL on failure
+ * @return                     loaded key, NULL on failure
  */
 pkcs11_public_key_t *pkcs11_public_key_load(key_type_t type, va_list args);