Two new PKCS#12 demo programs.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 7 Sep 2000 23:14:26 +0000 (23:14 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 7 Sep 2000 23:14:26 +0000 (23:14 +0000)
Update PKCS12_parse().

Make the keyid in certificate aux info more usable.

CHANGES
FAQ
crypto/asn1/t_x509a.c
crypto/asn1/x_x509a.c
crypto/pkcs12/p12_kiss.c
crypto/x509/x509.h
demos/pkcs12/README [new file with mode: 0644]
demos/pkcs12/pkread.c [new file with mode: 0644]
demos/pkcs12/pkwrite.c [new file with mode: 0644]
doc/apps/smime.pod

diff --git a/CHANGES b/CHANGES
index 01f8d5b87af031f1b539c274c9452af88f8f6938..dcb354f88ffda31c45a5f78bb97251455b933913 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 0.9.5a and 0.9.6  [xx XXX 2000]
 
+  *) Add two demo programs for PKCS12_parse() and PKCS12_create().
+     Update PKCS12_parse() so it copies the friendlyName and the
+     keyid to the certificates aux info.
+     [Steve Henson]
+
   *) Fix bug in PKCS7_verify() which caused an infinite loop
      if there was more than one signature.
      [Sven Uszpelkat <su@celocom.de>]
diff --git a/FAQ b/FAQ
index 6e34953c11ee19ca3d73f5ba6acf1a65e27cf85b..4497b1c7f438126fc0aea76b162a69bc8c91b2b8 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -10,6 +10,7 @@ OpenSSL  -  Frequently Asked Questions
 * Why does the linker complain about undefined symbols?
 * Where can I get a compiled version of OpenSSL?
 * I've compiled a program under Windows and it crashes: why?
+* I've tried using <M_some_evil_pkcs12_macro> and I get errors why?
 * I've called <some function> and it fails, why?
 * I just get a load of numbers for the error output, what do they mean?
 * Why do I get errors about unknown algorithms?
@@ -181,6 +182,17 @@ otherwise the conflict will cause a program to crash: typically on the
 first BIO related read or write operation.
 
 
+* I've tried using <M_some_evil_pkcs12_macro> and I get errors why?
+
+This usually happens when you try compiling something using the PKCS#12
+macros with a C++ compiler. There is hardly ever any need to use the
+PKCS#12 macros in a program, it is much easier to parse and create
+PKCS#12 files using the PKCS12_parse() and PKCS12_create() functions
+documented in doc/openssl.txt and with examples in demos/pkcs12. The
+'pkcs12' application has to use the macros because it prints out 
+debugging information.
+
+
 * I've called <some function> and it fails, why?
 
 Before submitting a report or asking in one of the mailing lists, you
index a18ebb586ce88512cb7b943986a30e2316f7beb7..f06af5b576bf038dd0d764a540a11f101f62bdb4 100644 (file)
@@ -98,5 +98,13 @@ int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
        } else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
        if(aux->alias) BIO_printf(out, "%*sAlias: %s\n", indent, "",
                                                        aux->alias->data);
+       if(aux->keyid) {
+               BIO_printf(out, "%*sKey Id: ", indent, "");
+               for(i = 0; i < aux->keyid->length; i++) 
+                       BIO_printf(out, "%s%02X", 
+                               i ? ":" : "",
+                               aux->keyid->data[i]);
+               BIO_write(out,"\n",1);
+       }
        return 1;
 }
index 42807cd334654e605cf837dec43a1b228d97cc05..ebcce87bf20a01c75801b8b530be05636b6f15d3 100644 (file)
@@ -153,6 +153,14 @@ int X509_alias_set1(X509 *x, unsigned char *name, int len)
        return ASN1_STRING_set(aux->alias, name, len);
 }
 
