Changes between 1.0.0e and 1.0.1 [xx XXX xxxx]
+ *) New -sigopt option to the ca, req and x509 utilities. Additional
+ signature parameters can be passed using this option and in
+ particular PSS.
+ [Steve Henson]
+
+ *) Add RSA PSS signing function. This will generate 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
+ the appropriate parameters.
+ [Steve Henson]
+
+ *) 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
+ can now print out signatures instead of the standard hex dump.
+
+ More complex signatures (e.g. PSS) can print out more meaningful
+ information. Include DSA version that prints out the signature
+ parameters r, s.
+ [Steve Henson]
+
*) Password based recipient info support for CMS library: implementing
RFC3211.
[Steve Henson]
int pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value);
int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx,
const char *algname, ENGINE *e, int do_param);
+int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
#ifndef OPENSSL_NO_PSK
extern char *psk_key;
#endif
static void lookup_fail(const char *name, const char *tag);
static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
- const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db,
+ const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy,CA_DB *db,
BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate,
char *enddate, long days, int batch, char *ext_sect, CONF *conf,
int verbose, unsigned long certopt, unsigned long nameopt,
int default_op, int ext_copy, int selfsign);
static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
- const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
+ const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy,
CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn,
char *startdate, char *enddate, long days, int batch,
char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy,
ENGINE *e);
static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
- const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
+ const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy,
CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn,
char *startdate, char *enddate, long days, char *ext_sect,
CONF *conf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy);
static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn,
int email_dn, char *startdate, char *enddate, long days, int batch,
int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
const EVP_MD *dgst=NULL;
STACK_OF(CONF_VALUE) *attribs=NULL;
STACK_OF(X509) *cert_sk=NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL;
#undef BSIZE
#define BSIZE 256
MS_STATIC char buf[3][BSIZE];
if (--argc < 1) goto bad;
outdir= *(++argv);
}
+ else if (strcmp(*argv,"-sigopt") == 0)
+ {
+ if (--argc < 1)
+ goto bad;
+ if (!sigopts)
+ sigopts = sk_OPENSSL_STRING_new_null();
+ if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
+ goto bad;
+ }
else if (strcmp(*argv,"-notext") == 0)
notext=1;
else if (strcmp(*argv,"-batch") == 0)
if (spkac_file != NULL)
{
total++;
- j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
- serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,extensions,
+ j=certify_spkac(&x,spkac_file,pkey,x509,dgst,sigopts,
+ attribs,db, serial,subj,chtype,multirdn,
+ email_dn,startdate,enddate,days,extensions,
conf,verbose,certopt,nameopt,default_op,ext_copy);
if (j < 0) goto err;
if (j > 0)
if (ss_cert_file != NULL)
{
total++;
- j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
+ j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,sigopts,
+ attribs,
db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, e);
if (infile != NULL)
{
total++;
- j=certify(&x,infile,pkey,x509p,dgst,attribs,db,
+ j=certify(&x,infile,pkey,x509p,dgst,sigopts, attribs,db,
serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, selfsign);
for (i=0; i<argc; i++)
{
total++;
- j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db,
+ j=certify(&x,argv[i],pkey,x509p,dgst,sigopts,attribs,db,
serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, selfsign);
crlnumber = NULL;
}
- if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
+ if (!do_X509_CRL_sign(bio_err,crl,pkey,dgst,sigopts)) goto err;
PEM_write_bio_X509_CRL(Sout,crl);
BN_free(serial);
BN_free(crlnumber);
free_index(db);
+ if (sigopts)
+ sk_OPENSSL_STRING_free(sigopts);
EVP_PKEY_free(pkey);
if (x509) X509_free(x509);
X509_CRL_free(crl);
}
static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
- BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ BIGNUM *serial, char *subj,unsigned long chtype, int multirdn,
+ int email_dn, char *startdate, char *enddate,
long days, int batch, char *ext_sect, CONF *lconf, int verbose,
unsigned long certopt, unsigned long nameopt, int default_op,
int ext_copy, int selfsign)
else
BIO_printf(bio_err,"Signature ok\n");
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn, email_dn,
+ ok=do_body(xret,pkey,x509,dgst,sigopts, policy,db,serial,subj,chtype,
+ multirdn, email_dn,
startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
certopt, nameopt, default_op, ext_copy, selfsign);
}
static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
long days, int batch, char *ext_sect, CONF *lconf, int verbose,
unsigned long certopt, unsigned long nameopt, int default_op,
if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
goto err;
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
+ ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
ext_copy, 0);
}
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
- STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,
+ STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy,
+ CA_DB *db, BIGNUM *serial, char *subj,
unsigned long chtype, int multirdn,
int email_dn, char *startdate, char *enddate, long days, int batch,
int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
EVP_PKEY_copy_parameters(pktmp,pkey);
EVP_PKEY_free(pktmp);
- if (!X509_sign(ret,pkey,dgst))
+ if (!do_X509_sign(bio_err, ret,pkey,dgst, sigopts))
goto err;
/* We now just add it to the database */
}
static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy)
X509_REQ_set_pubkey(req,pktmp);
EVP_PKEY_free(pktmp);
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
- days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
- ext_copy, 0);
+ ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,
+ multirdn,email_dn,startdate,enddate, days,1,verbose,req,
+ ext_sect,lconf, certopt, nameopt, default_op, ext_copy, 0);
err:
if (req != NULL) X509_REQ_free(req);
if (parms != NULL) CONF_free(parms);
EVP_PKEY_CTX *genctx = NULL;
const char *keyalg = NULL;
char *keyalgstr = NULL;
- STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
+ STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
EVP_PKEY *pkey=NULL;
int i=0,badops=0,newreq=0,verbose=0,pkey_type=-1;
long newkey = -1;
if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, *(++argv)))
goto bad;
}
+ else if (strcmp(*argv,"-sigopt") == 0)
+ {
+ if (--argc < 1)
+ goto bad;
+ if (!sigopts)
+ sigopts = sk_OPENSSL_STRING_new_null();
+ if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
+ goto bad;
+ }
else if (strcmp(*argv,"-batch") == 0)
batch=1;
else if (strcmp(*argv,"-newhdr") == 0)
extensions);
goto end;
}
-
- if (!(i=X509_sign(x509ss,pkey,digest)))
+
+ i=do_X509_sign(bio_err, x509ss, pkey, digest, sigopts);
+ if (!i)
{
ERR_print_errors(bio_err);
goto end;
req_exts);
goto end;
}
- if (!(i=X509_REQ_sign(req,pkey,digest)))
+ i=do_X509_REQ_sign(bio_err, req, pkey, digest, sigopts);
+ if (!i)
{
ERR_print_errors(bio_err);
goto end;
EVP_PKEY_CTX_free(genctx);
if (pkeyopts)
sk_OPENSSL_STRING_free(pkeyopts);
+ if (sigopts)
+ sk_OPENSSL_STRING_free(sigopts);
#ifndef OPENSSL_NO_ENGINE
if (gen_eng)
ENGINE_free(gen_eng);
#endif
return 1;
}
+
+static int do_sign_init(BIO *err, EVP_MD_CTX *ctx, EVP_PKEY *pkey,
+ const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts)
+ {
+ EVP_PKEY_CTX *pkctx = NULL;
+ int i;
+ EVP_MD_CTX_init(ctx);
+ if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
+ return 0;
+ for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++)
+ {
+ char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+ if (pkey_ctrl_string(pkctx, sigopt) <= 0)
+ {
+ BIO_printf(err, "parameter error \"%s\"\n", sigopt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+ {
+ int rv;
+ EVP_MD_CTX mctx;
+ EVP_MD_CTX_init(&mctx);
+ rv = do_sign_init(err, &mctx, pkey, md, sigopts);
+ if (rv > 0)
+ rv = X509_sign_ctx(x, &mctx);
+ EVP_MD_CTX_cleanup(&mctx);
+ return rv > 0 ? 1 : 0;
+ }
+
+
+int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+ {
+ int rv;
+ EVP_MD_CTX mctx;
+ EVP_MD_CTX_init(&mctx);
+ rv = do_sign_init(err, &mctx, pkey, md, sigopts);
+ if (rv > 0)
+ rv = X509_REQ_sign_ctx(x, &mctx);
+ EVP_MD_CTX_cleanup(&mctx);
+ return rv > 0 ? 1 : 0;
+ }
+
+
+
+int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+ {
+ int rv;
+ EVP_MD_CTX mctx;
+ EVP_MD_CTX_init(&mctx);
+ rv = do_sign_init(err, &mctx, pkey, md, sigopts);
+ if (rv > 0)
+ rv = X509_CRL_sign_ctx(x, &mctx);
+ EVP_MD_CTX_cleanup(&mctx);
+ return rv > 0 ? 1 : 0;
+ }
+
+
static int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
CONF *conf, char *section);
static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
- X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
- int create,int days, int clrext, CONF *conf, char *section,
- ASN1_INTEGER *sno);
+ X509 *x,X509 *xca,EVP_PKEY *pkey,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ char *serial, int create ,int days, int clrext,
+ CONF *conf, char *section, ASN1_INTEGER *sno);
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
static int reqfile=0;
X509_REQ *req=NULL;
X509 *x=NULL,*xca=NULL;
ASN1_OBJECT *objtmp;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL;
EVP_PKEY *Upkey=NULL,*CApkey=NULL;
ASN1_INTEGER *sno = NULL;
int i,num,badops=0;
if (--argc < 1) goto bad;
CAkeyformat=str2fmt(*(++argv));
}
+ else if (strcmp(*argv,"-sigopt") == 0)
+ {
+ if (--argc < 1)
+ goto bad;
+ if (!sigopts)
+ sigopts = sk_OPENSSL_STRING_new_null();
+ if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
+ goto bad;
+ }
else if (strcmp(*argv,"-days") == 0)
{
if (--argc < 1) goto bad;
assert(need_rand);
if (!x509_certify(ctx,CAfile,digest,x,xca,
- CApkey, CAserial,CA_createserial,days, clrext,
+ CApkey, sigopts,
+ CAserial,CA_createserial,days, clrext,
extconf, extsect, sno))
goto end;
}
X509_free(xca);
EVP_PKEY_free(Upkey);
EVP_PKEY_free(CApkey);
+ if (sigopts)
+ sk_OPENSSL_STRING_free(sigopts);
X509_REQ_free(rq);
ASN1_INTEGER_free(sno);
sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
}
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
- X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
- int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
+ X509 *x, X509 *xca, EVP_PKEY *pkey,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ char *serialfile, int create,
+ int days, int clrext, CONF *conf, char *section,
+ ASN1_INTEGER *sno)
{
int ret=0;
ASN1_INTEGER *bs=NULL;
if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
}
- if (!X509_sign(x,pkey,digest)) goto end;
+ if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
+ goto end;
ret=1;
end:
X509_STORE_CTX_cleanup(&xsc);
const EVP_MD *type)
{
EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+ if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey))
+ {
+ EVP_MD_CTX_cleanup(&ctx);
+ return 0;
+ }
+ return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
+ }
+
+
+int ASN1_item_sign_ctx(const ASN1_ITEM *it,
+ X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
+ {
+ const EVP_MD *type;
+ EVP_PKEY *pkey;
unsigned char *buf_in=NULL,*buf_out=NULL;
- int inl=0,outl=0,outll=0;
+ size_t inl=0,outl=0,outll=0;
int signid, paramtype;
+ int rv;
- if (type == NULL)
+ type = EVP_MD_CTX_md(ctx);
+ pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+
+ if (!type || !pkey)
{
- int def_nid;
- if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
- type = EVP_get_digestbynid(def_nid);
+ ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
+ return 0;
}
- if (type == NULL)
+ if (pkey->ameth->item_sign)
{
- ASN1err(ASN1_F_ASN1_ITEM_SIGN, ASN1_R_NO_DEFAULT_DIGEST);
- return 0;
+ rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
+ signature);
+ if (rv == 1)
+ outl = signature->length;
+ /* Return value meanings:
+ * <=0: error.
+ * 1: method does everything.
+ * 2: carry on as normal.
+ * 3: ASN1 method sets algorithm identifiers: just sign.
+ */
+ if (rv <= 0)
+ ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
+ if (rv <= 1)
+ goto err;
}
+ else
+ rv = 2;
- if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
+ if (rv == 2)
{
- if (!pkey->ameth ||
- !OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type),
- pkey->ameth->pkey_id))
+ if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
{
- ASN1err(ASN1_F_ASN1_ITEM_SIGN,
- ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
- return 0;
+ if (!pkey->ameth ||
+ !OBJ_find_sigid_by_algs(&signid,
+ EVP_MD_nid(type),
+ pkey->ameth->pkey_id))
+ {
+ ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
+ ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+ return 0;
+ }
}
- }
- else
- signid = type->pkey_type;
+ else
+ signid = type->pkey_type;
- if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
- paramtype = V_ASN1_NULL;
- else
- paramtype = V_ASN1_UNDEF;
+ if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
+ paramtype = V_ASN1_NULL;
+ else
+ paramtype = V_ASN1_UNDEF;
- if (algor1)
- X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
- if (algor2)
- X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);
+ if (algor1)
+ X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
+ if (algor2)
+ X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);
+
+ }
- EVP_MD_CTX_init(&ctx);
inl=ASN1_item_i2d(asn,&buf_in, it);
outll=outl=EVP_PKEY_size(pkey);
- buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
+ buf_out=OPENSSL_malloc((unsigned int)outl);
if ((buf_in == NULL) || (buf_out == NULL))
{
outl=0;
- ASN1err(ASN1_F_ASN1_ITEM_SIGN,ERR_R_MALLOC_FAILURE);
+ ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!EVP_SignInit_ex(&ctx,type, NULL)
- || !EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl)
- || !EVP_SignFinal(&ctx,(unsigned char *)buf_out,
- (unsigned int *)&outl,pkey))
+ if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
+ || !EVP_DigestSignFinal(ctx, buf_out, &outl))
{
outl=0;
- ASN1err(ASN1_F_ASN1_ITEM_SIGN,ERR_R_EVP_LIB);
+ ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,ERR_R_EVP_LIB);
goto err;
}
if (signature->data != NULL) OPENSSL_free(signature->data);
signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
err:
- EVP_MD_CTX_cleanup(&ctx);
+ EVP_MD_CTX_cleanup(ctx);
if (buf_in != NULL)
{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
if (buf_out != NULL)
#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;
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_VerifyInit_ex(&ctx,type, NULL))
- {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
- ret=0;
- goto err;
}
inl = ASN1_item_i2d(asn, &buf_in, it);
goto err;
}
- if (!EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl))
+ if (!EVP_DigestVerifyUpdate(&ctx,buf_in,inl))
{
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
ret=0;
OPENSSL_cleanse(buf_in,(unsigned int)inl);
OPENSSL_free(buf_in);
- if (EVP_VerifyFinal(&ctx,(unsigned char *)signature->data,
- (unsigned int)signature->length,pkey) <= 0)
+ if (EVP_DigestVerifyFinal(&ctx,signature->data,
+ (size_t)signature->length) <= 0)
{
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
ret=0;
*/
#define ASN1_STRING_FLAG_MSTRING 0x040
/* This is the base type that holds just about everything :-) */
-typedef struct asn1_string_st
+struct asn1_string_st
{
int length;
int type;
* input data has a non-zero 'unused bits' value, it will be
* handled correctly */
long flags;
- } ASN1_STRING;
+ };
/* ASN1_ENCODING structure: this is used to save the received
* encoding of an ASN1 type. This is useful to get round
* 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;
#define ASN1_F_ASN1_ITEM_I2D_FP 193
#define ASN1_F_ASN1_ITEM_PACK 198
#define ASN1_F_ASN1_ITEM_SIGN 195
+#define ASN1_F_ASN1_ITEM_SIGN_CTX 220
#define ASN1_F_ASN1_ITEM_UNPACK 199
#define ASN1_F_ASN1_ITEM_VERIFY 197
#define ASN1_F_ASN1_MBSTRING_NCOPY 122
#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106
#define ASN1_R_BUFFER_TOO_SMALL 107
#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108
+#define ASN1_R_CONTEXT_NOT_INITIALISED 217
#define ASN1_R_DATA_IS_WRONG 109
#define ASN1_R_DECODE_ERROR 110
#define ASN1_R_DECODING_ERROR 111
{ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_FP), "ASN1_item_i2d_fp"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_PACK), "ASN1_item_pack"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN), "ASN1_item_sign"},
+{ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN_CTX), "ASN1_item_sign_ctx"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_UNPACK), "ASN1_item_unpack"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY), "ASN1_item_verify"},
{ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY), "ASN1_mbstring_ncopy"},
{ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH),"boolean is wrong length"},
{ERR_REASON(ASN1_R_BUFFER_TOO_SMALL) ,"buffer too small"},
{ERR_REASON(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER),"cipher has no object identifier"},
+{ERR_REASON(ASN1_R_CONTEXT_NOT_INITIALISED),"context not initialised"},
{ERR_REASON(ASN1_R_DATA_IS_WRONG) ,"data is wrong"},
{ERR_REASON(ASN1_R_DECODE_ERROR) ,"decode error"},
{ERR_REASON(ASN1_R_DECODING_ERROR) ,"decoding error"},
int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx);
+ int (*sig_print)(BIO *out,
+ 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);
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);
+ int (*item_sign)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+ X509_ALGOR *alg1, X509_ALGOR *alg2,
+ ASN1_BIT_STRING *sig);
} /* EVP_PKEY_ASN1_METHOD */;
l = X509_CRL_get_version(x);
BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l+1, l);
i = OBJ_obj2nid(x->sig_alg->algorithm);
- BIO_printf(out, "%8sSignature Algorithm: %s\n", "",
- (i == NID_undef) ? "NONE" : OBJ_nid2ln(i));
+ X509_signature_print(out, x->sig_alg, NULL);
p=X509_NAME_oneline(X509_CRL_get_issuer(x),NULL,0);
BIO_printf(out,"%8sIssuer: %s\n","",p);
OPENSSL_free(p);
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include "asn1_locl.h"
#ifndef OPENSSL_NO_FP_API
int X509_print_fp(FILE *fp, X509 *x)
if(!(cflag & X509_FLAG_NO_SIGNAME))
{
+ if(X509_signature_print(bp, x->sig_alg, NULL) <= 0)
+ goto err;
+#if 0
if (BIO_printf(bp,"%8sSignature Algorithm: ","") <= 0)
goto err;
if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
+#endif
}
if(!(cflag & X509_FLAG_NO_ISSUER))
return(0);
}
-int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
+int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent)
{
- unsigned char *s;
+ const unsigned char *s;
int i, n;
- if (BIO_puts(bp," Signature Algorithm: ") <= 0) return 0;
- if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0;
n=sig->length;
s=sig->data;
for (i=0; i<n; i++)
{
if ((i%18) == 0)
- if (BIO_write(bp,"\n ",9) <= 0) return 0;
+ {
+ if (BIO_write(bp,"\n",1) <= 0) return 0;
+ if (BIO_indent(bp, indent, indent) <= 0) return 0;
+ }
if (BIO_printf(bp,"%02x%s",s[i],
((i+1) == n)?"":":") <= 0) return 0;
}
if (BIO_write(bp,"\n",1) != 1) return 0;
+
+ return 1;
+}
+
+int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
+{
+ int sig_nid;
+ if (BIO_puts(bp," Signature Algorithm: ") <= 0) return 0;
+ if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0;
+
+ sig_nid = OBJ_obj2nid(sigalg->algorithm);
+ if (sig_nid != NID_undef)
+ {
+ int pkey_nid, dig_nid;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid))
+ {
+ ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
+ if (ameth && ameth->sig_print)
+ return ameth->sig_print(bp, sigalg, sig, 9, 0);
+ }
+ }
+ if (sig)
+ return X509_signature_dump(bp, sig, 9);
+ else if (BIO_puts(bp, "\n") <= 0)
+ return 0;
return 1;
}
cmac_size,
0,
- 0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,
cmac_key_free,
0,
dh_copy_parameters,
dh_cmp_parameters,
dh_param_print,
+ 0,
int_dh_free,
0
#define DSA_F_DSA_SIGN 106
#define DSA_F_DSA_SIGN_SETUP 107
#define DSA_F_DSA_SIG_NEW 109
+#define DSA_F_DSA_SIG_PRINT 125
#define DSA_F_DSA_VERIFY 108
#define DSA_F_I2D_DSA_SIG 111
#define DSA_F_OLD_DSA_PRIV_DECODE 122
return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
}
+static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
+ const ASN1_STRING *sig,
+ int indent, ASN1_PCTX *pctx)
+ {
+ DSA_SIG *dsa_sig;
+ const unsigned char *p;
+ if (!sig)
+ {
+ if (BIO_puts(bp, "\n") <= 0)
+ return 0;
+ else
+ return 1;
+ }
+ p = sig->data;
+ dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
+ if (dsa_sig)
+ {
+ int rv = 0;
+ size_t buf_len = 0;
+ unsigned char *m=NULL;
+ update_buflen(dsa_sig->r, &buf_len);
+ update_buflen(dsa_sig->s, &buf_len);
+ m = OPENSSL_malloc(buf_len+10);
+ if (m == NULL)
+ {
+ DSAerr(DSA_F_DSA_SIG_PRINT,ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (BIO_write(bp, "\n", 1) != 1)
+ goto err;
+
+ if (!ASN1_bn_print(bp,"r: ",dsa_sig->r,m,indent))
+ goto err;
+ if (!ASN1_bn_print(bp,"s: ",dsa_sig->s,m,indent))
+ goto err;
+ rv = 1;
+ err:
+ if (m)
+ OPENSSL_free(m);
+ DSA_SIG_free(dsa_sig);
+ return rv;
+ }
+ return X509_signature_dump(bp, sig, indent);
+ }
+
static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
switch (op)
dsa_copy_parameters,
dsa_cmp_parameters,
dsa_param_print,
+ dsa_sig_print,
int_dsa_free,
dsa_pkey_ctrl,
{ERR_FUNC(DSA_F_DSA_SIGN), "DSA_sign"},
{ERR_FUNC(DSA_F_DSA_SIGN_SETUP), "DSA_sign_setup"},
{ERR_FUNC(DSA_F_DSA_SIG_NEW), "DSA_SIG_new"},
+{ERR_FUNC(DSA_F_DSA_SIG_PRINT), "DSA_SIG_PRINT"},
{ERR_FUNC(DSA_F_DSA_VERIFY), "DSA_verify"},
{ERR_FUNC(DSA_F_I2D_DSA_SIG), "i2d_DSA_SIG"},
{ERR_FUNC(DSA_F_OLD_DSA_PRIV_DECODE), "OLD_DSA_PRIV_DECODE"},
ec_copy_parameters,
ec_cmp_parameters,
eckey_param_print,
+ 0,
int_ec_free,
ec_pkey_ctrl,
hmac_size,
0,
- 0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,
hmac_key_free,
hmac_pkey_ctrl,
-/* AUTOGENERATED BY crypto/objects/objxref.pl, DO NOT EDIT */
+/* AUTOGENERATED BY objxref.pl, DO NOT EDIT */
typedef struct
{
{NID_id_GostR3411_94_with_GostR3410_94, NID_id_GostR3411_94, NID_id_GostR3410_94},
{NID_id_GostR3411_94_with_GostR3410_94_cc, NID_id_GostR3411_94, NID_id_GostR3410_94_cc},
{NID_id_GostR3411_94_with_GostR3410_2001_cc, NID_id_GostR3411_94, NID_id_GostR3410_2001_cc},
+ {NID_rsassaPss, NID_undef, NID_rsaEncryption},
};
static const nid_triple * const sigoid_srt_xref[] =
{
+ &sigoid_srt[29],
&sigoid_srt[17],
&sigoid_srt[18],
&sigoid_srt[0],
sha224WithRSAEncryption sha224 rsaEncryption
mdc2WithRSA mdc2 rsaEncryption
ripemd160WithRSA ripemd160 rsaEncryption
+# For PSS the digest algorithm can vary and depends on the included
+# AlgorithmIdentifier. The digest "undef" indicates the public key
+# method should handle this explicitly.
+rsassaPss undef rsaEncryption
# Alternative deprecated OIDs. By using the older "rsa" OID this
# type will be recognized by not normally used.
typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
typedef struct asn1_string_st ASN1_VISIBLESTRING;
typedef struct asn1_string_st ASN1_UTF8STRING;
+typedef struct asn1_string_st ASN1_STRING;
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
DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey)
DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey)
+typedef struct rsa_pss_params_st
+ {
+ X509_ALGOR *hashAlgorithm;
+ X509_ALGOR *maskGenAlgorithm;
+ ASN1_INTEGER *saltLength;
+ ASN1_INTEGER *trailerField;
+ } RSA_PSS_PARAMS;
+
+DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+
#ifndef OPENSSL_NO_FP_API
int RSA_print_fp(FILE *fp, const RSA *r,int offset);
#endif
#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT 104
#define RSA_F_RSA_GENERATE_KEY 105
#define RSA_F_RSA_GENERATE_KEY_EX 155
+#define RSA_F_RSA_ITEM_VERIFY 156
#define RSA_F_RSA_MEMORY_LOCK 130
#define RSA_F_RSA_NEW_METHOD 106
#define RSA_F_RSA_NULL 124
#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_MGF1_MD 156
#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
#define RSA_R_KEY_SIZE_TOO_SMALL 120
#define RSA_R_LAST_OCTET_INVALID 134
#define RSA_R_MODULUS_TOO_LARGE 105
-#define RSA_R_NON_FIPS_RSA_METHOD 150
+#define RSA_R_NON_FIPS_RSA_METHOD 157
#define RSA_R_NO_PUBLIC_EXPONENT 140
#define RSA_R_NULL_BEFORE_BLOCK_MISSING 113
#define RSA_R_N_DOES_NOT_EQUAL_P_Q 127
#define RSA_R_OAEP_DECODING_ERROR 121
-#define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 151
+#define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 158
#define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148
#define RSA_R_PADDING_CHECK_FAILED 114
#define RSA_R_P_NOT_PRIME 128
#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
return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
}
+static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
+ X509_ALGOR **pmaskHash)
+ {
+ const unsigned char *p;
+ int plen;
+ RSA_PSS_PARAMS *pss;
+
+ *pmaskHash = NULL;
+
+ if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE)
+ return NULL;
+ p = alg->parameter->value.sequence->data;
+ plen = alg->parameter->value.sequence->length;
+ pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
+
+ if (!pss)
+ return NULL;
+
+ if (pss->maskGenAlgorithm)
+ {
+ ASN1_TYPE *param = pss->maskGenAlgorithm->parameter;
+ if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) == NID_mgf1
+ && param->type == V_ASN1_SEQUENCE)
+ {
+ p = param->value.sequence->data;
+ plen = param->value.sequence->length;
+ *pmaskHash = d2i_X509_ALGOR(NULL, &p, plen);
+ }
+ }
+
+ return pss;
+ }
+
+static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
+ X509_ALGOR *maskHash, int indent)
+ {
+ int rv = 0;
+ if (!pss)
+ {
+ if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0)
+ return 0;
+ return 1;
+ }
+ if (BIO_puts(bp, "\n") <= 0)
+ goto err;
+ if (!BIO_indent(bp, indent, 128))
+ goto err;
+ if (BIO_puts(bp, "Hash Algorithm: ") <= 0)
+ goto err;
+
+ if (pss->hashAlgorithm)
+ {
+ if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "sha1 (default)") <= 0)
+ goto err;
+
+ if (BIO_puts(bp, "\n") <= 0)
+ goto err;
+
+ if (!BIO_indent(bp, indent, 128))
+ goto err;
+
+ if (BIO_puts(bp, "Mask Algorithm: ") <= 0)
+ goto err;
+ if (pss->maskGenAlgorithm)
+ {
+ if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0)
+ goto err;
+ if (BIO_puts(bp, " with ") <= 0)
+ goto err;
+ if (maskHash)
+ {
+ if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "INVALID") <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0)
+ goto err;
+ BIO_puts(bp, "\n");
+
+ if (!BIO_indent(bp, indent, 128))
+ goto err;
+ if (BIO_puts(bp, "Salt Length: ") <= 0)
+ goto err;
+ if (pss->saltLength)
+ {
+ if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "20 (default)") <= 0)
+ goto err;
+ BIO_puts(bp, "\n");
+
+ if (!BIO_indent(bp, indent, 128))
+ goto err;
+ if (BIO_puts(bp, "Trailer Field: ") <= 0)
+ goto err;
+ if (pss->trailerField)
+ {
+ if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "0xbc (default)") <= 0)
+ goto err;
+ BIO_puts(bp, "\n");
+
+ rv = 1;
+
+ err:
+ return rv;
+
+ }
+
+static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
+ const ASN1_STRING *sig,
+ int indent, ASN1_PCTX *pctx)
+ {
+ if (OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss)
+ {
+ int rv;
+ RSA_PSS_PARAMS *pss;
+ X509_ALGOR *maskHash;
+ pss = rsa_pss_decode(sigalg, &maskHash);
+ rv = rsa_pss_param_print(bp, pss, maskHash, indent);
+ if (pss)
+ RSA_PSS_PARAMS_free(pss);
+ if (maskHash)
+ X509_ALGOR_free(maskHash);
+ if (!rv)
+ return 0;
+ }
+ else if (!sig && BIO_puts(bp, "\n") <= 0)
+ return 0;
+ if (sig)
+ return X509_signature_dump(bp, sig, indent);
+ return 1;
+ }
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(pss->hashAlgorithm->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;
+
+ /* low-level routines support only trailer field 0xbc (value 1)
+ * and PKCS#1 says we should reject any other value anyway.
+ */
+ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_TRAILER);
+ goto err;
+ }
+
+ /* 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) <= 0)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
+ goto err;
+ /* Carry on */
+ rv = 2;
+
+ err:
+ RSA_PSS_PARAMS_free(pss);
+ if (maskHash)
+ X509_ALGOR_free(maskHash);
+ 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;
+ if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0)
+ saltlen--;
+ }
+ 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;
+ if (alg2)
+ {
+ os2 = ASN1_STRING_dup(os1);
+ if (!os2)
+ goto err;
+ X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_rsassaPss),
+ V_ASN1_SEQUENCE, os2);
+ }
+ X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_rsassaPss),
+ V_ASN1_SEQUENCE, os1);
+ 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[] =
{
0,0,0,0,0,0,
+ rsa_sig_print,
int_rsa_free,
rsa_pkey_ctrl,
old_rsa_priv_decode,
- old_rsa_priv_encode
+ old_rsa_priv_encode,
+ rsa_item_verify,
+ rsa_item_sign
},
{
#include "cryptlib.h"
#include <openssl/bn.h>
#include <openssl/rsa.h>
+#include <openssl/x509.h>
#include <openssl/asn1t.h>
/* Override the default free and new methods */
ASN1_SIMPLE(RSA, e, BIGNUM),
} ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey)
+ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3)
+} ASN1_SEQUENCE_END(RSA_PSS_PARAMS)
+
+IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey)
{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_GENERATE_KEY_EX), "RSA_generate_key_ex"},
+{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"},
{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_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"},
{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}
int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
+int X509_signature_dump(BIO *bp,const ASN1_STRING *sig, int indent);
int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig);
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx);
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx);
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx);
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
int X509_pubkey_digest(const X509 *data,const EVP_MD *type,
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(const ASN1_ITEM *it,
+ X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx);
#endif
int X509_set_version(X509 *x,long version);
x->sig_alg, x->signature, x->cert_info,pkey,md));
}
+int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
+ {
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
+ x->cert_info->signature,
+ x->sig_alg, x->signature, x->cert_info, ctx);
+ }
+
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
{
return(ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO),x->sig_alg, NULL,
x->signature, x->req_info,pkey,md));
}
+int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
+ {
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
+ x->sig_alg, NULL, x->signature, x->req_info, ctx);
+ }
+
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
{
x->crl->enc.modified = 1;
x->sig_alg, x->signature, x->crl,pkey,md));
}
+int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
+ {
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
+ x->crl->sig_alg, x->sig_alg, x->signature, x->crl, ctx);
+ }
+
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
{
return(ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,NULL,