mirror of
https://github.com/openssl/openssl.git
synced 2024-12-04 15:34:41 +08:00
RSA PSS verification support including certificates and certificate
requests. Add new ASN1 signature initialisation function to handle this case.
This commit is contained in:
parent
a4d9c12f99
commit
31904ecdf3
9
CHANGES
9
CHANGES
@ -4,7 +4,14 @@
|
||||
|
||||
Changes between 1.0.0 and 1.1.0 [xx XXX xxxx]
|
||||
|
||||
*) Add signature printing for PSS. Add PSS OIDs.
|
||||
*) Add new algorithm specific ASN1 verification initialisation function
|
||||
to EVP_PKEY_ASN1_METHOD: this is not in EVP_PKEY_METHOD since the ASN1
|
||||
handling will be the same no matter what EVP_PKEY_METHOD is used.
|
||||
Add a PSS handler to support verification of PSS signatures: checked
|
||||
against a number of sample certificates.
|
||||
[Steve Henson]
|
||||
|
||||
*) Add signature printing for PSS. Add PSS OIDs.
|
||||
[Steve Henson, Martin Kaiser <lists@kaiser.cx>]
|
||||
|
||||
*) Add algorithm specific signature printing. An individual ASN1 method
|
||||
|
@ -131,11 +131,10 @@ err:
|
||||
#endif
|
||||
|
||||
|
||||
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signature,
|
||||
void *asn, EVP_PKEY *pkey)
|
||||
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
|
||||
ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
|
||||
{
|
||||
EVP_MD_CTX ctx;
|
||||
const EVP_MD *type = NULL;
|
||||
unsigned char *buf_in=NULL;
|
||||
int ret= -1,inl;
|
||||
|
||||
@ -149,25 +148,47 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
type=EVP_get_digestbynid(mdnid);
|
||||
if (type == NULL)
|
||||
if (mdnid == NID_undef)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
|
||||
goto err;
|
||||
if (!pkey->ameth || !pkey->ameth->item_verify)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
ret = pkey->ameth->item_verify(&ctx, it, asn, a,
|
||||
signature, pkey);
|
||||
/* Return value of 2 means carry on, anything else means we
|
||||
* exit straight away: either a fatal error of the underlying
|
||||
* verification routine handles all verification.
|
||||
*/
|
||||
if (ret != 2)
|
||||
goto err;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Check public key OID matches public key type */
|
||||
if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id)
|
||||
else
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_WRONG_PUBLIC_KEY_TYPE);
|
||||
goto err;
|
||||
}
|
||||
const EVP_MD *type;
|
||||
type=EVP_get_digestbynid(mdnid);
|
||||
if (type == NULL)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check public key OID matches public key type */
|
||||
if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_WRONG_PUBLIC_KEY_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey))
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
|
||||
ret=0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey))
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
|
||||
ret=0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
inl = ASN1_item_i2d(asn, &buf_in, it);
|
||||
|
@ -293,7 +293,6 @@ DECLARE_STACK_OF(ASN1_STRING_TABLE)
|
||||
* see asn1t.h
|
||||
*/
|
||||
typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE;
|
||||
typedef struct ASN1_ITEM_st ASN1_ITEM;
|
||||
typedef struct ASN1_TLC_st ASN1_TLC;
|
||||
/* This is just an opaque pointer */
|
||||
typedef struct ASN1_VALUE_st ASN1_VALUE;
|
||||
|
@ -106,6 +106,7 @@ struct evp_pkey_asn1_method_st
|
||||
const X509_ALGOR *sigalg, const ASN1_STRING *sig,
|
||||
int indent, ASN1_PCTX *pctx);
|
||||
|
||||
|
||||
void (*pkey_free)(EVP_PKEY *pkey);
|
||||
int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
|
||||
|
||||
@ -114,6 +115,10 @@ struct evp_pkey_asn1_method_st
|
||||
int (*old_priv_decode)(EVP_PKEY *pkey,
|
||||
const unsigned char **pder, int derlen);
|
||||
int (*old_priv_encode)(const EVP_PKEY *pkey, unsigned char **pder);
|
||||
/* Custom ASN1 signature verification */
|
||||
int (*item_verify)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
|
||||
X509_ALGOR *a, ASN1_BIT_STRING *sig,
|
||||
EVP_PKEY *pkey);
|
||||
|
||||
} /* EVP_PKEY_ASN1_METHOD */;
|
||||
|
||||
|
@ -96,6 +96,7 @@ typedef int ASN1_BOOLEAN;
|
||||
typedef int ASN1_NULL;
|
||||
#endif
|
||||
|
||||
typedef struct ASN1_ITEM_st ASN1_ITEM;
|
||||
typedef struct asn1_pctx_st ASN1_PCTX;
|
||||
|
||||
#ifdef OPENSSL_SYS_WIN32
|
||||
|
@ -236,12 +236,16 @@ 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, -1, EVP_PKEY_OP_TYPE_SIG, \
|
||||
EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md)
|
||||
|
||||
#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_MGF1_MD (EVP_PKEY_ALG_CTRL + 5)
|
||||
#define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 5)
|
||||
|
||||
#define RSA_PKCS1_PADDING 1
|
||||
#define RSA_SSLV23_PADDING 2
|
||||
@ -424,6 +428,7 @@ void ERR_load_RSA_strings(void);
|
||||
#define RSA_F_RSA_EAY_PUBLIC_DECRYPT 103
|
||||
#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT 104
|
||||
#define RSA_F_RSA_GENERATE_KEY 105
|
||||
#define RSA_F_RSA_ITEM_VERIFY 148
|
||||
#define RSA_F_RSA_MEMORY_LOCK 130
|
||||
#define RSA_F_RSA_NEW_METHOD 106
|
||||
#define RSA_F_RSA_NULL 124
|
||||
@ -483,7 +488,9 @@ void ERR_load_RSA_strings(void);
|
||||
#define RSA_R_INVALID_MESSAGE_LENGTH 131
|
||||
#define RSA_R_INVALID_PADDING 138
|
||||
#define RSA_R_INVALID_PADDING_MODE 141
|
||||
#define RSA_R_INVALID_PSS_PARAMETERS 149
|
||||
#define RSA_R_INVALID_PSS_SALTLEN 146
|
||||
#define RSA_R_INVALID_SALT_LENGTH 150
|
||||
#define RSA_R_INVALID_TRAILER 139
|
||||
#define RSA_R_INVALID_X931_DIGEST 142
|
||||
#define RSA_R_IQMP_NOT_INVERSE_OF_Q 126
|
||||
@ -504,7 +511,12 @@ void ERR_load_RSA_strings(void);
|
||||
#define RSA_R_SSLV3_ROLLBACK_ATTACK 115
|
||||
#define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116
|
||||
#define RSA_R_UNKNOWN_ALGORITHM_TYPE 117
|
||||
#define RSA_R_UNKNOWN_MASK_DIGEST 151
|
||||
#define RSA_R_UNKNOWN_PADDING_TYPE 118
|
||||
#define RSA_R_UNKNOWN_PSS_DIGEST 152
|
||||
#define RSA_R_UNSUPPORTED_MASK_ALGORITHM 153
|
||||
#define RSA_R_UNSUPPORTED_MASK_PARAMETER 154
|
||||
#define RSA_R_UNSUPPORTED_SIGNATURE_TYPE 155
|
||||
#define RSA_R_VALUE_MISSING 147
|
||||
#define RSA_R_WRONG_SIGNATURE_LENGTH 119
|
||||
|
||||
|
@ -449,6 +449,109 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
||||
|
||||
}
|
||||
|
||||
/* Customised RSA item verification routine. This is called
|
||||
* when a signature is encountered requiring special handling. We
|
||||
* currently only handle PSS.
|
||||
*/
|
||||
|
||||
|
||||
static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
|
||||
X509_ALGOR *sigalg, ASN1_BIT_STRING *sig,
|
||||
EVP_PKEY *pkey)
|
||||
{
|
||||
int rv = -1;
|
||||
int saltlen;
|
||||
const EVP_MD *mgf1md = NULL, *md = NULL;
|
||||
RSA_PSS_PARAMS *pss;
|
||||
X509_ALGOR *maskHash;
|
||||
EVP_PKEY_CTX *pkctx;
|
||||
/* Sanity check: make sure it is PSS */
|
||||
if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
|
||||
return -1;
|
||||
}
|
||||
/* Decode PSS parameters */
|
||||
pss = rsa_pss_decode(sigalg, &maskHash);
|
||||
|
||||
if (pss == NULL)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_PSS_PARAMETERS);
|
||||
goto err;
|
||||
}
|
||||
/* Check mask and lookup mask hash algorithm */
|
||||
if (pss->maskGenAlgorithm)
|
||||
{
|
||||
if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) != NID_mgf1)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
if (!maskHash)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_PARAMETER);
|
||||
goto err;
|
||||
}
|
||||
mgf1md = EVP_get_digestbyobj(maskHash->algorithm);
|
||||
if (mgf1md == NULL)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_MASK_DIGEST);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
mgf1md = EVP_sha1();
|
||||
|
||||
if (pss->hashAlgorithm)
|
||||
{
|
||||
md = EVP_get_digestbyobj(maskHash->algorithm);
|
||||
if (md == NULL)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_PSS_DIGEST);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
md = EVP_sha1();
|
||||
|
||||
if (pss->saltLength)
|
||||
{
|
||||
saltlen = ASN1_INTEGER_get(pss->saltLength);
|
||||
|
||||
/* Could perform more salt length sanity checks but the main
|
||||
* RSA routines will trap other invalid values anyway.
|
||||
*/
|
||||
if (saltlen < 0)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_SALT_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
saltlen = 20;
|
||||
|
||||
/* We have all parameters now set up context */
|
||||
|
||||
if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
|
||||
goto err;
|
||||
|
||||
if (!EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING))
|
||||
goto err;
|
||||
|
||||
if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen))
|
||||
goto err;
|
||||
|
||||
if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md))
|
||||
goto err;
|
||||
/* Carry on */
|
||||
rv = 2;
|
||||
|
||||
err:
|
||||
RSA_PSS_PARAMS_free(pss);
|
||||
if (maskHash)
|
||||
X509_ALGOR_free(maskHash);
|
||||
return rv;
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
|
||||
{
|
||||
@ -478,7 +581,8 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
|
||||
int_rsa_free,
|
||||
rsa_pkey_ctrl,
|
||||
old_rsa_priv_decode,
|
||||
old_rsa_priv_encode
|
||||
old_rsa_priv_encode,
|
||||
rsa_item_verify
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* crypto/rsa/rsa_err.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved.
|
||||
* Copyright (c) 1999-2010 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
|
||||
@ -86,6 +86,7 @@ static ERR_STRING_DATA RSA_str_functs[]=
|
||||
{ERR_FUNC(RSA_F_RSA_EAY_PUBLIC_DECRYPT), "RSA_EAY_PUBLIC_DECRYPT"},
|
||||
{ERR_FUNC(RSA_F_RSA_EAY_PUBLIC_ENCRYPT), "RSA_EAY_PUBLIC_ENCRYPT"},
|
||||
{ERR_FUNC(RSA_F_RSA_GENERATE_KEY), "RSA_generate_key"},
|
||||
{ERR_FUNC(RSA_F_RSA_ITEM_VERIFY), "RSA_ITEM_VERIFY"},
|
||||
{ERR_FUNC(RSA_F_RSA_MEMORY_LOCK), "RSA_memory_lock"},
|
||||
{ERR_FUNC(RSA_F_RSA_NEW_METHOD), "RSA_new_method"},
|
||||
{ERR_FUNC(RSA_F_RSA_NULL), "RSA_NULL"},
|
||||
@ -148,7 +149,9 @@ static ERR_STRING_DATA RSA_str_reasons[]=
|
||||
{ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH),"invalid message length"},
|
||||
{ERR_REASON(RSA_R_INVALID_PADDING) ,"invalid padding"},
|
||||
{ERR_REASON(RSA_R_INVALID_PADDING_MODE) ,"invalid padding mode"},
|
||||
{ERR_REASON(RSA_R_INVALID_PSS_PARAMETERS),"invalid pss parameters"},
|
||||
{ERR_REASON(RSA_R_INVALID_PSS_SALTLEN) ,"invalid pss saltlen"},
|
||||
{ERR_REASON(RSA_R_INVALID_SALT_LENGTH) ,"invalid salt length"},
|
||||
{ERR_REASON(RSA_R_INVALID_TRAILER) ,"invalid trailer"},
|
||||
{ERR_REASON(RSA_R_INVALID_X931_DIGEST) ,"invalid x931 digest"},
|
||||
{ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) ,"iqmp not inverse of q"},
|
||||
@ -169,7 +172,12 @@ static ERR_STRING_DATA RSA_str_reasons[]=
|
||||
{ERR_REASON(RSA_R_SSLV3_ROLLBACK_ATTACK) ,"sslv3 rollback attack"},
|
||||
{ERR_REASON(RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD),"the asn1 object identifier is not known for this md"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_ALGORITHM_TYPE),"unknown algorithm type"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_MASK_DIGEST) ,"unknown mask digest"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_PADDING_TYPE) ,"unknown padding type"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_PSS_DIGEST) ,"unknown pss digest"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_MASK_ALGORITHM),"unsupported mask algorithm"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_MASK_PARAMETER),"unsupported mask parameter"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_SIGNATURE_TYPE),"unsupported signature type"},
|
||||
{ERR_REASON(RSA_R_VALUE_MISSING) ,"value missing"},
|
||||
{ERR_REASON(RSA_R_WRONG_SIGNATURE_LENGTH),"wrong signature length"},
|
||||
{0,NULL}
|
||||
|
@ -444,7 +444,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
rctx->md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_MGF1_MD:
|
||||
case EVP_PKEY_CTRL_RSA_MGF1_MD:
|
||||
rctx->mgf1md = p2;
|
||||
return 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user