summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES44
-rw-r--r--apps/dsa.c8
-rw-r--r--apps/rsa.c21
-rw-r--r--apps/verify.c20
-rw-r--r--apps/x509.c20
-rw-r--r--crypto/asn1/asn1.h2
-rw-r--r--crypto/asn1/asn1_err.c2
-rw-r--r--crypto/asn1/x_pubkey.c107
-rw-r--r--crypto/evp/evp.h9
-rw-r--r--crypto/evp/p_lib.c27
-rw-r--r--crypto/pem/pem.h6
-rw-r--r--crypto/pem/pem_all.c86
-rw-r--r--crypto/x509/by_file.c54
-rw-r--r--crypto/x509/x509.h23
-rw-r--r--crypto/x509/x509_err.c1
-rw-r--r--crypto/x509/x509_vfy.h1
-rw-r--r--crypto/x509/x_all.c40
-rwxr-xr-xutil/libeay.num44
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)
@@ -640,6 +643,21 @@ bad:
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)
{
unsigned char *d;
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 <openssl/pkcs7.h>
#include <openssl/pem.h>
+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 1