use openssl rsa_verify function
authorSansar Choinyambuu <schoinya@hsr.ch>
Mon, 31 Oct 2011 15:08:31 +0000 (16:08 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 28 Nov 2011 19:31:13 +0000 (20:31 +0100)
src/libpts/pts/pts.c
src/libstrongswan/credentials/keys/public_key.c
src/libstrongswan/credentials/keys/public_key.h
src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c

index 3d5e233..9c1703d 100644 (file)
@@ -1201,9 +1201,6 @@ METHOD(pts_t, verify_quote_signature, bool,
 {
        public_key_t *aik_pub_key;
        chunk_t key_encoding;
-       EVP_PKEY *pkey = NULL;
-       RSA *rsa = NULL;
-       unsigned char *p;
 
        aik_pub_key = this->aik->get_public_key(this->aik);
        if (!aik_pub_key)
@@ -1228,52 +1225,8 @@ METHOD(pts_t, verify_quote_signature, bool,
                goto cleanup;
        }
        
-       p = key_encoding.ptr;
-       pkey = d2i_PUBKEY(NULL, (const unsigned char**)&p, key_encoding.len);
-       if (!pkey)
-       {
-               DBG1(DBG_PTS, "failed to get EVP_PKEY object from AIK public key");
-               goto cleanup;
-       }
-
-       rsa = EVP_PKEY_get1_RSA(pkey);
-       if (!rsa)
-       {
-               DBG1(DBG_PTS, "failed to get RSA object from EVP_PKEY");
-               goto cleanup;
-       }
-
-       if (RSA_verify(NID_sha1, data.ptr, data.len,
-               signature.ptr, signature.len, rsa) != 1)
-       {
-               DBG1(DBG_PTS, "signature verification failed for TPM Quote Info");
-               goto cleanup;
-       }
-
-       RSA_free(rsa);
-       EVP_PKEY_free(pkey);
-       if (key_encoding.ptr)
-       {
-               chunk_clear(&key_encoding);
-       }
        aik_pub_key->destroy(aik_pub_key);
        return TRUE;
-
-cleanup:
-       if (rsa)
-       {
-               RSA_free(rsa);
-       }
-       if (pkey)
-       {
-               EVP_PKEY_free(pkey);
-       }
-       if (key_encoding.ptr)
-       {
-               chunk_clear(&key_encoding);
-       }
-       DESTROY_IF(aik_pub_key);
-       return FALSE;
 }
 
 METHOD(pts_t, destroy, void,
index 37bba77..9c59ba7 100644 (file)
@@ -26,6 +26,7 @@ ENUM(key_type_names, KEY_ANY, KEY_DSA,
 
 ENUM(signature_scheme_names, SIGN_UNKNOWN, SIGN_ECDSA_521,
        "UNKNOWN",
+       "RSA_SHA1"
        "RSA_EMSA_PKCS1_NULL",
        "RSA_EMSA_PKCS1_MD5",
        "RSA_EMSA_PKCS1_SHA1",
index fdbe17f..303d0b5 100644 (file)
@@ -60,6 +60,8 @@ extern enum_name_t *key_type_names;
 enum signature_scheme_t {
        /** Unknown signature scheme                                       */
        SIGN_UNKNOWN,
+       /** Generic PKCS1_v1.5 signature as in PKCS#1 using RSA and SHA-1  */
+       SIGN_RSA_SHA1,
        /** EMSA-PKCS1_v1.5 signature over digest without digestInfo       */
        SIGN_RSA_EMSA_PKCS1_NULL,
        /** EMSA-PKCS1_v1.5 signature as in PKCS#1 using RSA and MD5       */
index a24bae5..2c9ad2a 100644 (file)
@@ -116,6 +116,64 @@ error:
        return valid;
 }
 
+/**
+ * Verification of an EMPSA PKCS1 signature described in PKCS#1
+ */
+static bool verify_rsa_signature(private_openssl_rsa_public_key_t *this,
+                                                                               int type, chunk_t data, chunk_t signature)
+{
+       bool valid = FALSE;
+       int rsa_size = RSA_size(this->rsa);
+
+       /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */
+       if (signature.len > rsa_size)
+       {
+               signature = chunk_skip(signature, signature.len - rsa_size);
+       }
+
+       if (type == NID_undef)
+       {
+               chunk_t hash = chunk_alloc(rsa_size);
+
+               hash.len = RSA_public_decrypt(signature.len, signature.ptr, hash.ptr,
+                                                                         this->rsa, RSA_PKCS1_PADDING);
+               valid = chunk_equals(data, hash);
+               free(hash.ptr);
+       }
+       else
+       {
+               EVP_PKEY *key;
+               RSA *rsa = NULL;
+
+               key = EVP_PKEY_new();
+               if (!EVP_PKEY_set1_RSA(key, this->rsa))
+               {
+                       goto error;
+               }
+               rsa = EVP_PKEY_get1_RSA(key);
+               if (!rsa)
+               {
+                       goto error;
+               }
+
+               valid = (RSA_verify(type, data.ptr, data.len,
+                                                       signature.ptr, signature.len, rsa) == 1);
+
+error:
+               if (key)
+               {
+                       EVP_PKEY_free(key);
+               }
+               if (rsa)
+               {
+                       RSA_free(rsa);
+               }
+       }
+
+       return valid;
+}
+
+
 METHOD(public_key_t, get_type, key_type_t,
        private_openssl_rsa_public_key_t *this)
 {
@@ -128,6 +186,8 @@ METHOD(public_key_t, verify, bool,
 {
        switch (scheme)
        {
+               case SIGN_RSA_SHA1:
+                       return verify_rsa_signature(this, NID_sha1, data, signature);
                case SIGN_RSA_EMSA_PKCS1_NULL:
                        return verify_emsa_pkcs1_signature(this, NID_undef, data, signature);
                case SIGN_RSA_EMSA_PKCS1_SHA1: