Harmonize Tru64 and Linux make rules.
[oweals/openssl.git] / crypto / rsa / rsa_pmeth.c
index 5b2ecf56adc7343b8661ac4c9c4222a00dde5a10..7fe1b62ce3377a03037ec51f52085b23ce143be8 100644 (file)
@@ -63,6 +63,7 @@
 #include <openssl/rsa.h>
 #include <openssl/bn.h>
 #include <openssl/evp.h>
+#include <openssl/x509v3.h>
 #ifndef OPENSSL_NO_CMS
 #include <openssl/cms.h>
 #endif
@@ -87,10 +88,13 @@ typedef struct
        const EVP_MD *md;
        /* message digest for MGF1 */
        const EVP_MD *mgf1md;
-       /* PSS/OAEP salt length */
+       /* PSS salt length */
        int saltlen;
        /* Temp buffer */
        unsigned char *tbuf;
+       /* OAEP label */
+       unsigned char *oaep_label;
+       size_t oaep_labellen;
        } RSA_PKEY_CTX;
 
 static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
@@ -108,6 +112,9 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
 
        rctx->saltlen = -2;
 
+       rctx->oaep_label = NULL;
+       rctx->oaep_labellen = 0;
+
        ctx->data = rctx;
        ctx->keygen_info = rctx->gentmp;
        ctx->keygen_info_count = 2;
@@ -131,6 +138,17 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
                }
        dctx->pad_mode = sctx->pad_mode;
        dctx->md = sctx->md;
+       dctx->mgf1md = sctx->mgf1md;
+       if (sctx->oaep_label)
+               {
+               if (dctx->oaep_label)
+                       OPENSSL_free(dctx->oaep_label);
+               dctx->oaep_label = BUF_memdup(sctx->oaep_label,
+                                               sctx->oaep_labellen);
+               if (!dctx->oaep_label)
+                       return 0;
+               dctx->oaep_labellen = sctx->oaep_labellen;
+               }
        return 1;
        }
 
@@ -153,6 +171,8 @@ static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
                        BN_free(rctx->pub_exp);
                if (rctx->tbuf)
                        OPENSSL_free(rctx->tbuf);
+               if (rctx->oaep_label)
+                       OPENSSL_free(rctx->oaep_label);
                OPENSSL_free(rctx);
                }
        }
@@ -174,10 +194,20 @@ static int pkey_fips_check_ctx(EVP_PKEY_CTX *ctx)
                rv = 0;
        if (!(rsa->meth->flags & RSA_FLAG_FIPS_METHOD) && rv)
                return -1;
-       if (rctx->md && !(rctx->md->flags & EVP_MD_FLAG_FIPS))
-               return rv;
+       if (rctx->md)
+               {
+               const EVP_MD *fmd;
+               fmd = FIPS_get_digestbynid(EVP_MD_type(rctx->md));
+               if (!fmd || !(fmd->flags & EVP_MD_FLAG_FIPS))
+                       return rv;
+               }
        if (rctx->mgf1md && !(rctx->mgf1md->flags & EVP_MD_FLAG_FIPS))
-               return rv;
+               {
+               const EVP_MD *fmd;
+               fmd = FIPS_get_digestbynid(EVP_MD_type(rctx->mgf1md));
+               if (!fmd || !(fmd->flags & EVP_MD_FLAG_FIPS))
+                       return rv;
+               }
        return 1;
        }
 #endif
@@ -411,7 +441,6 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
        return 1;
                        
        }
-       
 
 static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
                                        unsigned char *out, size_t *outlen,
@@ -419,7 +448,23 @@ static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
        {
        int ret;
        RSA_PKEY_CTX *rctx = ctx->data;
-       ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
+       if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING)
+               {
+               int klen = RSA_size(ctx->pkey->pkey.rsa);
+               if (!setup_tbuf(rctx, ctx))
+                       return -1;
+               if (!RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, klen,
+                                                       in, inlen,
+                                                       rctx->oaep_label,
+                                                       rctx->oaep_labellen,
+                                                       rctx->md, rctx->mgf1md))
+                       return -1;
+               ret = RSA_public_encrypt(klen, rctx->tbuf, out,
+                                               ctx->pkey->pkey.rsa,
+                                               RSA_NO_PADDING);
+               }
+       else
+               ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
                                                        rctx->pad_mode);
        if (ret < 0)
                return ret;
@@ -433,7 +478,29 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
        {
        int ret;
        RSA_PKEY_CTX *rctx = ctx->data;
-       ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
+       if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING)
+               {
+               int i;
+               if (!setup_tbuf(rctx, ctx))
+                       return -1;
+               ret = RSA_private_decrypt(inlen, in, rctx->tbuf,
+                                                       ctx->pkey->pkey.rsa,
+                                                       RSA_NO_PADDING);
+               if (ret <= 0)
+                       return ret;
+               for (i = 0; i < ret; i++)
+                       {
+                       if (rctx->tbuf[i])
+                               break;
+                       }
+               ret = RSA_padding_check_PKCS1_OAEP_mgf1(out,ret,rctx->tbuf + i,
+                                                       ret - i, ret,
+                                                       rctx->oaep_label,
+                                                       rctx->oaep_labellen,
+                                                       rctx->md, rctx->mgf1md);
+               }
+       else 
+               ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
                                                        rctx->pad_mode);
        if (ret < 0)
                return ret;
