RSA PSS ASN1 signing method
authorDr. Stephen Henson <steve@openssl.org>
Thu, 11 Mar 2010 14:06:46 +0000 (14:06 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 11 Mar 2010 14:06:46 +0000 (14:06 +0000)
CHANGES
crypto/rsa/rsa_ameth.c
crypto/x509/x509.h

diff --git a/CHANGES b/CHANGES
index fad16c1..2c1fd55 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 1.0.0 and 1.1.0  [xx XXX xxxx]
 
+  *) Add RSA PSS signing function. This will generated and set the
+     appropriate AlgorithmIdentifiers for PSS based on those in the
+     corresponding EVP_MD_CTX structure. No application support yet.
+     [Steve Henson]
+
   *) Support for companion algorithm specific ASN1 signing routines.
      New function ASN1_item_sign_ctx() signs a pre-initialised
      EVP_MD_CTX structure and sets AlgorithmIdentifiers based on
index f5c59b2..dcf4a12 100644 (file)
@@ -535,13 +535,13 @@ static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
        if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
                goto err;
 
-       if (!EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING))
+       if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0)
                goto err;
 
-       if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen))
+       if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0)
                goto err;
 
-       if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md))
+       if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
                goto err;
        /* Carry on */
        rv = 2;
@@ -553,6 +553,92 @@ static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
        return rv;
        }
 
+static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+                               X509_ALGOR *alg1, X509_ALGOR *alg2, 
+                               ASN1_BIT_STRING *sig)
+       {
+       int pad_mode;
+       EVP_PKEY_CTX *pkctx = ctx->pctx;
+       if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
+               return 0;
+       if (pad_mode == RSA_PKCS1_PADDING)
+               return 2;
+       if (pad_mode == RSA_PKCS1_PSS_PADDING)
+               {
+               const EVP_MD *sigmd, *mgf1md;
+               RSA_PSS_PARAMS *pss = NULL;
+               X509_ALGOR *mgf1alg = NULL;
+               ASN1_STRING *os1 = NULL, *os2 = NULL;
+               EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
+               int saltlen, rv = 0;
+               sigmd = EVP_MD_CTX_md(ctx);
+               if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
+                       goto err;
+               if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen))
+                       goto err;
+               if (saltlen == -1)
+                       saltlen = EVP_MD_size(sigmd);
+               else if (saltlen == -2)
+                       saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
+               pss = RSA_PSS_PARAMS_new();
+               if (!pss)
+                       goto err;
+               if (saltlen != 20)
+                       {
+                       pss->saltLength = ASN1_INTEGER_new();
+                       if (!pss->saltLength)
+                               goto err;
+                       if (!ASN1_INTEGER_set(pss->saltLength, saltlen))
+                               goto err;
+                       }
+               if (EVP_MD_type(sigmd) != NID_sha1)
+                       {
+                       pss->hashAlgorithm = X509_ALGOR_new();
+                       if (!pss->hashAlgorithm)
+                               goto err;
+                       X509_ALGOR_set_md(pss->hashAlgorithm, sigmd);
+                       }
+               if (EVP_MD_type(mgf1md) != NID_sha1)
+                       {
+                       ASN1_STRING *stmp = NULL;
+                       /* need to embed algorithm ID inside another */
+                       mgf1alg = X509_ALGOR_new();
+                       X509_ALGOR_set_md(mgf1alg, mgf1md);
+                       if (!ASN1_item_pack(mgf1alg, ASN1_ITEM_rptr(X509_ALGOR),
+                                                                       &stmp))
+                                       goto err;
+                       pss->maskGenAlgorithm = X509_ALGOR_new();
+                       if (!pss->maskGenAlgorithm)
+                               goto err;
+                       X509_ALGOR_set0(pss->maskGenAlgorithm,
+                                       OBJ_nid2obj(NID_mgf1),
+                                       V_ASN1_SEQUENCE, stmp);
+                       }
+               /* Finally create string with pss parameter encoding. */
+               if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os1))
+                       goto err;
+               os2 = ASN1_STRING_dup(os1);
+               if (!os2)
+                       goto err;
+               X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_rsassaPss),
+                                       V_ASN1_SEQUENCE, os1);
+               X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_rsassaPss),
+                                       V_ASN1_SEQUENCE, os2);
+               os1 = os2 = NULL;
+               rv = 3;
+               err:
+               if (mgf1alg)
+                       X509_ALGOR_free(mgf1alg);
+               if (pss)
+                       RSA_PSS_PARAMS_free(pss);
+               if (os1)
+                       ASN1_STRING_free(os1);
+               return rv;
+               
+               }
+       return 2;
+       }
+
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] = 
        {
                {
@@ -582,7 +668,8 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
                rsa_pkey_ctrl,
                old_rsa_priv_decode,
                old_rsa_priv_encode,
-               rsa_item_verify
+               rsa_item_verify,
+               rsa_item_sign
                },
 
                {
index 9090f2e..abd526e 100644 (file)
@@ -897,6 +897,9 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
 int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
        ASN1_BIT_STRING *signature,
        void *data, EVP_PKEY *pkey, const EVP_MD *type);
+int ASN1_item_sign_ctx(EVP_MD_CTX *ctx,
+               const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+               ASN1_BIT_STRING *signature, void *asn);
 #endif
 
 int            X509_set_version(X509 *x,long version);