+int X509_keyid_set1(X509 *x, unsigned char *id, int len)
+{
+       X509_CERT_AUX *aux;
+       if(!(aux = aux_get(x))) return 0;
+       if(!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) return 0;
+       return ASN1_STRING_set(aux->keyid, id, len);
+}
+
 unsigned char *X509_alias_get0(X509 *x, int *len)
 {
        if(!x->aux || !x->aux->alias) return NULL;
index 3b36cfa46cadc96460f1bfb8ac72b83e04754ba7..368c98765cbc89c901d7870bb665c776ece04fb6 100644 (file)
@@ -86,21 +86,18 @@ int PKCS12_parse (PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
 
        /* Check for NULL PKCS12 structure */
 
-       if(!p12)
-               {
+       if(!p12) {
                PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER);
                return 0;
-               }
+       }
 
        /* Allocate stack for ca certificates if needed */
-       if ((ca != NULL) && (*ca == NULL))
-               {
-               if (!(*ca = sk_X509_new(NULL)))
-                       {
+       if ((ca != NULL) && (*ca == NULL)) {
+               if (!(*ca = sk_X509_new(NULL))) {
                        PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE);
                        return 0;
-                       }
                }
+       }
 
        if(pkey) *pkey = NULL;
        if(cert) *cert = NULL;
@@ -206,12 +203,17 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
 {
        PKCS8_PRIV_KEY_INFO *p8;
        X509 *x509;
-       ASN1_OCTET_STRING *lkey = NULL;
+       ASN1_OCTET_STRING *lkey = NULL, *ckid = NULL;
        ASN1_TYPE *attrib;
+       ASN1_BMPSTRING *fname = NULL;
 
+       if ((attrib = PKCS12_get_attr (bag, NID_friendlyName)))
+               fname = attrib->value.bmpstring;
 
-       if ((attrib = PKCS12_get_attr (bag, NID_localKeyID)))
-                                           lkey = attrib->value.octet_string;
+       if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) {
+               lkey = attrib->value.octet_string;
+               ckid = lkey;
+       }
 
        /* Check for any local key id matching (if needed) */
        if (lkey && ((*keymatch & MATCH_ALL) != MATCH_ALL)) {
@@ -247,6 +249,18 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
                if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate )
                                                                 return 1;
                if (!(x509 = M_PKCS12_certbag2x509(bag))) return 0;
+               if(ckid) X509_keyid_set1(x509, ckid->data, ckid->length);
+               if(fname) {
+                       int len;
+                       unsigned char *data;
+                       len = ASN1_STRING_to_UTF8(&data, fname);
+                       if(len > 0) {
+                               X509_alias_set1(x509, data, len);
+                               OPENSSL_free(data);
+                       }
+               }
+
+
                if (lkey) {
                        *keymatch |= MATCH_CERT;
                        if (cert) *cert = x509;
index ae0ebd89d7ba4db9eaf506f94ff2742cd11618b4..813c8adffd7a93eb00c0cdf1593b81d2939ced63 100644 (file)
@@ -912,6 +912,7 @@ int         i2d_X509_CERT_AUX(X509_CERT_AUX *a,unsigned char **pp);
 X509_CERT_AUX *        d2i_X509_CERT_AUX(X509_CERT_AUX **a,unsigned char **pp,
                                                                long length);
 int X509_alias_set1(X509 *x, unsigned char *name, int len);
+int X509_keyid_set1(X509 *x, unsigned char *id, int len);
 unsigned char * X509_alias_get0(X509 *x, int *len);
 int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int);
 int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);