@@ -533,18 +600,37 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
                if (!p2)
                        return -2;
+               BN_free(rctx->pub_exp);
                rctx->pub_exp = p2;
                return 1;
 
+               case EVP_PKEY_CTRL_RSA_OAEP_MD:
+               case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
+               if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING)
+                       {
+                       RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
+                       return -2;
+                       }
+               if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD)
+                       *(const EVP_MD **)p2 = rctx->md;
+               else
+                       rctx->md = p2;
+               return 1;
+
                case EVP_PKEY_CTRL_MD:
                if (!check_padding_md(p2, rctx->pad_mode))
                        return 0;
                rctx->md = p2;
                return 1;
 
+               case EVP_PKEY_CTRL_GET_MD:
+               *(const EVP_MD **)p2 = rctx->md;
+               return 1;
+
                case EVP_PKEY_CTRL_RSA_MGF1_MD:
                case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
-               if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING)
+               if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING
+                       && rctx->pad_mode != RSA_PKCS1_OAEP_PADDING)
                        {
                        RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
                        return -2;
@@ -560,6 +646,35 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                        rctx->mgf1md = p2;
                return 1;
 
+               case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
+               if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING)
+                       {
+                       RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
+                       return -2;
+                       }
+               if (rctx->oaep_label)
+                       OPENSSL_free(rctx->oaep_label);
+               if (p2 && p1 > 0)
+                       {
+                       rctx->oaep_label = p2;
+                       rctx->oaep_labellen = p1;
+                       }
+               else
+                       {
+                       rctx->oaep_label = NULL;
+                       rctx->oaep_labellen = 0;
+                       }
+               return 1;
+
+               case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
+               if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING)
+                       {
+                       RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
+                       return -2;
+                       }
+               *(unsigned char **)p2 = rctx->oaep_label;
+               return rctx->oaep_labellen;
+
                case EVP_PKEY_CTRL_DIGESTINIT:
                case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
                case EVP_PKEY_CTRL_PKCS7_DECRYPT:
@@ -567,16 +682,6 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                return 1;
 #ifndef OPENSSL_NO_CMS
                case EVP_PKEY_CTRL_CMS_DECRYPT:
-               {
-               X509_ALGOR *alg = NULL;
-               ASN1_OBJECT *encalg = NULL;
-               if (p2)
-                       CMS_RecipientInfo_ktri_get0_algs(p2, NULL, NULL, &alg);
-               if (alg)
-                       X509_ALGOR_get0(&encalg, NULL, NULL, alg);
-               if (encalg && OBJ_obj2nid(encalg) == NID_rsaesOaep)
-                       rctx->pad_mode = RSA_PKCS1_OAEP_PADDING;
-               }
                case EVP_PKEY_CTRL_CMS_ENCRYPT:
                case EVP_PKEY_CTRL_CMS_SIGN:
                return 1;
@@ -611,6 +716,8 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
                        pm = RSA_NO_PADDING;
                else if (!strcmp(value, "oeap"))
                        pm = RSA_PKCS1_OAEP_PADDING;
+               else if (!strcmp(value, "oaep"))
+                       pm = RSA_PKCS1_OAEP_PADDING;
                else if (!strcmp(value, "x931"))
                        pm = RSA_X931_PADDING;
                else if (!strcmp(value, "pss"))
@@ -650,6 +757,43 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
                return ret;
                }
 
+       if (!strcmp(type, "rsa_mgf1_md"))
+               {
+               const EVP_MD *md;
+               if (!(md = EVP_get_digestbyname(value)))
+                       {
+                       RSAerr(RSA_F_PKEY_RSA_CTRL_STR,
+                                               RSA_R_INVALID_DIGEST);
+                       return 0;
+                       }
+               return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
+               }
+
+       if (!strcmp(type, "rsa_oaep_md"))
+               {
+               const EVP_MD *md;
+               if (!(md = EVP_get_digestbyname(value)))
+                       {
+                       RSAerr(RSA_F_PKEY_RSA_CTRL_STR,
+                                               RSA_R_INVALID_DIGEST);
+                       return 0;
+                       }
+               return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md);
+               }
+       if (!strcmp(type, "rsa_oaep_label"))
+               {
+               unsigned char *lab;
+               long lablen;
+               int ret;
+               lab = string_to_hex(value, &lablen);
+               if (!lab)
+                       return 0;
+               ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
+               if (ret <= 0)
+                       OPENSSL_free(lab);
+               return ret;
+               }
+
        return -2;
        }