From 03919683f9bade36ef1b58e64638ac3ccbbf371a Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 7 May 2006 17:09:39 +0000 Subject: [PATCH] Add support for default public key digest type ctrl. --- CHANGES | 10 ++++++++++ apps/ca.c | 36 +++++++++++------------------------- apps/openssl.cnf | 2 +- apps/req.c | 13 ++----------- apps/x509.c | 37 +++++++------------------------------ crypto/asn1/a_sign.c | 13 +++++++++++++ crypto/asn1/asn1.h | 1 + crypto/asn1/asn1_err.c | 1 + crypto/dsa/dsa_ameth.c | 4 ++++ crypto/ec/ec_ameth.c | 4 ++++ crypto/evp/evp.h | 3 +++ crypto/evp/p_lib.c | 9 +++++++++ crypto/rsa/rsa_ameth.c | 4 ++++ 13 files changed, 70 insertions(+), 67 deletions(-) diff --git a/CHANGES b/CHANGES index 1d536cdd20..991e4b0972 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,16 @@ Changes between 0.9.8a and 0.9.9 [xx XXX xxxx] + *) Add a ctrl to asn1 method to allow a public key algorithm to express + a default digest type to use. In most cases this will be SHA1 but some + algorithms (such as GOST) need to specify an alternative digest. The + return value indicates how strong the prefernce is 1 means optional and + 2 is mandatory (that is it is the only supported type). Modify + ASN1_item_sign() to accept a NULL digest argument to indicate it should + use the default md. Update openssl utilities to use the default digest + type for signing if it is not explicitly indicated. + [Steve Henson] + *) Use OID cross reference table in ASN1_sign() and ASN1_verify(). New EVP_MD flag EVP_MD_FLAG_PKEY_METHOD_SIGNATURE. This uses the relevant signing method from the key type. This effectively removes the link diff --git a/apps/ca.c b/apps/ca.c index f7532d21b5..9fde400f69 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -1016,6 +1016,17 @@ bad: goto err; } + if (!strcmp(md, "default")) + { + int def_nid; + if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) + { + BIO_puts(bio_err,"no default digest\n"); + goto err; + } + md = (char *)OBJ_nid2sn(def_nid); + } + if ((dgst=EVP_get_digestbyname(md)) == NULL) { BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); @@ -1412,17 +1423,6 @@ bad: /* we now have a CRL */ if (verbose) BIO_printf(bio_err,"signing CRL\n"); -#if 0 -#ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) - dgst=EVP_dss1(); - else -#endif -#ifndef OPENSSL_NO_ECDSA - if (pkey->type == EVP_PKEY_EC) - dgst=EVP_ecdsa(); -#endif -#endif /* Add any extensions asked for */ @@ -2101,25 +2101,11 @@ again2: } } - -#ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1(); pktmp=X509_get_pubkey(ret); if (EVP_PKEY_missing_parameters(pktmp) && !EVP_PKEY_missing_parameters(pkey)) EVP_PKEY_copy_parameters(pktmp,pkey); EVP_PKEY_free(pktmp); -#endif -#ifndef OPENSSL_NO_ECDSA - if (pkey->type == EVP_PKEY_EC) - dgst = EVP_ecdsa(); - pktmp = X509_get_pubkey(ret); - if (EVP_PKEY_missing_parameters(pktmp) && - !EVP_PKEY_missing_parameters(pkey)) - EVP_PKEY_copy_parameters(pktmp, pkey); - EVP_PKEY_free(pktmp); -#endif - if (!X509_sign(ret,pkey,dgst)) goto err; diff --git a/apps/openssl.cnf b/apps/openssl.cnf index a620b98cf7..2995800d96 100644 --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -72,7 +72,7 @@ cert_opt = ca_default # Certificate field options default_days = 365 # how long to certify for default_crl_days= 30 # how long before next CRL -default_md = sha1 # which md to use. +default_md = default # use public key default MD preserve = no # keep passed DN ordering # A few difference way of specifying how similar the request should look diff --git a/apps/req.c b/apps/req.c index b9a3852cfc..4c95bb9e3c 100644 --- a/apps/req.c +++ b/apps/req.c @@ -193,7 +193,7 @@ int MAIN(int argc, char **argv) char *p; char *subj = NULL; int multirdn = 0; - const EVP_MD *md_alg=NULL,*digest=EVP_sha1(); + const EVP_MD *md_alg=NULL,*digest=NULL; unsigned long chtype = MBSTRING_ASC; #ifndef MONOLITH char *to_free; @@ -894,16 +894,7 @@ loop: BIO_printf(bio_err,"you need to specify a private key\n"); goto end; } -#if 0 -#ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) - digest=EVP_dss1(); -#endif -#ifndef OPENSSL_NO_ECDSA - if (pkey->type == EVP_PKEY_EC) - digest=EVP_ecdsa(); -#endif -#endif + if (req == NULL) { req=X509_REQ_new(); diff --git a/apps/x509.c b/apps/x509.c index e3a97383a6..dfe41a6f1f 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -188,7 +188,7 @@ int MAIN(int argc, char **argv) X509_REQ *rq=NULL; int fingerprint=0; char buf[256]; - const EVP_MD *md_alg,*digest=EVP_sha1(); + const EVP_MD *md_alg,*digest=NULL; CONF *extconf = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL; int need_rand = 0; @@ -885,14 +885,18 @@ bad: int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; + const EVP_MD *fdig = digest; - if (!X509_digest(x,digest,md,&n)) + if (!fdig) + fdig = EVP_sha1(); + + if (!X509_digest(x,fdig,md,&n)) { BIO_printf(bio_err,"out of memory\n"); goto end; } BIO_printf(STDout,"%s Fingerprint=", - OBJ_nid2sn(EVP_MD_type(digest))); + OBJ_nid2sn(EVP_MD_type(fdig))); for (j=0; j<(int)n; j++) { BIO_printf(STDout,"%02X%c",md[j], @@ -912,16 +916,6 @@ bad: passin, e, "Private key"); if (Upkey == NULL) goto end; } -#if 0 -#ifndef OPENSSL_NO_DSA - if (Upkey->type == EVP_PKEY_DSA) - digest=EVP_dss1(); -#endif -#ifndef OPENSSL_NO_ECDSA - if (Upkey->type == EVP_PKEY_EC) - digest=EVP_ecdsa(); -#endif -#endif assert(need_rand); if (!sign(x,Upkey,days,clrext,digest, @@ -938,14 +932,6 @@ bad: "CA Private Key"); if (CApkey == NULL) goto end; } -#ifndef OPENSSL_NO_DSA - if (CApkey->type == EVP_PKEY_DSA) - digest=EVP_dss1(); -#endif -#ifndef OPENSSL_NO_ECDSA - if (CApkey->type == EVP_PKEY_EC) - digest = EVP_ecdsa(); -#endif assert(need_rand); if (!x509_certify(ctx,CAfile,digest,x,xca, @@ -973,15 +959,6 @@ bad: BIO_printf(bio_err,"Generating certificate request\n"); -#ifndef OPENSSL_NO_DSA - if (pk->type == EVP_PKEY_DSA) - digest=EVP_dss1(); -#endif -#ifndef OPENSSL_NO_ECDSA - if (pk->type == EVP_PKEY_EC) - digest=EVP_ecdsa(); -#endif - rq=X509_to_X509_REQ(x,pk,digest); EVP_PKEY_free(pk); if (rq == NULL) diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c index c98dc7c332..ff63bfc7be 100644 --- a/crypto/asn1/a_sign.c +++ b/crypto/asn1/a_sign.c @@ -222,6 +222,19 @@ int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, int inl=0,outl=0,outll=0; int signid, paramtype; + if (type == NULL) + { + int def_nid; + if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0) + type = EVP_get_digestbynid(def_nid); + } + + if (type == NULL) + { + ASN1err(ASN1_F_ASN1_ITEM_SIGN, ASN1_R_NO_DEFAULT_DIGEST); + return 0; + } + if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { if (!pkey->ameth || diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index ea57f77861..912619efc7 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -1228,6 +1228,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_NON_HEX_CHARACTERS 141 #define ASN1_R_NOT_ASCII_FORMAT 190 #define ASN1_R_NOT_ENOUGH_DATA 142 +#define ASN1_R_NO_DEFAULT_DIGEST 201 #define ASN1_R_NO_MATCHING_CHOICE_TYPE 143 #define ASN1_R_NULL_IS_WRONG_LENGTH 144 #define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191 diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index 8b1a651a92..148455c2d6 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -248,6 +248,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS) ,"non hex characters"}, {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT) ,"not ascii format"}, {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA) ,"not enough data"}, +{ERR_REASON(ASN1_R_NO_DEFAULT_DIGEST) ,"no default digest"}, {ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE),"no matching choice type"}, {ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) ,"null is wrong length"}, {ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT),"object not ascii format"}, diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 3178bac9bc..e221fada34 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -544,6 +544,10 @@ static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) } return 1; + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha1; + return 2; + default: return -2; diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 12b85b6fde..ba611646fd 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -586,6 +586,10 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) } return 1; + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha1; + return 2; + default: return -2; diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 83bf8050ea..ff95a34b49 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -770,6 +770,8 @@ int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx); +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid); + int EVP_CIPHER_type(const EVP_CIPHER *ctx); /* calls methods */ @@ -805,6 +807,7 @@ void EVP_PBE_cleanup(void); #define ASN1_PKEY_CTRL_PKCS7_SIGN 0x1 #define ASN1_PKEY_CTRL_PKCS7_ENCRYPT 0x2 +#define ASN1_PKEY_CTRL_DEFAULT_MD_NID 0x3 int EVP_PKEY_asn1_get_count(void); const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx); diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 19644ab6e2..730520fb59 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -361,3 +361,12 @@ int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, return pkey->ameth->param_print(out, pkey, indent, pctx); return unsup_alg(out, pkey, indent, "Parameters"); } + +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid) + { + if (!pkey->ameth || !pkey->ameth->pkey_ctrl) + return -2; + return pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, + 0, pnid); + } + diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 917b376caa..03785495df 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -287,6 +287,10 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) } return 1; + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha1; + return 1; + default: return -2; -- GitLab