diff --git a/demos/pkcs12/README b/demos/pkcs12/README
new file mode 100644 (file)
index 0000000..c87434b
--- /dev/null
@@ -0,0 +1,3 @@
+PKCS#12 demo applications
+
+Written by Steve Henson.
diff --git a/demos/pkcs12/pkread.c b/demos/pkcs12/pkread.c
new file mode 100644 (file)
index 0000000..8e1b686
--- /dev/null
@@ -0,0 +1,61 @@
+/* pkread.c */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+
+/* Simple PKCS#12 file reader */
+
+int main(int argc, char **argv)
+{
+       FILE *fp;
+       EVP_PKEY *pkey;
+       X509 *cert;
+       STACK_OF(X509) *ca = NULL;
+       PKCS12 *p12;
+       int i;
+       if (argc != 4) {
+               fprintf(stderr, "Usage: pkread p12file password opfile\n");
+               exit (1);
+       }
+       SSLeay_add_all_algorithms();
+       ERR_load_crypto_strings();
+       if (!(fp = fopen(argv[1], "rb"))) {
+               fprintf(stderr, "Error opening file %s\n", argv[1]);
+               exit(1);
+       }
+       p12 = d2i_PKCS12_fp(fp, NULL);
+       fclose (fp);
+       if (!p12) {
+               fprintf(stderr, "Error reading PKCS#12 file\n");
+               ERR_print_errors_fp(stderr);
+               exit (1);
+       }
+       if (!PKCS12_parse(p12, argv[2], &pkey, &cert, &ca)) {
+               fprintf(stderr, "Error parsing PKCS#12 file\n");
+               ERR_print_errors_fp(stderr);
+               exit (1);
+       }
+       PKCS12_free(p12);
+       if (!(fp = fopen(argv[3], "w"))) {
+               fprintf(stderr, "Error opening file %s\n", argv[1]);
+               exit(1);
+       }
+       if (pkey) {
+               fprintf(fp, "***Private Key***\n");
+               PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
+       }
+       if (cert) {
+               fprintf(fp, "***User Certificate***\n");
+               PEM_write_X509_AUX(fp, cert);
+       }
+       if (ca && sk_num(ca)) {
+               fprintf(fp, "***Other Certificates***\n");
+               for (i = 0; i < sk_X509_num(ca); i++) 
+                   PEM_write_X509_AUX(fp, sk_X509_value(ca, i));
+       }
+       fclose(fp);
+       return 0;
+}
diff --git a/demos/pkcs12/pkwrite.c b/demos/pkcs12/pkwrite.c
new file mode 100644 (file)
index 0000000..15f839d
--- /dev/null
@@ -0,0 +1,46 @@
+/* pkwrite.c */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+
+/* Simple PKCS#12 file creator */
+
+int main(int argc, char **argv)
+{
+       FILE *fp;
+       EVP_PKEY *pkey;
+       X509 *cert;
+       PKCS12 *p12;
+       if (argc != 5) {
+               fprintf(stderr, "Usage: pkwrite infile password name p12file\n");
+               exit(1);
+       }
+       SSLeay_add_all_algorithms();
+       ERR_load_crypto_strings();
+       if (!(fp = fopen(argv[1], "r"))) {
+               fprintf(stderr, "Error opening file %s\n", argv[1]);
+               exit(1);
+       }
+       cert = PEM_read_X509(fp, NULL, NULL, NULL);
+       rewind(fp);
+       pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
+       fclose(fp);
+       p12 = PKCS12_create(argv[2], argv[3], pkey, cert, NULL, 0,0,0,0,0);
+       if(!p12) {
+               fprintf(stderr, "Error creating PKCS#12 structure\n");
+               ERR_print_errors_fp(stderr);
+               exit(1);
+       }
+       if (!(fp = fopen(argv[4], "wb"))) {
+               fprintf(stderr, "Error opening file %s\n", argv[1]);
+               ERR_print_errors_fp(stderr);
+               exit(1);
+       }
+       i2d_PKCS12_fp(fp, p12);
+       PKCS12_free(p12);
+       fclose(fp);
+       return 0;
+}
index eee9d049ca022648315dfe98397853c46dc74936..4ab53322c506867d55480969605eae8536327c9e 100644 (file)
@@ -23,6 +23,7 @@ B<openssl> B<smime>
 [B<-recip  file>]
 [B<-in file>]
 [B<-inform SMIME|PEM|DER>]
+[B<-passin arg>]
 [B<-inkey file>]
 [B<-out file>]
 [B<-outform SMIME|PEM|DER>]
@@ -203,6 +204,11 @@ corresponding certificate. If this option is not specified then the
 private key must be included in the certificate file specified with
 the B<-recip> or B<-signer> file.
 
+=item B<-passin arg>
+
+the private key password source. For more information about the format of B<arg>
+see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)|openssl(1)>.
+
 =item B<-rand file(s)>
 
 a file or files containing random data used to seed the random number