How to load a PKCS#12 file in OpenSSL programmatically?
Asked Answered
Q

3

20

In an SSL Server Application based on OpenSSL, how can we load a PKCS#12 file programmatically?

Also, can I load a PKCS#12 file having Certificate, Key & CAs in the same file in OpenSSL?

Quintero answered 16/6, 2011 at 12:27 Comment(0)
I
44

Yes you can load a PKCS#12 file containing certificate, key and CAs in the same file with OpenSSL.

  • Use d2i_PKCS12_fp() or d2i_PKCS12_bio() to load the PKCS#12 file.
  • Optionally use PKCS12_verify_mac() to verify the password.
  • Use PKCS12_parse() which decrypts and extracts key, certificate and CA chain for you.

From openssl-1.0.0d/demos/pkcs12/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);
    }
    OpenSSL_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_X509_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));
    }

    sk_X509_pop_free(ca, X509_free);
    X509_free(cert);
    EVP_PKEY_free(pkey);

    fclose(fp);
    return 0;
}
Irrigate answered 16/6, 2011 at 17:10 Comment(4)
@Mathias The above code u gave is used to read an DER encode P12 certificate . is there any API to read PEM encoded P12 certificateExertion
@Balamurugan: I've never seen a PEM-encoded PKCS#12 file or software that supported it.Irrigate
I wonder if you can expand this answer so it parses the PKCS12 structure without leaking memory (ie, so it is suitable for use in a long-running program). In particular, PKCS12_parse seems to leak about 4kB.Mcburney
@Jean-PaulCalderone: I added the additional cleanups of ca, cert and pkey. I still have a leak with OpenSSL 0.9.8 but not with 1.0.1.Irrigate
Y
3

Be warned that the code writes the certs out as trusted certificates (encrypted). If you want unencrypted certificates, change the calls to PEM_write_X509_AUX() to PEM_write_X509().

Yoho answered 7/6, 2013 at 18:32 Comment(2)
That text should really be in the comments.Logsdon
This was my issue was the tags were BEGIN TRUSTED CERTIFICATE instead of Just BEGIN CERTIFICATEPreferable
K
0

Try man SSL, which gives you a list of OpenSSL functions. Something like SSL_load_client_CA_file might suit your needs; it depends if the certificate is in a file on disk or already in memory. There are lots of helper functions, one of them will do the trick. Also check out man PEM for PEM handling routines.

Edit: Hm, maybe a combination of d2i_PKCS12_fp and PKCS12_parse (both available from <openssl/pkcs12.h>) lets you read a certificate from file and parse it.

Keeter answered 16/6, 2011 at 12:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.