Commit a5b38620 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Backport extended PSS support from HEAD: allow setting of mgf1Hash explicitly.

This is needed to handle FIPS redirection fully.
parent 916bcab2
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -222,12 +222,22 @@ struct rsa_st
	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, \
				pad, NULL)

#define EVP_PKEY_CTX_get_rsa_padding(ctx, ppad) \
	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, \
				EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad)

#define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \
	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \
				(EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
				EVP_PKEY_CTRL_RSA_PSS_SALTLEN, \
				len, NULL)

#define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \
	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \
				(EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
				EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, \
				0, plen)

#define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \
	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, \
				EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
@@ -236,11 +246,24 @@ struct rsa_st
	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, \
				EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp)

#define	 EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md)	\
		EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_SIG,  \
				EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md)

#define	 EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, pmd)	\
		EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_SIG,  \
				EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)pmd)

#define EVP_PKEY_CTRL_RSA_PADDING	(EVP_PKEY_ALG_CTRL + 1)
#define EVP_PKEY_CTRL_RSA_PSS_SALTLEN	(EVP_PKEY_ALG_CTRL + 2)

#define EVP_PKEY_CTRL_RSA_KEYGEN_BITS	(EVP_PKEY_ALG_CTRL + 3)
#define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP	(EVP_PKEY_ALG_CTRL + 4)
#define EVP_PKEY_CTRL_RSA_MGF1_MD	(EVP_PKEY_ALG_CTRL + 5)

#define EVP_PKEY_CTRL_GET_RSA_PADDING		(EVP_PKEY_ALG_CTRL + 6)
#define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN	(EVP_PKEY_ALG_CTRL + 7)
#define EVP_PKEY_CTRL_GET_RSA_MGF1_MD		(EVP_PKEY_ALG_CTRL + 8)

#define RSA_PKCS1_PADDING	1
#define RSA_SSLV23_PADDING	2
@@ -380,6 +403,14 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
			const unsigned char *mHash,
			const EVP_MD *Hash, int sLen);

int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
			const EVP_MD *Hash, const EVP_MD *mgf1Hash, 
			const unsigned char *EM, int sLen);

int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
			const unsigned char *mHash,
			const EVP_MD *Hash, const EVP_MD *mgf1Hash, int sLen);

int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
int RSA_set_ex_data(RSA *r,int idx,void *arg);
@@ -424,6 +455,7 @@ void ERR_load_RSA_strings(void);
#define RSA_F_RSA_PADDING_ADD_NONE			 107
#define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP		 121
#define RSA_F_RSA_PADDING_ADD_PKCS1_PSS			 125
#define RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1		 148
#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1		 108
#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2		 109
#define RSA_F_RSA_PADDING_ADD_SSLV23			 110
@@ -445,6 +477,7 @@ void ERR_load_RSA_strings(void);
#define RSA_F_RSA_VERIFY				 119
#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING		 120
#define RSA_F_RSA_VERIFY_PKCS1_PSS			 126
#define RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1			 149

/* Reason codes. */
#define RSA_R_ALGORITHM_MISMATCH			 100
@@ -470,6 +503,7 @@ void ERR_load_RSA_strings(void);
#define RSA_R_INVALID_HEADER				 137
#define RSA_R_INVALID_KEYBITS				 145
#define RSA_R_INVALID_MESSAGE_LENGTH			 131
#define RSA_R_INVALID_MGF1_MD				 149
#define RSA_R_INVALID_PADDING				 138
#define RSA_R_INVALID_PADDING_MODE			 141
#define RSA_R_INVALID_PSS_SALTLEN			 146
+4 −1
Original line number Diff line number Diff line
/* crypto/rsa/rsa_err.c */
/* ====================================================================
 * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
 * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
@@ -97,6 +97,7 @@ static ERR_STRING_DATA RSA_str_functs[]=
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_NONE),	"RSA_padding_add_none"},
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP),	"RSA_padding_add_PKCS1_OAEP"},
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_PSS),	"RSA_padding_add_PKCS1_PSS"},
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1),	"RSA_padding_add_PKCS1_PSS_mgf1"},
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1),	"RSA_padding_add_PKCS1_type_1"},
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2),	"RSA_padding_add_PKCS1_type_2"},
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_SSLV23),	"RSA_padding_add_SSLv23"},
@@ -118,6 +119,7 @@ static ERR_STRING_DATA RSA_str_functs[]=
{ERR_FUNC(RSA_F_RSA_VERIFY),	"RSA_verify"},
{ERR_FUNC(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING),	"RSA_verify_ASN1_OCTET_STRING"},
{ERR_FUNC(RSA_F_RSA_VERIFY_PKCS1_PSS),	"RSA_verify_PKCS1_PSS"},
{ERR_FUNC(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1),	"RSA_verify_PKCS1_PSS_mgf1"},
{0,NULL}
	};

@@ -146,6 +148,7 @@ static ERR_STRING_DATA RSA_str_reasons[]=
{ERR_REASON(RSA_R_INVALID_HEADER)        ,"invalid header"},
{ERR_REASON(RSA_R_INVALID_KEYBITS)       ,"invalid keybits"},
{ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH),"invalid message length"},
{ERR_REASON(RSA_R_INVALID_MGF1_MD)       ,"invalid mgf1 md"},
{ERR_REASON(RSA_R_INVALID_PADDING)       ,"invalid padding"},
{ERR_REASON(RSA_R_INVALID_PADDING_MODE)  ,"invalid padding mode"},
{ERR_REASON(RSA_R_INVALID_PSS_SALTLEN)   ,"invalid pss saltlen"},
+40 −6
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ typedef struct
	int pad_mode;
	/* message digest */
	const EVP_MD *md;
	/* message digest for MGF1 */
	const EVP_MD *mgf1md;
	/* PSS/OAEP salt length */
	int saltlen;
	/* Temp buffer */
