Transparent support for PKCS#8 private keys in RSA/DSA.
authorDr. Stephen Henson <steve@openssl.org>
Sun, 21 Nov 1999 22:28:31 +0000 (22:28 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 21 Nov 1999 22:28:31 +0000 (22:28 +0000)
New universal public key format.

Fix CRL+cert load problem in by_file.c

Make verify report errors when loading files or dirs

18 files changed:
CHANGES
apps/dsa.c
apps/rsa.c
apps/verify.c
apps/x509.c
crypto/asn1/asn1.h
crypto/asn1/asn1_err.c
crypto/asn1/x_pubkey.c
crypto/evp/evp.h
crypto/evp/p_lib.c
crypto/pem/pem.h
crypto/pem/pem_all.c
crypto/x509/by_file.c
crypto/x509/x509.h
crypto/x509/x509_err.c
crypto/x509/x509_vfy.h
crypto/x509/x_all.c
util/libeay.num

diff --git a/CHANGES b/CHANGES
index a7516c4..56d2c6e 100644 (file)
--- 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]
 
index 85c62b9..a5ff647 100644 (file)
@@ -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);
index ee1365a..219bdd6 100644 (file)
@@ -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);
index 840fda9..4166b92 100644 (file)
@@ -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();
index f56244c..a6b5deb 100644 (file)
@@ -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)
                                {
index bf48104..ab89027 100644 (file)
@@ -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
index 1167029..6d11e13 100644 (file)
@@ -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"},
index 8adaeba..1740df7 100644 (file)
@@ -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;
+}
index f249dae..eb592f0 100644 (file)
@@ -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,
index dba0852..14ad90c 100644 (file)
@@ -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);
index ce2c1a3..9260a11 100644 (file)
@@ -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,
index 80f4037..93f5d7b 100644 (file)
@@ -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);
index 0457f01..78b4c47 100644 (file)
@@ -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 */
 
index d3d8030..f35a614 100644 (file)
@@ -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
index 0a0b704..58e13c6 100644 (file)
@@ -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"},
index 39fa056..9891a69 100644 (file)
@@ -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
 
 
index 354d4c3..4973c18 100644 (file)
@@ -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
index b08c1fa..a7003bd 100755 (executable)
@@ -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