From 52664f5081939c96c5867fd02278f7575f1cab2d Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 21 Nov 1999 22:28:31 +0000 Subject: [PATCH] Transparent support for PKCS#8 private keys in RSA/DSA. New universal public key format. Fix CRL+cert load problem in by_file.c Make verify report errors when loading files or dirs --- CHANGES | 44 +++++++++++++++++ apps/dsa.c | 8 +-- apps/rsa.c | 21 +++++--- apps/verify.c | 20 ++++++-- apps/x509.c | 20 +++++++- crypto/asn1/asn1.h | 2 + crypto/asn1/asn1_err.c | 2 + crypto/asn1/x_pubkey.c | 107 +++++++++++++++++++++++++++++++++++++++++ crypto/evp/evp.h | 9 ++-- crypto/evp/p_lib.c | 27 +++++++++-- crypto/pem/pem.h | 6 ++- crypto/pem/pem_all.c | 86 +++++++++++++++++++++++++++++++-- crypto/x509/by_file.c | 54 ++++++++++++++++----- crypto/x509/x509.h | 23 +++++++-- crypto/x509/x509_err.c | 1 + crypto/x509/x509_vfy.h | 1 + crypto/x509/x_all.c | 40 ++++++++++++--- util/libeay.num | 44 ++++++++++++----- 18 files changed, 452 insertions(+), 63 deletions(-) diff --git a/CHANGES b/CHANGES index a7516c4783..56d2c6e3c7 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,50 @@ Changes between 0.9.4 and 0.9.5 [xx XXX 1999] + *) Modify RSA and DSA PEM read routines to transparently handle + PKCS#8 format private keys. New *_PUBKEY_* functions that handle + public keys in a format compatible with certificate + SubjectPublicKeyInfo structures. Unfortunately there were already + functions called *_PublicKey_* which used various odd formats so + these are retained for compatability: however the DSA variants were + never in a public release so they have been deleted. Changed dsa/rsa + utilities to handle the new format: note no releases ever handled public + keys so we should be OK. + + The primary motivation for this change is to avoid the same fiasco + that dogs private keys: there are several incompatible private key + formats some of which are standard and some OpenSSL specific and + require various evil hacks to allow partial transparent handling and + even then it doesn't work with DER formats. Given the option anything + other than PKCS#8 should be dumped: but the other formats have to + stay in the name of compatability. + + With public keys and the benefit of hindsight one standard format + is used which works with EVP_PKEY, RSA or DSA structures: though + it clearly returns an error if you try to read the wrong kind of key. + + Added a -pubkey option to the 'x509' utility to output the public key. + Also rename the EVP_PKEY_get_*() to EVP_PKEY_rget_*() and add + EVP_PKEY_rset_*() functions that do the same as the EVP_PKEY_assign_*() + except they up the reference count of the added key (they don't "swallow" + the supplied key). + [Steve Henson] + + *) Fixes to crypto/x509/by_file.c the code to read in certificates and + CRLs would fail if the file contained no certificates or no CRLs: + added a new function to read in both types and return the number + read: this means that if none are read it will be an error. The + DER versions of the certificate and CRL reader would always fail + because it isn't possible to mix certificates and CRLs in DER format + without choking one or the other routine. Changed this to just read + a certificate: this is the best we can do. Also modified the code + in apps/verify.c to take notice of return codes: it was previously + attempting to read in certificates from NULL pointers and ignoring + any errors: this is one reason why the cert and CRL reader seemed + to work. It doesn't check return codes from the default certificate + routines: these may well fail if the certificates aren't installed. + [Steve Henson] + *) Code to support otherName option in GeneralName. [Steve Henson] diff --git a/apps/dsa.c b/apps/dsa.c index 85c62b9275..a5ff647252 100644 --- a/apps/dsa.c +++ b/apps/dsa.c @@ -232,10 +232,10 @@ bad: BIO_printf(bio_err,"read DSA key\n"); if (informat == FORMAT_ASN1) { - if(pubin) dsa=d2i_DSAPublicKey_bio(in,NULL); + if(pubin) dsa=d2i_DSA_PUBKEY_bio(in,NULL); else dsa=d2i_DSAPrivateKey_bio(in,NULL); } else if (informat == FORMAT_PEM) { - if(pubin) dsa=PEM_read_bio_DSAPublicKey(in,NULL, NULL, NULL); + if(pubin) dsa=PEM_read_bio_DSA_PUBKEY(in,NULL, NULL, NULL); else { if(passin) dsa=PEM_read_bio_DSAPrivateKey(in,NULL, key_cb,passin); @@ -282,11 +282,11 @@ bad: if (noout) goto end; BIO_printf(bio_err,"writing DSA key\n"); if (outformat == FORMAT_ASN1) { - if(pubin || pubout) i=i2d_DSAPublicKey_bio(out,dsa); + if(pubin || pubout) i=i2d_DSA_PUBKEY_bio(out,dsa); else i=i2d_DSAPrivateKey_bio(out,dsa); } else if (outformat == FORMAT_PEM) { if(pubin || pubout) - i=PEM_write_bio_DSAPublicKey(out,dsa); + i=PEM_write_bio_DSA_PUBKEY(out,dsa); else { if(passout) i=PEM_write_bio_DSAPrivateKey(out,dsa,enc, NULL,0,key_cb, passout); diff --git a/apps/rsa.c b/apps/rsa.c index ee1365a929..219bdd65d6 100644 --- a/apps/rsa.c +++ b/apps/rsa.c @@ -220,6 +220,11 @@ bad: ERR_load_crypto_strings(); + if(check && pubin) { + BIO_printf(bio_err, "Only private keys can be checked\n"); + goto end; + } + in=BIO_new(BIO_s_file()); out=BIO_new(BIO_s_file()); if ((in == NULL) || (out == NULL)) @@ -239,9 +244,9 @@ bad: } } - BIO_printf(bio_err,"read RSA private key\n"); + BIO_printf(bio_err,"read RSA key\n"); if (informat == FORMAT_ASN1) { - if (pubin) rsa=d2i_RSAPublicKey_bio(in,NULL); + if (pubin) rsa=d2i_RSA_PUBKEY_bio(in,NULL); else rsa=d2i_RSAPrivateKey_bio(in,NULL); } #ifndef NO_RC4 @@ -272,7 +277,7 @@ bad: } #endif else if (informat == FORMAT_PEM) { - if(pubin) rsa=PEM_read_bio_RSAPublicKey(in,NULL,NULL,NULL); + if(pubin) rsa=PEM_read_bio_RSA_PUBKEY(in,NULL,NULL,NULL); else { if(passin) rsa=PEM_read_bio_RSAPrivateKey(in,NULL, key_cb,passin); @@ -286,7 +291,7 @@ bad: } if (rsa == NULL) { - BIO_printf(bio_err,"unable to load Key\n"); + BIO_printf(bio_err,"unable to load key\n"); ERR_print_errors(bio_err); goto end; } @@ -312,9 +317,9 @@ bad: if (modulus) { - fprintf(stdout,"Modulus="); + BIO_printf(out,"Modulus="); BN_print(out,rsa->n); - fprintf(stdout,"\n"); + BIO_printf(out,"\n"); } if (check) @@ -351,7 +356,7 @@ bad: } BIO_printf(bio_err,"writing RSA key\n"); if (outformat == FORMAT_ASN1) { - if(pubout || pubin) i=i2d_RSAPublicKey_bio(out,rsa); + if(pubout || pubin) i=i2d_RSA_PUBKEY_bio(out,rsa); else i=i2d_RSAPrivateKey_bio(out,rsa); } #ifndef NO_RC4 @@ -375,7 +380,7 @@ bad: #endif else if (outformat == FORMAT_PEM) { if(pubout || pubin) - i=PEM_write_bio_RSAPublicKey(out,rsa); + i=PEM_write_bio_RSA_PUBKEY(out,rsa); else { if(passout) i=PEM_write_bio_RSAPrivateKey(out,rsa, enc,NULL,0,key_cb,passout); diff --git a/apps/verify.c b/apps/verify.c index 840fda9561..4166b92fb4 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -124,13 +124,25 @@ int MAIN(int argc, char **argv) lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_file()); if (lookup == NULL) abort(); - if (!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) - X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); + if (CAfile) { + i=X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM); + if(!i) { + BIO_printf(bio_err, "Error loading file %s\n", CAfile); + ERR_print_errors(bio_err); + goto end; + } + } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_hash_dir()); if (lookup == NULL) abort(); - if (!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) - X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); + if (CApath) { + i=X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM); + if(!i) { + BIO_printf(bio_err, "Error loading directory %s\n", CApath); + ERR_print_errors(bio_err); + goto end; + } + } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); ERR_clear_error(); diff --git a/apps/x509.c b/apps/x509.c index f56244c5c7..a6b5deb114 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -101,6 +101,7 @@ static char *x509_usage[]={ " -purpose - print out certificate purposes\n", " -dates - both Before and After dates\n", " -modulus - print the RSA key modulus\n", +" -pubkey - output the public key\n", " -fingerprint - print the certificate fingerprint\n", " -alias - output certificate alias\n", " -noout - no certificate output\n", @@ -161,7 +162,7 @@ int MAIN(int argc, char **argv) int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0; int trustout=0,clrtrust=0,clrnotrust=0,aliasout=0; int C=0; - int x509req=0,days=DEF_DAYS,modulus=0; + int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0; int pprint = 0; char **pp; X509_STORE *ctx=NULL; @@ -324,6 +325,8 @@ int MAIN(int argc, char **argv) serial= ++num; else if (strcmp(*argv,"-modulus") == 0) modulus= ++num; + else if (strcmp(*argv,"-pubkey") == 0) + pubkey= ++num; else if (strcmp(*argv,"-x509toreq") == 0) x509req= ++num; else if (strcmp(*argv,"-text") == 0) @@ -639,6 +642,21 @@ bad: BIO_printf(STDout,"\n"); EVP_PKEY_free(pkey); } + else + if (pubkey == i) + { + EVP_PKEY *pkey; + + pkey=X509_get_pubkey(x); + if (pkey == NULL) + { + BIO_printf(bio_err,"Error getting public key\n"); + ERR_print_errors(bio_err); + goto end; + } + PEM_write_bio_PUBKEY(STDout, pkey); + EVP_PKEY_free(pkey); + } else if (C == i) { diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index bf481042bc..ab89027ade 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -914,12 +914,14 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_F_I2D_DSAPARAMS 178 #define ASN1_F_I2D_DSAPRIVATEKEY 179 #define ASN1_F_I2D_DSAPUBLICKEY 180 +#define ASN1_F_I2D_DSA_PUBKEY 290 #define ASN1_F_I2D_NETSCAPE_RSA 181 #define ASN1_F_I2D_PKCS7 182 #define ASN1_F_I2D_PRIVATEKEY 183 #define ASN1_F_I2D_PUBLICKEY 184 #define ASN1_F_I2D_RSAPRIVATEKEY 185 #define ASN1_F_I2D_RSAPUBLICKEY 186 +#define ASN1_F_I2D_RSA_PUBKEY 289 #define ASN1_F_I2D_X509_ATTRIBUTE 187 #define ASN1_F_I2T_ASN1_OBJECT 188 #define ASN1_F_NETSCAPE_CERT_SEQUENCE_NEW 229 diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index 1167029ad3..6d11e13c3f 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -194,12 +194,14 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_I2D_DSAPARAMS,0), "i2d_DSAparams"}, {ERR_PACK(0,ASN1_F_I2D_DSAPRIVATEKEY,0), "i2d_DSAPrivateKey"}, {ERR_PACK(0,ASN1_F_I2D_DSAPUBLICKEY,0), "i2d_DSAPublicKey"}, +{ERR_PACK(0,ASN1_F_I2D_DSA_PUBKEY,0), "i2d_DSA_PUBKEY"}, {ERR_PACK(0,ASN1_F_I2D_NETSCAPE_RSA,0), "i2d_Netscape_RSA"}, {ERR_PACK(0,ASN1_F_I2D_PKCS7,0), "i2d_PKCS7"}, {ERR_PACK(0,ASN1_F_I2D_PRIVATEKEY,0), "i2d_PrivateKey"}, {ERR_PACK(0,ASN1_F_I2D_PUBLICKEY,0), "i2d_PublicKey"}, {ERR_PACK(0,ASN1_F_I2D_RSAPRIVATEKEY,0), "i2d_RSAPrivateKey"}, {ERR_PACK(0,ASN1_F_I2D_RSAPUBLICKEY,0), "i2d_RSAPublicKey"}, +{ERR_PACK(0,ASN1_F_I2D_RSA_PUBKEY,0), "i2d_RSA_PUBKEY"}, {ERR_PACK(0,ASN1_F_I2D_X509_ATTRIBUTE,0), "i2d_X509_ATTRIBUTE"}, {ERR_PACK(0,ASN1_F_I2T_ASN1_OBJECT,0), "i2t_ASN1_OBJECT"}, {ERR_PACK(0,ASN1_F_NETSCAPE_CERT_SEQUENCE_NEW,0), "NETSCAPE_CERT_SEQUENCE_new"}, diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c index 8adaeba82c..1740df7e2b 100644 --- a/crypto/asn1/x_pubkey.c +++ b/crypto/asn1/x_pubkey.c @@ -252,3 +252,110 @@ err: return(NULL); } +/* Now two pseudo ASN1 routines that take an EVP_PKEY structure + * and encode or decode as X509_PUBKEY + */ + +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, unsigned char **pp, + long length) +{ + X509_PUBKEY *xpk; + EVP_PKEY *pktmp; + xpk = d2i_X509_PUBKEY(NULL, pp, length); + if(!xpk) return NULL; + pktmp = X509_PUBKEY_get(xpk); + X509_PUBKEY_free(xpk); + if(!pktmp) return NULL; + if(a) { + EVP_PKEY_free(*a); + *a = pktmp; + } + return pktmp; +} + +int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) +{ + X509_PUBKEY *xpk=NULL; + int ret; + if(!a) return 0; + if(!X509_PUBKEY_set(&xpk, a)) return 0; + ret = i2d_X509_PUBKEY(xpk, pp); + X509_PUBKEY_free(xpk); + return ret; +} + +/* The following are equivalents but which return RSA and DSA + * keys + */ + +RSA *d2i_RSA_PUBKEY(RSA **a, unsigned char **pp, + long length) +{ + EVP_PKEY *pkey; + RSA *key; + unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if(!pkey) return NULL; + key = EVP_PKEY_rget_RSA(pkey); + EVP_PKEY_free(pkey); + if(!key) return NULL; + *pp = q; + if(a) { + RSA_free(*a); + *a = key; + } + return key; +} + +int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if(!a) return 0; + pktmp = EVP_PKEY_new(); + if(!pktmp) { + ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_PKEY_rset_RSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} + +DSA *d2i_DSA_PUBKEY(DSA **a, unsigned char **pp, + long length) +{ + EVP_PKEY *pkey; + DSA *key; + unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if(!pkey) return NULL; + key = EVP_PKEY_rget_DSA(pkey); + EVP_PKEY_free(pkey); + if(!key) return NULL; + *pp = q; + if(a) { + DSA_free(*a); + *a = key; + } + return key; +} + +int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if(!a) return 0; + pktmp = EVP_PKEY_new(); + if(!pktmp) { + ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_PKEY_rset_DSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index f249daeed6..eb592f0752 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -612,9 +612,12 @@ int EVP_PKEY_type(int type); int EVP_PKEY_bits(EVP_PKEY *pkey); int EVP_PKEY_size(EVP_PKEY *pkey); int EVP_PKEY_assign(EVP_PKEY *pkey,int type,char *key); -RSA * EVP_PKEY_get_RSA(EVP_PKEY *pkey); -DSA * EVP_PKEY_get_DSA(EVP_PKEY *pkey); -DH * EVP_PKEY_get_DH(EVP_PKEY *pkey); +int EVP_PKEY_rset_RSA(EVP_PKEY *pkey,RSA *key); +int EVP_PKEY_rset_DSA(EVP_PKEY *pkey,DSA *key); +int EVP_PKEY_rset_DH(EVP_PKEY *pkey,DH *key); +RSA * EVP_PKEY_rget_RSA(EVP_PKEY *pkey); +DSA * EVP_PKEY_rget_DSA(EVP_PKEY *pkey); +DH * EVP_PKEY_rget_DH(EVP_PKEY *pkey); EVP_PKEY * EVP_PKEY_new(void); void EVP_PKEY_free(EVP_PKEY *pkey); EVP_PKEY * d2i_PublicKey(int type,EVP_PKEY **a, unsigned char **pp, diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index dba08525a3..14ad90cec5 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -206,7 +206,13 @@ int EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key) } #ifndef NO_RSA -RSA *EVP_PKEY_get_RSA(EVP_PKEY *pkey) +int EVP_PKEY_rset_RSA(EVP_PKEY *pkey, RSA *key) +{ + CRYPTO_add(&key->references, 1, CRYPTO_LOCK_RSA); + return EVP_PKEY_assign_RSA(pkey, key); +} + +RSA *EVP_PKEY_rget_RSA(EVP_PKEY *pkey) { if(pkey->type != EVP_PKEY_RSA) { EVPerr(EVP_F_EVP_PKEY_GET_RSA, EVP_R_EXPECTING_AN_RSA_KEY); @@ -218,19 +224,32 @@ RSA *EVP_PKEY_get_RSA(EVP_PKEY *pkey) #endif #ifndef NO_DSA -DSA *EVP_PKEY_get_DSA(EVP_PKEY *pkey) +int EVP_PKEY_rset_DSA(EVP_PKEY *pkey, DSA *key) +{ + CRYPTO_add(&key->references, 1, CRYPTO_LOCK_DSA); + return EVP_PKEY_assign_DSA(pkey, key); +} + +DSA *EVP_PKEY_rget_DSA(EVP_PKEY *pkey) { if(pkey->type != EVP_PKEY_DSA) { EVPerr(EVP_F_EVP_PKEY_GET_DSA, EVP_R_EXPECTING_A_DSA_KEY); return NULL; } - CRYPTO_add(&pkey->pkey.rsa->references, 1, CRYPTO_LOCK_DSA); + CRYPTO_add(&pkey->pkey.dsa->references, 1, CRYPTO_LOCK_DSA); return pkey->pkey.dsa; } #endif #ifndef NO_DH -DH *EVP_PKEY_get_DH(EVP_PKEY *pkey) + +int EVP_PKEY_rset_DH(EVP_PKEY *pkey, DH *key) +{ + CRYPTO_add(&key->references, 1, CRYPTO_LOCK_DH); + return EVP_PKEY_assign_DH(pkey, key); +} + +DH *EVP_PKEY_rget_DH(EVP_PKEY *pkey) { if(pkey->type != EVP_PKEY_DH) { EVPerr(EVP_F_EVP_PKEY_GET_DH, EVP_R_EXPECTING_A_DH_KEY); diff --git a/crypto/pem/pem.h b/crypto/pem/pem.h index ce2c1a3596..9260a11b8a 100644 --- a/crypto/pem/pem.h +++ b/crypto/pem/pem.h @@ -108,6 +108,7 @@ extern "C" { #define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" #define PEM_STRING_X509_CRL "X509 CRL" #define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" +#define PEM_STRING_PUBLIC "PUBLIC KEY" #define PEM_STRING_RSA "RSA PRIVATE KEY" #define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" #define PEM_STRING_DSA "DSA PRIVATE KEY" @@ -549,6 +550,7 @@ DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) DECLARE_PEM_rw(RSAPublicKey, RSA) +DECLARE_PEM_rw(RSA_PUBKEY, RSA) #endif @@ -556,7 +558,7 @@ DECLARE_PEM_rw(RSAPublicKey, RSA) DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) -DECLARE_PEM_rw(DSAPublicKey, DSA) +DECLARE_PEM_rw(DSA_PUBKEY, DSA) DECLARE_PEM_rw(DSAparams, DSA) @@ -570,6 +572,8 @@ DECLARE_PEM_rw(DHparams, DH) DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) +DECLARE_PEM_rw(PUBKEY, EVP_PKEY); + int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, char *, int, pem_password_cb *, void *); int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc, diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c index 80f4037262..93f5d7ba79 100644 --- a/crypto/pem/pem_all.c +++ b/crypto/pem/pem_all.c @@ -65,6 +65,9 @@ #include #include +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa); +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa); + IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509) IMPLEMENT_PEM_rw(X509_AUX, X509, PEM_STRING_X509_TRUSTED, X509_AUX) @@ -84,17 +87,92 @@ IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, #ifndef NO_RSA -IMPLEMENT_PEM_rw_cb(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey) +/* We treat RSA or DSA private keys as a special case. + * + * For private keys we read in an EVP_PKEY structure with + * PEM_read_bio_PrivateKey() and extract the relevant private + * key: this means can handle "traditional" and PKCS#8 formats + * transparently. + */ + +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) +{ + RSA *rtmp; + if(!key) return NULL; + rtmp = EVP_PKEY_rget_RSA(key); + EVP_PKEY_free(key); + if(!rtmp) return NULL; + if(rsa) { + RSA_free(*rsa); + *rsa = rtmp; + } + return rtmp; +} + +RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); +} + +#ifndef NO_FP_API + +RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); +} +#endif + +IMPLEMENT_PEM_write_cb(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey) IMPLEMENT_PEM_rw(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey) +IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY) #endif #ifndef NO_DSA -IMPLEMENT_PEM_rw_cb(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey) +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa) +{ + DSA *dtmp; + if(!key) return NULL; + dtmp = EVP_PKEY_rget_DSA(key); + EVP_PKEY_free(key); + if(!dtmp) return NULL; + if(dsa) { + DSA_free(*dsa); + *dsa = dtmp; + } + return dtmp; +} + +DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); +} + +IMPLEMENT_PEM_write_cb(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey) +IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY) + +#ifndef NO_FP_API + +DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); +} -IMPLEMENT_PEM_rw(DSAPublicKey, DSA, PEM_STRING_DSA_PUBLIC, DSAPublicKey) +#endif IMPLEMENT_PEM_rw(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams) @@ -115,3 +193,5 @@ IMPLEMENT_PEM_rw(DHparams, DH, PEM_STRING_DHPARAMS, DHparams) */ IMPLEMENT_PEM_read(PrivateKey, EVP_PKEY, PEM_STRING_EVP_PKEY, PrivateKey) IMPLEMENT_PEM_write_cb(PrivateKey, EVP_PKEY, ((x->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA), PrivateKey) + +IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY); diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c index 0457f01c34..78b4c47751 100644 --- a/crypto/x509/by_file.c +++ b/crypto/x509/by_file.c @@ -92,7 +92,7 @@ X509_LOOKUP_METHOD *X509_LOOKUP_file(void) static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret) { - int ok=0,ok2=0; + int ok=0; char *file; switch (cmd) @@ -100,31 +100,29 @@ static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, case X509_L_FILE_LOAD: if (argl == X509_FILETYPE_DEFAULT) { - ok=X509_load_cert_file(ctx,X509_get_default_cert_file(), + ok=X509_load_cert_crl_file(ctx,X509_get_default_cert_file(), X509_FILETYPE_PEM); - ok2=X509_load_crl_file(ctx,X509_get_default_cert_file(), - X509_FILETYPE_PEM); - if (!ok || !ok2) + if (!ok) { X509err(X509_F_BY_FILE_CTRL,X509_R_LOADING_DEFAULTS); } else { file=(char *)Getenv(X509_get_default_cert_file_env()); - ok=X509_load_cert_file(ctx,file, - X509_FILETYPE_PEM); - ok2=X509_load_crl_file(ctx,file, + ok=X509_load_cert_crl_file(ctx,file, X509_FILETYPE_PEM); } } else { - ok=X509_load_cert_file(ctx,argp,(int)argl); - ok2=X509_load_crl_file(ctx,argp,(int)argl); + if(argl == X509_FILETYPE_PEM) + ok=X509_load_cert_crl_file(ctx,argp, + X509_FILETYPE_PEM); + else ok=X509_load_cert_file(ctx,argp,(int)argl); } break; } - return((ok && ok2)?ok:0); + return(ok); } int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) @@ -261,5 +259,39 @@ err: return(ret); } +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + STACK_OF(X509_INFO) *inf; + X509_INFO *itmp; + BIO *in; + int i, count = 0; + if(type != X509_FILETYPE_PEM) + return X509_load_cert_file(ctx, file, type); + in = BIO_new_file(file, "r"); + if(!in) { + X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_SYS_LIB); + return 0; + } + inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + BIO_free(in); + if(!inf) { + X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB); + return 0; + } + for(i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if(itmp->x509) { + X509_STORE_add_cert(ctx->store_ctx, itmp->x509); + count++; + } else if(itmp->crl) { + X509_STORE_add_crl(ctx->store_ctx, itmp->crl); + count++; + } + } + sk_X509_INFO_pop_free(inf, X509_INFO_free); + return count; +} + + #endif /* NO_STDIO */ diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index d3d8030086..f35a61476f 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -613,10 +613,12 @@ RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa); int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa); RSA *d2i_RSAPublicKey_fp(FILE *fp,RSA **rsa); int i2d_RSAPublicKey_fp(FILE *fp,RSA *rsa); +RSA *d2i_RSA_PUBKEY_fp(FILE *fp,RSA **rsa); +int i2d_RSA_PUBKEY_fp(FILE *fp,RSA *rsa); #endif #ifndef NO_DSA -DSA *d2i_DSAPublicKey_fp(FILE *fp, DSA **dsa); -int i2d_DSAPublicKey_fp(FILE *fp, DSA *dsa); +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8); @@ -639,10 +641,12 @@ RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa); int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa); RSA *d2i_RSAPublicKey_bio(BIO *bp,RSA **rsa); int i2d_RSAPublicKey_bio(BIO *bp,RSA *rsa); +RSA *d2i_RSA_PUBKEY_bio(BIO *bp,RSA **rsa); +int i2d_RSA_PUBKEY_bio(BIO *bp,RSA *rsa); #endif #ifndef NO_DSA -DSA *d2i_DSAPublicKey_bio(BIO *bp, DSA **dsa); -int i2d_DSAPublicKey_bio(BIO *bp, DSA *dsa); +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); #endif @@ -703,7 +707,15 @@ int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); EVP_PKEY * X509_PUBKEY_get(X509_PUBKEY *key); int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain); - +int i2d_PUBKEY(EVP_PKEY *a,unsigned char **pp); +EVP_PKEY * d2i_PUBKEY(EVP_PKEY **a,unsigned char **pp, + long length); +int i2d_RSA_PUBKEY(RSA *a,unsigned char **pp); +RSA * d2i_RSA_PUBKEY(RSA **a,unsigned char **pp, + long length); +int i2d_DSA_PUBKEY(DSA *a,unsigned char **pp); +DSA * d2i_DSA_PUBKEY(DSA **a,unsigned char **pp, + long length); X509_SIG * X509_SIG_new(void ); void X509_SIG_free(X509_SIG *a); @@ -1028,6 +1040,7 @@ PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken); #define X509_F_X509_EXTENSION_CREATE_BY_NID 108 #define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109 #define X509_F_X509_GET_PUBKEY_PARAMETERS 110 +#define X509_F_X509_LOAD_CERT_CRL_FILE 132 #define X509_F_X509_LOAD_CERT_FILE 111 #define X509_F_X509_LOAD_CRL_FILE 112 #define X509_F_X509_NAME_ADD_ENTRY 113 diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index 0a0b704043..58e13c6c6b 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -76,6 +76,7 @@ static ERR_STRING_DATA X509_str_functs[]= {ERR_PACK(0,X509_F_X509_EXTENSION_CREATE_BY_NID,0), "X509_EXTENSION_create_by_NID"}, {ERR_PACK(0,X509_F_X509_EXTENSION_CREATE_BY_OBJ,0), "X509_EXTENSION_create_by_OBJ"}, {ERR_PACK(0,X509_F_X509_GET_PUBKEY_PARAMETERS,0), "X509_get_pubkey_parameters"}, +{ERR_PACK(0,X509_F_X509_LOAD_CERT_CRL_FILE,0), "X509_load_cert_crl_file"}, {ERR_PACK(0,X509_F_X509_LOAD_CERT_FILE,0), "X509_load_cert_file"}, {ERR_PACK(0,X509_F_X509_LOAD_CRL_FILE,0), "X509_load_crl_file"}, {ERR_PACK(0,X509_F_X509_NAME_ADD_ENTRY,0), "X509_NAME_add_entry"}, diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h index 39fa056c1a..9891a6944d 100644 --- a/crypto/x509/x509_vfy.h +++ b/crypto/x509/x509_vfy.h @@ -306,6 +306,7 @@ int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, #ifndef NO_STDIO int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type); int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); #endif diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 354d4c3f3c..4973c18eae 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -285,10 +285,22 @@ RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) (unsigned char **)(rsa))); } +RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) + { + return((RSA *)ASN1_d2i_fp((char *(*)()) + RSA_new,(char *(*)())d2i_RSA_PUBKEY, (fp), + (unsigned char **)(rsa))); + } + int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa) { return(ASN1_i2d_fp(i2d_RSAPublicKey,fp,(unsigned char *)rsa)); } + +int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa) + { + return(ASN1_i2d_fp(i2d_RSA_PUBKEY,fp,(unsigned char *)rsa)); + } #endif RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa) @@ -310,10 +322,22 @@ RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) (unsigned char **)(rsa))); } +RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) + { + return((RSA *)ASN1_d2i_bio((char *(*)()) + RSA_new,(char *(*)())d2i_RSA_PUBKEY, (bp), + (unsigned char **)(rsa))); + } + int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa) { return(ASN1_i2d_bio(i2d_RSAPublicKey,bp,(unsigned char *)rsa)); } + +int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) + { + return(ASN1_i2d_bio(i2d_RSA_PUBKEY,bp,(unsigned char *)rsa)); + } #endif #ifndef NO_DSA @@ -330,16 +354,16 @@ int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa) return(ASN1_i2d_fp(i2d_DSAPrivateKey,fp,(unsigned char *)dsa)); } -DSA *d2i_DSAPublicKey_fp(FILE *fp, DSA **dsa) +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa) { return((DSA *)ASN1_d2i_fp((char *(*)()) - DSA_new,(char *(*)())d2i_DSAPublicKey, (fp), + DSA_new,(char *(*)())d2i_DSA_PUBKEY, (fp), (unsigned char **)(dsa))); } -int i2d_DSAPublicKey_fp(FILE *fp, DSA *dsa) +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa) { - return(ASN1_i2d_fp(i2d_DSAPublicKey,fp,(unsigned char *)dsa)); + return(ASN1_i2d_fp(i2d_DSA_PUBKEY,fp,(unsigned char *)dsa)); } #endif @@ -355,16 +379,16 @@ int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa) return(ASN1_i2d_bio(i2d_DSAPrivateKey,bp,(unsigned char *)dsa)); } -DSA *d2i_DSAPublicKey_bio(BIO *bp, DSA **dsa) +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa) { return((DSA *)ASN1_d2i_bio((char *(*)()) - DSA_new,(char *(*)())d2i_DSAPublicKey, (bp), + DSA_new,(char *(*)())d2i_DSA_PUBKEY, (bp), (unsigned char **)(dsa))); } -int i2d_DSAPublicKey_bio(BIO *bp, DSA *dsa) +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa) { - return(ASN1_i2d_bio(i2d_DSAPublicKey,bp,(unsigned char *)dsa)); + return(ASN1_i2d_bio(i2d_DSA_PUBKEY,bp,(unsigned char *)dsa)); } #endif diff --git a/util/libeay.num b/util/libeay.num index b08c1faef5..a7003bd1a5 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -1895,9 +1895,9 @@ DSA_get_default_method 1919 sk_X509_PURPOSE_push 1920 sk_X509_PURPOSE_delete 1921 sk_X509_PURPOSE_num 1922 -PEM_read_DSAPublicKey 1923 +PEM_read_DSA_PUBKEY 1923 ASN1_T61STRING_free 1924 -d2i_DSAPublicKey_fp 1925 +d2i_DSA_PUBKEY_fp 1925 DSA_set_method 1926 X509_get_ex_data 1927 ASN1_STRING_type 1928 @@ -1908,12 +1908,12 @@ ASN1_BIT_STRING_new 1932 X509V3_X509_get_d2i 1933 ASN1_INTEGER_cmp 1934 ASN1_TIME_new 1935 -d2i_DSAPublicKey_bio 1936 +d2i_DSA_PUBKEY_bio 1936 sk_X509_PURPOSE_new_null 1937 ASN1_UTCTIME_free 1938 DSA_set_default_method 1939 sk_X509_PURPOSE_set_cmp_func 1940 -PEM_write_bio_DSAPublicKey 1941 +PEM_write_bio_DSA_PUBKEY 1941 X509_PURPOSE_get_id 1942 DISPLAYTEXT_free 1943 X509V3_CRL_get_d2i 1944 @@ -1931,7 +1931,7 @@ ASN1_OCTET_STRING_set 1955 ASN1_IA5STRING_new 1956 X509_check_purpose 1957 ASN1_ENUMERATED_new 1958 -PEM_write_DSAPublicKey 1959 +PEM_write_DSA_PUBKEY 1959 ASN1_BMPSTRING_free 1960 ASN1_T61STRING_new 1961 ASN1_UTCTIME_new 1962 @@ -1944,7 +1944,7 @@ X509_PURPOSE_add 1968 ASN1_UTF8STRING_free 1969 X509_PURPOSE_enum 1970 sk_X509_PURPOSE_pop_free 1971 -i2d_DSAPublicKey_fp 1972 +i2d_DSA_PUBKEY_fp 1972 sk_X509_PURPOSE_free 1973 sk_X509_PURPOSE_dup 1974 ASN1_OCTET_STRING_dup 1975 @@ -1956,10 +1956,10 @@ sk_X509_PURPOSE_shift 1980 sk_X509_PURPOSE_new 1981 sk_X509_PURPOSE_insert 1982 ASN1_GENERALIZEDTIME_new 1983 -PEM_read_bio_DSAPublicKey 1984 +PEM_read_bio_DSA_PUBKEY 1984 ASN1_OCTET_STRING_new 1985 ASN1_INTEGER_new 1986 -i2d_DSAPublicKey_bio 1987 +i2d_DSA_PUBKEY_bio 1987 ASN1_STRING_length_set 1988 DIRECTORYSTRING_new 1989 ASN1_mbstring_copy 1990 @@ -1989,9 +1989,9 @@ sk_ASN1_STRING_TABLE_dup 2013 ASN1_mbstring_ncopy 2014 sk_ASN1_STRING_TABLE_find 2015 sk_ASN1_STRING_TABLE_new 2016 -EVP_PKEY_get_RSA 2017 -EVP_PKEY_get_DH 2018 -EVP_PKEY_get_DSA 2019 +EVP_PKEY_rget_RSA 2017 +EVP_PKEY_rget_DH 2018 +EVP_PKEY_rget_DSA 2019 X509_PURPOSE_cleanup 2020 ASN1_STRING_set_default_mask_asc 2021 X509_NAME_add_entry_by_txt 2022 @@ -2026,3 +2026,25 @@ CRYPTO_add_info 2050 d2i_OTHERNAME 2051 OTHERNAME_free 2052 X509_cmp 2053 +PEM_write_PUBKEY 2054 +PEM_write_bio_RSA_PUBKEY 2055 +d2i_RSA_PUBKEY_fp 2056 +EVP_PKEY_rset_DSA 2057 +X509_load_cert_crl_file 2058 +i2d_RSA_PUBKEY 2059 +PEM_read_RSA_PUBKEY 2060 +i2d_DSA_PUBKEY 2061 +i2d_RSA_PUBKEY_bio 2062 +i2d_PUBKEY 2063 +PEM_read_bio_PUBKEY 2064 +PEM_read_PUBKEY 2065 +d2i_RSA_PUBKEY 2066 +d2i_DSA_PUBKEY 2067 +d2i_RSA_PUBKEY_bio 2068 +d2i_PUBKEY 2069 +EVP_PKEY_rset_RSA 2070 +PEM_read_bio_RSA_PUBKEY 2071 +PEM_write_RSA_PUBKEY 2072 +EVP_PKEY_rset_DH 2073 +i2d_RSA_PUBKEY_fp 2074 +PEM_write_bio_PUBKEY 2075 -- GitLab