@@ -95,6 +97,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
	rctx->pub_exp = NULL;
	rctx->pad_mode = RSA_PKCS1_PADDING;
	rctx->md = NULL;
	rctx->mgf1md = NULL;
	rctx->tbuf = NULL;

	rctx->saltlen = -2;
@@ -186,8 +189,10 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
			{
			if (!setup_tbuf(rctx, ctx))
				return -1;
			if (!RSA_padding_add_PKCS1_PSS(rsa, rctx->tbuf, tbs,
						rctx->md, rctx->saltlen))
			if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
						rctx->tbuf, tbs,
						rctx->md, rctx->mgf1md,
						rctx->saltlen))
				return -1;
			ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
						sig, rsa, RSA_NO_PADDING);
@@ -289,7 +294,8 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
							rsa, RSA_NO_PADDING);
			if (ret <= 0)
				return 0;
			ret = RSA_verify_PKCS1_PSS(rsa, tbs, rctx->md,
			ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs,
						rctx->md, rctx->mgf1md,
						rctx->tbuf, rctx->saltlen);
			if (ret <= 0)
				return 0;
@@ -403,15 +409,25 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
				RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
		return -2;

		case EVP_PKEY_CTRL_GET_RSA_PADDING:
		*(int *)p2 = rctx->pad_mode;
		return 1;

		case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
		if (p1 < -2)
			return -2;
		case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
		if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING)
			{
			RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
			return -2;
			}
		if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN)
			*(int *)p2 = rctx->saltlen;
		else
			{
			if (p1 < -2)
				return -2;
			rctx->saltlen = p1;
			}
		return 1;

		case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
@@ -435,6 +451,24 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
		rctx->md = p2;
		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)
			{
			RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
			return -2;
			}
		if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD)
			{
			if (rctx->mgf1md)
				*(const EVP_MD **)p2 = rctx->mgf1md;
			else
				*(const EVP_MD **)p2 = rctx->md;
			}
		else
			rctx->mgf1md = p2;
		return 1;

		case EVP_PKEY_CTRL_DIGESTINIT:
		case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
		case EVP_PKEY_CTRL_PKCS7_DECRYPT:
+53 −28
Original line number Diff line number Diff line
@@ -73,6 +73,13 @@ static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0};
int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
			const EVP_MD *Hash, const unsigned char *EM, int sLen)
	{
	return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
	}

int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
			const EVP_MD *Hash, const EVP_MD *mgf1Hash,
			const unsigned char *EM, int sLen)
	{
	int i;
	int ret = 0;
	int hLen, maskedDBLen, MSBits, emLen;
@@ -80,6 +87,10 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
	unsigned char *DB = NULL;
	EVP_MD_CTX ctx;
	unsigned char H_[EVP_MAX_MD_SIZE];
	EVP_MD_CTX_init(&ctx);

	if (mgf1Hash == NULL)
		mgf1Hash = Hash;

	hLen = EVP_MD_size(Hash);
	if (hLen < 0)
@@ -94,7 +105,7 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
	else if (sLen == -2)	sLen = -2;
	else if (sLen < -2)
		{
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
		goto err;
		}

@@ -102,7 +113,7 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
	emLen = RSA_size(rsa);
	if (EM[0] & (0xFF << MSBits))
		{
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_FIRST_OCTET_INVALID);
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID);
		goto err;
		}
	if (MSBits == 0)
