Two new PKCS#12 demo programs.

Update PKCS12_parse().

Make the keyid in certificate aux info more usable.
This commit is contained in:
Dr. Stephen Henson 2000-09-07 23:14:26 +00:00
parent f50c11ca40
commit 84b65340e1
10 changed files with 175 additions and 11 deletions

View File

@ -4,6 +4,11 @@
Changes between 0.9.5a and 0.9.6 [xx XXX 2000] 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 *) Fix bug in PKCS7_verify() which caused an infinite loop
if there was more than one signature. if there was more than one signature.
[Sven Uszpelkat <su@celocom.de>] [Sven Uszpelkat <su@celocom.de>]

12
FAQ
View File

@ -10,6 +10,7 @@ OpenSSL - Frequently Asked Questions
* Why does the linker complain about undefined symbols? * Why does the linker complain about undefined symbols?
* Where can I get a compiled version of OpenSSL? * Where can I get a compiled version of OpenSSL?
* I've compiled a program under Windows and it crashes: why? * 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've called <some function> and it fails, why?
* I just get a load of numbers for the error output, what do they mean? * I just get a load of numbers for the error output, what do they mean?
* Why do I get errors about unknown algorithms? * 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. 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? * I've called <some function> and it fails, why?
Before submitting a report or asking in one of the mailing lists, you Before submitting a report or asking in one of the mailing lists, you

View 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, ""); } else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
if(aux->alias) BIO_printf(out, "%*sAlias: %s\n", indent, "", if(aux->alias) BIO_printf(out, "%*sAlias: %s\n", indent, "",
aux->alias->data); 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; return 1;
} }

View File

@ -153,6 +153,14 @@ int X509_alias_set1(X509 *x, unsigned char *name, int len)
return ASN1_STRING_set(aux->alias, name, 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) unsigned char *X509_alias_get0(X509 *x, int *len)
{ {
if(!x->aux || !x->aux->alias) return NULL; if(!x->aux || !x->aux->alias) return NULL;

View File

@ -86,17 +86,14 @@ int PKCS12_parse (PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
/* Check for NULL PKCS12 structure */ /* Check for NULL PKCS12 structure */
if(!p12) if(!p12) {
{
PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER); PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER);
return 0; return 0;
} }
/* Allocate stack for ca certificates if needed */ /* Allocate stack for ca certificates if needed */
if ((ca != NULL) && (*ca == NULL)) if ((ca != NULL) && (*ca == NULL)) {
{ if (!(*ca = sk_X509_new(NULL))) {
if (!(*ca = sk_X509_new(NULL)))
{
PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE); PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE);
return 0; return 0;
} }
@ -206,12 +203,17 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
{ {
PKCS8_PRIV_KEY_INFO *p8; PKCS8_PRIV_KEY_INFO *p8;
X509 *x509; X509 *x509;
ASN1_OCTET_STRING *lkey = NULL; ASN1_OCTET_STRING *lkey = NULL, *ckid = NULL;
ASN1_TYPE *attrib; 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))) if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) {
lkey = attrib->value.octet_string; lkey = attrib->value.octet_string;
ckid = lkey;
}
/* Check for any local key id matching (if needed) */ /* Check for any local key id matching (if needed) */
if (lkey && ((*keymatch & MATCH_ALL) != MATCH_ALL)) { 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 ) if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate )
return 1; return 1;
if (!(x509 = M_PKCS12_certbag2x509(bag))) return 0; 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) { if (lkey) {
*keymatch |= MATCH_CERT; *keymatch |= MATCH_CERT;
if (cert) *cert = x509; if (cert) *cert = x509;

View 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, X509_CERT_AUX * d2i_X509_CERT_AUX(X509_CERT_AUX **a,unsigned char **pp,
long length); long length);
int X509_alias_set1(X509 *x, unsigned char *name, int len); 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); unsigned char * X509_alias_get0(X509 *x, int *len);
int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int); int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int);
int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj); int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);

3
demos/pkcs12/README Normal file
View File

@ -0,0 +1,3 @@
PKCS#12 demo applications
Written by Steve Henson.

61
demos/pkcs12/pkread.c Normal file
View File

@ -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;
}

46
demos/pkcs12/pkwrite.c Normal file
View File

@ -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;
}

View File

@ -23,6 +23,7 @@ B<openssl> B<smime>
[B<-recip file>] [B<-recip file>]
[B<-in file>] [B<-in file>]
[B<-inform SMIME|PEM|DER>] [B<-inform SMIME|PEM|DER>]
[B<-passin arg>]
[B<-inkey file>] [B<-inkey file>]
[B<-out file>] [B<-out file>]
[B<-outform SMIME|PEM|DER>] [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 private key must be included in the certificate file specified with
the B<-recip> or B<-signer> file. 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)> =item B<-rand file(s)>
a file or files containing random data used to seed the random number a file or files containing random data used to seed the random number