diff --git a/CHANGES b/CHANGES index 1d536cdd20305dbdfdf4ebf840aeca4c58da680c..991e4b0972ef87583e06d35e4f5c76148dcadc68 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 f7532d21b56c3ae34e0116484e667f058f5ea815..9fde400f69aca561c5ae9226da6da3a9783a89ce 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 a620b98cf78a18ca1c5a0220768726c6497890d6..2995800d96565247b86ec820c8d59dcac9106b86 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 b9a3852cfce5bcfc9311f3a02b6cab698c692428..4c95bb9e3c83d44333576f5b0c78d55aa5e64695 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 e3a97383a6cd37a031a884d3b4df589c3fd1fd02..dfe41a6f1f474de0da775bd4f92f33bb913f6124 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 c98dc7c332fe4a8d9b7fbb0555171fb0bf8cf2e8..ff63bfc7be9427181a86e8c5c133409d0ceecfaa 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 ea57f77861e6bc22b1267f4ef007316ac84ef0b2..912619efc7354606f1c3a8c370ebbae004db5bc8 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 8b1a651a92153833cb1a83ca625cdb88ad66c018..148455c2d6a52661e01107bfc337254cddb3a3cb 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 3178bac9bc72a88b8b2de4bde1ab0aa43b12d330..e221fada34433608b115eb0842685c0840ed5bad 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 12b85b6fdef7c6eaec5f6947f3828d2415fc49d8..ba611646fd51bb9642bf43fcf37fedc3c15b20e0 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 83bf8050ea12a4674bb32b56e483044a5e78a3b6..ff95a34b49e20c4d2cf6ac5d2024145282855d35 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 19644ab6e26922d42b28429e0514c64757ca004a..730520fb59bceb947172d74d64fa515f7e9ee981 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 917b376caac0c356ad875a99340cb42c29957eae..03785495df2a9d5c8a7b5d4ea18a8f485406ab0f 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;