@@ -112,12 +123,12 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
		}
	if (emLen < (hLen + sLen + 2)) /* sLen can be small negative */
		{
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_DATA_TOO_LARGE);
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE);
		goto err;
		}
	if (EM[emLen - 1] != 0xbc)
		{
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_LAST_OCTET_INVALID);
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID);
		goto err;
		}
	maskedDBLen = emLen - hLen - 1;
@@ -125,10 +136,10 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
	DB = OPENSSL_malloc(maskedDBLen);
	if (!DB)
		{
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, ERR_R_MALLOC_FAILURE);
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE);
		goto err;
		}
	if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, Hash) < 0)
	if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0)
		goto err;
	for (i = 0; i < maskedDBLen; i++)
		DB[i] ^= EM[i];
@@ -137,25 +148,28 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
	for (i = 0; DB[i] == 0 && i < (maskedDBLen-1); i++) ;
	if (DB[i++] != 0x1)
		{
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_RECOVERY_FAILED);
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED);
		goto err;
		}
	if (sLen >= 0 && (maskedDBLen - i) != sLen)
		{
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
		goto err;
		}
	EVP_MD_CTX_init(&ctx);
	EVP_DigestInit_ex(&ctx, Hash, NULL);
	EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes);
	EVP_DigestUpdate(&ctx, mHash, hLen);
	if (!EVP_DigestInit_ex(&ctx, Hash, NULL)
		|| !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes)
		|| !EVP_DigestUpdate(&ctx, mHash, hLen))
		goto err;
	if (maskedDBLen - i)
		EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i);
	EVP_DigestFinal(&ctx, H_, NULL);
	EVP_MD_CTX_cleanup(&ctx);
		{
		if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i))
			goto err;
		}
	if (!EVP_DigestFinal_ex(&ctx, H_, NULL))
		goto err;
	if (memcmp(H_, H, hLen))
		{
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_BAD_SIGNATURE);
		RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE);
		ret = 0;
		}
	else 
@@ -164,6 +178,7 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
	err:
	if (DB)
		OPENSSL_free(DB);
	EVP_MD_CTX_cleanup(&ctx);

	return ret;

@@ -173,12 +188,22 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
			const unsigned char *mHash,
			const EVP_MD *Hash, int sLen)
	{
	return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen);
	}

int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
			const unsigned char *mHash,
			const EVP_MD *Hash, const EVP_MD *mgf1Hash, int sLen)
	{
	int i;
	int ret = 0;
	int hLen, maskedDBLen, MSBits, emLen;
	unsigned char *H, *salt = NULL, *p;
	EVP_MD_CTX ctx;

	if (mgf1Hash == NULL)
		mgf1Hash = Hash;

	hLen = EVP_MD_size(Hash);
	if (hLen < 0)
		goto err;
@@ -192,7 +217,7 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
	else if (sLen == -2)	sLen = -2;
	else if (sLen < -2)
		{
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
		goto err;
		}

@@ -209,8 +234,7 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
		}
	else if (emLen < (hLen + sLen + 2))
		{
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS,
		   RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
		goto err;
		}
	if (sLen > 0)
@@ -218,8 +242,7 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
		salt = OPENSSL_malloc(sLen);
		if (!salt)
			{
			RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS,
		   		ERR_R_MALLOC_FAILURE);
			RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		if (RAND_bytes(salt, sLen) <= 0)
@@ -228,16 +251,18 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
	maskedDBLen = emLen - hLen - 1;
	H = EM + maskedDBLen;
	EVP_MD_CTX_init(&ctx);
	EVP_DigestInit_ex(&ctx, Hash, NULL);
	EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes);
	EVP_DigestUpdate(&ctx, mHash, hLen);
	if (sLen)
		EVP_DigestUpdate(&ctx, salt, sLen);
	EVP_DigestFinal(&ctx, H, NULL);
	if (!EVP_DigestInit_ex(&ctx, Hash, NULL)
		|| !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes)
		|| !EVP_DigestUpdate(&ctx, mHash, hLen))
		goto err;
	if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen))
		goto err;
	if (!EVP_DigestFinal_ex(&ctx, H, NULL))
		goto err;
	EVP_MD_CTX_cleanup(&ctx);

	/* Generate dbMask in place then perform XOR on it */
	if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, Hash))
	if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash))
		goto err;

	p = EM;