Alt-Crypt-OpenSSL-PKCS12-Broadbean
view release on metacpan or search on metacpan
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#define NEED_newCONSTSUB
#include "ppport.h"
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
OSSL_PROVIDER *legacy = NULL;
OSSL_PROVIDER *deflt = NULL;
#endif
#define NOKEYS 0x1
#define NOCERTS 0x2
#define INFO 0x4
#define CLCERTS 0x8
#define CACERTS 0x10
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define PKCS12_SAFEBAG_get0_p8inf(o) ((o)->value.keybag)
#define PKCS12_SAFEBAG_get0_attr PKCS12_get_attr
#define PKCS12_SAFEBAG_get_bag_nid M_PKCS12_cert_bag_type
#define PKCS12_SAFEBAG_get_nid M_PKCS12_bag_type
#define PKCS12_SAFEBAG_get1_cert PKCS12_certbag2x509
#define PKCS12_SAFEBAG_get0_safes(o) ((o)->value.safes)
#define PKCS12_SAFEBAG_get0_type(o) (o)->type
#define PKCS8_pkey_get0_attrs(o) ((o)->attributes)
#define PKCS12_SAFEBAG_get0_attrs(o) ((o)->attrib)
#define CONST_PKCS8_PRIV_KEY_INFO PKCS8_PRIV_KEY_INFO
#define CONST_X509_ALGOR X509_ALGOR
#define CONST_X509_SIG X509_SIG
#define CONST_ASN1_TYPE ASN1_TYPE
#define CONST_STACK_OF(o) STACK_OF(o)
#define CONST_X509_NAME X509_NAME
#define CONST_ASN1_INTEGER ASN1_INTEGER
#define CONST_ASN1_OBJECT ASN1_OBJECT
#define CONST_ASN1_OCTET_STRING ASN1_OCTET_STRING
#define CONST_VOID void
#else
#define CONST_PKCS8_PRIV_KEY_INFO const PKCS8_PRIV_KEY_INFO
#define CONST_X509_ALGOR const X509_ALGOR
#define CONST_X509_SIG const X509_SIG
#define CONST_ASN1_TYPE const ASN1_TYPE
#define CONST_STACK_OF(o) const STACK_OF(o)
#define CONST_X509_NAME const X509_NAME
#define CONST_ASN1_INTEGER const ASN1_INTEGER
#define CONST_ASN1_OBJECT const ASN1_OBJECT
#define CONST_ASN1_OCTET_STRING const ASN1_OCTET_STRING
#define CONST_VOID const void
#endif
const EVP_CIPHER *enc;
int dump_certs_pkeys_bags(pTHX_ BIO *out, CONST_STACK_OF(PKCS12_SAFEBAG) *bags,
const char *pass, int passlen, int options,
char *pempass, const EVP_CIPHER *enc, HV* hash);
static int alg_print(pTHX_ BIO *bio, CONST_X509_ALGOR *alg, HV* hash);
void print_attribute(pTHX_ BIO *out, CONST_ASN1_TYPE *av, char **value);
int print_attribs(pTHX_ BIO *out, CONST_STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name, HV *hash);
void hex_prin(BIO *out, unsigned char *buf, int len);
void dump_cert_text(BIO *out, X509 *x);
SV * get_cert_subject_name(pTHX_ X509 *x);
SV * get_cert_issuer_name(pTHX_ X509 *x);
#define CHECK_OPEN_SSL(p_result) if (!(p_result)) croakSSL(__FILE__, __LINE__);
#define PACKAGE_CROAK(p_message) croak("%s", (p_message))
#define CHECK_NEW(p_var, p_size, p_type) \
if (New(0, p_var, p_size, p_type) == NULL) \
{ PACKAGE_CROAK("unable to alloc buffer"); }
/* fake our package name */
typedef PKCS12* Crypt__OpenSSL__PKCS12;
void croakSSL(char* p_file, int p_line) {
const char* errorReason;
/* Just return the top error on the stack */
errorReason = ERR_reason_error_string(ERR_get_error());
ERR_clear_error();
croak("%s:%d: OpenSSL error: %s", p_file, p_line, errorReason);
}
EVP_PKEY* _load_pkey(char* keyString, EVP_PKEY*(*p_loader)(BIO*, EVP_PKEY**, pem_password_cb*, void*)) {
EVP_PKEY* pkey;
BIO* stringBIO;
if (!strncmp(keyString, "----", 4)) {
CHECK_OPEN_SSL(stringBIO = BIO_new_mem_buf(keyString, strlen(keyString)));
} else {
CHECK_OPEN_SSL(stringBIO = BIO_new_file(keyString, "r"));
}
pkey = p_loader(stringBIO, NULL, NULL, NULL);
(void)BIO_set_close(stringBIO, BIO_CLOSE);
BIO_free_all(stringBIO);
CHECK_OPEN_SSL(pkey);
return pkey;
}
STACK_OF(X509)* _load_cert_chain(char* keyString, STACK_OF(X509_INFO)*(*p_loader)(BIO*, STACK_OF(X509_INFO)*, pem_password_cb*, void*)) {
int i;
STACK_OF(X509_INFO) *xis = NULL;
X509_INFO *xi = NULL;
BIO* stringBIO;
STACK_OF(X509) *stack = sk_X509_new_null();
if (!strncmp(keyString, "----", 4)) {
CHECK_OPEN_SSL(stringBIO = BIO_new_mem_buf(keyString, strlen(keyString)));
} else {
CHECK_OPEN_SSL(stringBIO = BIO_new_file(keyString, "r"));
}
xis = p_loader(stringBIO, NULL, NULL, NULL);
for (i = 0; i < sk_X509_INFO_num(xis); i++) {
xi = sk_X509_INFO_value(xis, i);
if (xi->x509 != NULL && stack != NULL) {
CHECK_OPEN_SSL(xi->x509);
if (!sk_X509_push(stack, xi->x509))
goto end;
xi->x509 = NULL;
}
}
end:
sk_X509_INFO_pop_free(xis, X509_INFO_free);
(void)BIO_set_close(stringBIO, BIO_CLOSE);
BIO_free_all(stringBIO);
return stack;
}
static void sv_bio_error(pTHX_ BIO *bio) {
SV* sv = (SV *)BIO_get_callback_arg(bio);
if (sv) sv_free(sv);
BIO_free_all (bio);
}
SV* extractBioString(pTHX_ BIO* p_stringBio)
{
SV* sv;
char *datap;
long datasize = 0;
CHECK_OPEN_SSL(BIO_flush(p_stringBio) == 1);
datasize = BIO_get_mem_data(p_stringBio, &datap);
sv = newSVpv(datap, datasize);
CHECK_OPEN_SSL(BIO_set_close(p_stringBio, BIO_CLOSE) == 1);
BIO_free(p_stringBio);
return sv;
}
static const char *ssl_error(pTHX) {
BIO *bio;
SV *sv;
STRLEN l;
CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
ERR_print_errors(bio);
sv = extractBioString(aTHX_ bio);
ERR_clear_error();
return SvPV(sv, l);
}
/* these are trimmed from their openssl/apps/pkcs12.c counterparts */
int dump_certs_pkeys_bag (pTHX_ BIO *bio, PKCS12_SAFEBAG *bag, const char *pass, int passlen, int options, char *pempass, const EVP_CIPHER *enc, HV * bag_hv) {
EVP_PKEY *pkey;
X509 *x509;
CONST_PKCS8_PRIV_KEY_INFO *p8 = NULL;
CONST_STACK_OF(X509_ATTRIBUTE) *bag_attrs;
CONST_STACK_OF(X509_ATTRIBUTE) *key_attrs;
bag_attrs = PKCS12_SAFEBAG_get0_attrs(bag);
/* FIXME: Change NULL to default_enc and allow the encryption to ne overridden like no-des */
#ifndef OPENSSL_NO_DES
EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_des_ede3_cbc();
enc = NULL; /*default_enc; */
#else
EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_aes_256_cbc();
enc = default_enc;
#endif
switch (PKCS12_SAFEBAG_get_nid(bag)) {
case NID_keyBag: ;
if (options & NOKEYS) return 1;
p8 = PKCS12_SAFEBAG_get0_p8inf(bag);
if (!(pkey = EVP_PKCS82PKEY (p8))) return 0;
if (options & INFO) {
key_attrs = PKCS8_pkey_get0_attrs(p8);
if (bag_hv) {
SV * value = newSVpvn("key_bag", strlen("key_bag"));
if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
croak("unable to add certificate_bag to the bag_hv");
/* Assign the output to a temporary BIO and free after it is saved to key_sv */
BIO *keybio;
CHECK_OPEN_SSL(keybio = BIO_new(BIO_s_mem()));
PEM_write_bio_PrivateKey (keybio, pkey, enc, NULL, 0, NULL, pempass);
SV * key_sv = extractBioString(aTHX_ keybio);
if((hv_store(bag_hv, "key", strlen("key"), key_sv, 0)) == NULL)
croak("unable to add certificate_bag to the bag_hv");
print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
print_attribs(aTHX_ bio, key_attrs, "key_attributes", bag_hv);
} else {
BIO_printf(bio, "Key bag\n");
print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
print_attribs(aTHX_ bio, key_attrs, "Key Attributes", NULL);
PEM_write_bio_PrivateKey (bio, pkey, enc, NULL, 0, NULL, pempass);
}
} else {
PEM_write_bio_PrivateKey (bio, pkey, enc, NULL, 0, NULL, pempass);
}
EVP_PKEY_free(pkey);
break;
case NID_pkcs8ShroudedKeyBag: ;
if (options & NOKEYS) return 1;
if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
return 0;
if ((pkey = EVP_PKCS82PKEY (p8)) == NULL) {
PKCS8_PRIV_KEY_INFO_free((PKCS8_PRIV_KEY_INFO *) p8);
return 0;
}
if (options & INFO) {
CONST_X509_ALGOR *tp8alg;
#if OPENSSL_VERSION_NUMBER > 0x10100000L
CONST_X509_SIG *tp8;
tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag);
X509_SIG_get0(tp8, &tp8alg, NULL);
#else
tp8alg = bag->value.shkeybag->algor;
#endif
key_attrs = PKCS8_pkey_get0_attrs(p8);
if (bag_hv) {
SV *str_bag = newSVpvn("shrouded_bag", strlen("shrouded_bag"));
HV * parameters_hv = newHV();;
if((hv_store(bag_hv, "type", strlen("type"), str_bag, 0)) == NULL)
croak("unable to add type to the bag_hv");
#if OPENSSL_VERSION_NUMBER > 0x10000000L
alg_print(aTHX_ bio, tp8alg, parameters_hv);
#endif
print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
if((hv_store(bag_hv, "parameters", strlen("parameters"), newRV_inc((SV *) parameters_hv), 0)) == NULL)
croak("unable to add bag_attributes to the bag_hv");
SV *str_key_bag = newSVpvn("shrouded_keybag", strlen("shrouded_keybag"));
if((hv_store(bag_hv, "type", strlen("type"), str_key_bag, 0)) == NULL)
croak("unable to add type to the bag_hv");
print_attribs(aTHX_ bio, key_attrs, "key_attributes", bag_hv);
/* Assign the output to a temporary BIO and free after it is saved to key_sv */
BIO *keybio;
CHECK_OPEN_SSL(keybio = BIO_new(BIO_s_mem()));
PEM_write_bio_PrivateKey (keybio, pkey, enc, NULL, 0, NULL, pempass);
SV * key_sv = extractBioString(aTHX_ keybio);
if((hv_store(bag_hv, "key", strlen("key"), key_sv, 0)) == NULL)
croak("unable to add certificate_bag to the bag_hv");
} else {
BIO_printf(bio, "Shrouded Keybag: ");
alg_print(aTHX_ bio, tp8alg, NULL);
print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
print_attribs(aTHX_ bio, key_attrs, "Key Attributes", NULL);
PEM_write_bio_PrivateKey (bio, pkey, enc, NULL, 0, NULL, pempass);
}
} else {
PEM_write_bio_PrivateKey (bio, pkey, enc, NULL, 0, NULL, pempass);
}
PKCS8_PRIV_KEY_INFO_free((PKCS8_PRIV_KEY_INFO *)p8);
EVP_PKEY_free(pkey);
break;
croak("unable to add issuer to the bag_hv");
PEM_write_bio_X509 (keybio, x509);
SV * key_sv = extractBioString(aTHX_ keybio);
if((hv_store(bag_hv, "cert", strlen("cert"), key_sv, 0)) == NULL)
croak("unable to add certificate_bag to the bag_hv");
} else
{
BIO_printf(bio, "Certificate bag\n");
print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
dump_cert_text(bio, x509);
PEM_write_bio_X509 (bio, x509);
}
} else {
PEM_write_bio_X509 (bio, x509);
}
X509_free(x509);
break;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
case NID_secretBag:
/*FIXME: Not sure how to test this */
if (options & INFO) {
char * attribute_value = NULL;
if (bag_hv){
SV * value = newSVpvn("secret_bag", strlen("secret_bag"));
if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
croak("unable to add type to the bag_hv");
print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
Newx(attribute_value, 0, char);
print_attribute(aTHX_ bio, PKCS12_SAFEBAG_get0_bag_obj(bag), &attribute_value);
if(hv_store(bag_hv, "bag_value", strlen("bag_value"), newSVpvn(attribute_value, strlen(attribute_value)), 0) == NULL)
croak("unable to add MAC to the bag_hv");
}
else {
BIO_printf(bio, "Secret bag\n");
print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
BIO_printf(bio, "Bag Type: ");
i2a_ASN1_OBJECT(bio, PKCS12_SAFEBAG_get0_bag_type(bag));
BIO_printf(bio, "\nBag Value: ");
print_attribute(aTHX_ bio, PKCS12_SAFEBAG_get0_bag_obj(bag), &attribute_value);
}
Safefree(attribute_value);
} else {
if (!bag_hv)
i2a_ASN1_OBJECT(bio, PKCS12_SAFEBAG_get0_bag_type(bag));
}
break;
#endif
case NID_safeContentsBag:
if (options & INFO) {
if(bag_hv) {
SV * value = newSVpvn("safe_contents_bag", strlen("safe_contents_bag"));
if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
croak("unable to add type to the bag_hv");
print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
dump_certs_pkeys_bags(aTHX_ bio, PKCS12_SAFEBAG_get0_safes(bag),
pass, passlen, options, pempass, enc, bag_hv);
} else {
BIO_printf(bio, "Safe Contents bag\n");
print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
dump_certs_pkeys_bags(aTHX_ bio, PKCS12_SAFEBAG_get0_safes(bag),
pass, passlen, options, pempass, enc, NULL);
}
}
break;
default:
if(bag_hv)
return 1;
BIO_printf(bio, "Warning unsupported bag type: ");
i2a_ASN1_OBJECT(bio, PKCS12_SAFEBAG_get0_type(bag));
BIO_printf(bio, "\n");
}
return 1;
}
int dump_certs_pkeys_bags(pTHX_ BIO *bio, CONST_STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, int passlen, int options, char *pempass, const EVP_CIPHER *enc, HV * hash) {
int i;
AV * bags_av = NULL;
HV * bag_hv = NULL;
if(hash) {
bags_av = newAV();
}
for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
if(hash)
bag_hv = newHV();
if (!dump_certs_pkeys_bag (aTHX_ bio, sk_PKCS12_SAFEBAG_value (bags, i), pass, passlen, options, pempass, enc, bag_hv)) {
return 0;
}
if(hash)
av_push(bags_av, newRV_inc((SV *) bag_hv));
}
if (hash) {
SV **svp = NULL;
char *type;
if (hv_exists(bag_hv, "type", strlen("type"))) {
svp = hv_fetch(bag_hv, "type", strlen("type"), 0);
if (svp != NULL)
type = SvPVbyte_nolen(*svp);
}
if (svp != NULL) {
if (strcmp(type, "safe_contents_bag") == 0 ) {
if((hv_store(hash, "safe_contents_bag", strlen("safe_contents_bag"), newRV_inc((SV *) bags_av), 0)) == NULL)
croak("unable to add bags to the hash");
} else {
if((hv_store(hash, "bags", strlen("bags"), newRV_inc((SV *) bags_av), 0)) == NULL)
croak("unable to add bags to the hash");
}
}
}
return 1;
}
int dump_certs_keys_p12(pTHX_ BIO *bio, PKCS12 *p12, char *pass, int passlen, int options, char *pempass, HV * orig_hash) {
STACK_OF(PKCS7) *asafes;
STACK_OF(PKCS12_SAFEBAG) *bags;
int i, bagnid;
PKCS7 *p7;
HV * bag_hv = NULL;
HV * parameters_hv = NULL;
AV * pkcs7_bags_av = newAV();
AV * pkcs7_enc_bags_av = newAV();
if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) {
croak("Unable to PKCS12_unpack_authsafes");
return 0;
}
for (i = 0; i < sk_PKCS7_num(asafes); i++) {
if (orig_hash) {
parameters_hv = newHV();
bag_hv = newHV();
}
p7 = sk_PKCS7_value(asafes, i);
bagnid = OBJ_obj2nid(p7->type);
if (bagnid == NID_pkcs7_data) {
if (options & INFO) {
if (orig_hash) {
bag_hv = newHV();
av_push(pkcs7_bags_av, newRV_inc((SV *) bag_hv));
}
else
BIO_printf(bio, "PKCS7 Data\n");
}
bags = PKCS12_unpack_p7data(p7);
} else if (bagnid == NID_pkcs7_encrypted) {
if (options & INFO) {
if (orig_hash) {
bag_hv = newHV();
if (p7->d.encrypted != NULL)
alg_print(aTHX_ bio, p7->d.encrypted->enc_data->algorithm, parameters_hv);
if((hv_store(bag_hv, "parameters", strlen("parameters"), newRV_inc((SV *) parameters_hv), 0)) == NULL)
croak("unable to add parameters to the hash");
if((hv_store(orig_hash, "pkcs7_encrypted_data", strlen("pkcs7_encrypted_data"), newRV_inc((SV *) bag_hv), 0)) == NULL)
croak("unable to add pkcs7_encrypted_data to the orig_hash");
av_push(pkcs7_enc_bags_av, newRV_inc((SV *) bag_hv));
} else {
BIO_printf(bio, "PKCS7 Encrypted data: ");
if (p7->d.encrypted == NULL) {
BIO_printf(bio, "<no data>\n");
} else {
alg_print(aTHX_ bio, p7->d.encrypted->enc_data->algorithm, NULL);
}
}
}
bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
} else {
continue;
}
if (bags == NULL) return 0;
if (!dump_certs_pkeys_bags(aTHX_ bio, bags, pass, passlen, options, pempass, enc, bag_hv)) {
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
return 0;
}
if (orig_hash) {
if((hv_store(orig_hash, "pkcs7_data", strlen("pkcs7_data"), newRV_inc((SV *) pkcs7_bags_av), 0)) == NULL)
croak("unable to add bags to the hash");
if((hv_store(orig_hash, "pkcs7_encrypted_data", strlen("pkcs7_encrypted_data"), newRV_inc((SV *) pkcs7_enc_bags_av), 0)) == NULL)
croak("unable to add bags to the hash");
}
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
}
sk_PKCS7_pop_free(asafes, PKCS7_free);
return 1;
}
#ifdef TIM
# define B_FORMAT_TEXT 0x8000
# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */
int FMT_istext(int format)
{
return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT;
}
BIO *dup_bio_err(int format)
{
BIO *b = BIO_new_fp(stderr,
BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
return b;
}
#endif
static unsigned long nmflag = 0;
static char nmflag_set = 0;
# define XN_FLAG_SPC_EQ (1 << 23)/* Put spaces round '=' */
#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
ASN1_STRFLGS_ESC_QUOTE | \
ASN1_STRFLGS_ESC_CTRL | \
ASN1_STRFLGS_ESC_MSB)
unsigned long get_nameopt(void)
{
return
nmflag_set ? nmflag : ESC_FLAGS | XN_FLAG_SEP_CPLUS_SPC | ASN1_STRFLGS_UTF8_CONVERT | XN_FLAG_SPC_EQ;
}
void print_name(BIO *out, const char *title, CONST_X509_NAME *nm)
{
char *buf;
char mline = 0;
int indent = 0;
unsigned long lflags = get_nameopt();
if (out == NULL)
return;
if (title != NULL)
Crypt::OpenSSL::PKCS12
new_from_string(class, string)
SV *class
SV *string
ALIAS:
new_from_file = 1
PREINIT:
BIO *bio;
STRLEN str_len;
char *str_ptr;
CODE:
SvGETMAGIC(string);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
/* FIXME: There should likely be an option for whether to load the legacy provider */
legacy = OSSL_PROVIDER_load(NULL, "legacy");
if (legacy == NULL) {
warn("Failed to load Legacy provider\n");
}
deflt = OSSL_PROVIDER_load(NULL, "default");
if (deflt == NULL) {
OSSL_PROVIDER_unload(legacy);
croak("Failed to load Default provider\n");
}
#endif
if (SvPOKp(string) || SvNOKp(string) || SvIOKp(string)) {
if (ix == 1) {
/* We are not looking up the SV's UTF8 bit because BIO_new_file() accepts
* filename like syscall fopen() which mainly may accept octet sequences
* for UTF-8 in C char*. That's what we get from using SvPV(). Also,
* using SvPV() is not a bug if ASCII input is only allowed. */
str_ptr = SvPV(string, str_len);
} else {
/* To avoid encoding mess, caller is not allowed to provide octets from
* UTF-8 encoded strings. BIO_new_mem_buf() needs octet input only. */
if (SvUTF8(string)) {
croak("PKCS12_new_from: Source string must not be UTF-8 encoded (please use octets)");
}
str_ptr = SvPV(string, str_len);
}
} else {
croak("PKCS12_new_from: Invalid Perl type for string or file was passed (0x%x).", (unsigned int)SvFLAGS(string));
}
if (!str_ptr || !str_len) croak("PKCS12_new_from: No string or file was passed.");
if (ix == 1) {
bio = BIO_new_file(str_ptr, "rb");
} else {
bio = BIO_new_mem_buf(str_ptr, str_len);
}
if (!bio) croak("Failed to create BIO");
/* this can come in any number of ways */
if ((RETVAL = d2i_PKCS12_bio(bio, 0)) == NULL) {
BIO_free_all(bio);
croak("%" SVf ": Couldn't create PKCS12 from d2i_PKCS12_BIO(): %s", SVfARG(class), ssl_error(aTHX));
}
BIO_free_all(bio);
OUTPUT:
RETVAL
# This is called at per-object destruction time.
void
DESTROY(pkcs12)
Crypt::OpenSSL::PKCS12 pkcs12;
CODE:
if (pkcs12) {
PKCS12_free(pkcs12);
}
# This is called via an END block in the Perl module to clean up initialization that happened in BOOT.
void
__PKCS12_cleanup(void)
CODE:
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
#if OPENSSL_VERSION_NUMBER < 0x10100000L
ERR_remove_state(0);
#endif
EVP_cleanup();
SV*
as_string(pkcs12)
Crypt::OpenSSL::PKCS12 pkcs12;
PREINIT:
BIO *bio;
CODE:
CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
if (!(i2d_PKCS12_bio(bio, pkcs12))) {
sv_bio_error(aTHX_ bio);
croak("i2d_PKCS12_bio: %s", ssl_error(aTHX));
}
RETVAL = extractBioString(aTHX_ bio);
OUTPUT:
RETVAL
SV*
mac_ok(pkcs12, pwd = "")
Crypt::OpenSSL::PKCS12 pkcs12
char *pwd
CODE:
if (!(PKCS12_verify_mac(pkcs12, pwd, strlen(pwd)))) {
croak("PKCS12_verify_mac: \n%s", ssl_error(aTHX));
}
RETVAL = (PKCS12_verify_mac(pkcs12, pwd, strlen(pwd))) ? &PL_sv_yes : &PL_sv_no;
OUTPUT:
RETVAL
SV*
changepass(pkcs12, oldpwd = "", newpwd = "")
Crypt::OpenSSL::PKCS12 pkcs12
char *oldpwd
char *newpwd
CODE:
if (!(PKCS12_newpass(pkcs12, oldpwd, newpwd))) {
warn("PKCS12_newpass: %s %s\n%s", oldpwd, newpwd, ssl_error(aTHX));
RETVAL = &PL_sv_no;
} else {
RETVAL = &PL_sv_yes;
}
OUTPUT:
RETVAL
SV*
create(pkcs12, cert_chain_pem = "", pk = "", pass = 0, file = 0, name = "PKCS12 Certificate")
char *cert_chain_pem
char *pk
char *pass
char *file
char *name
PREINIT:
FILE *fp;
EVP_PKEY* pkey;
PKCS12 *p12;
STACK_OF(X509) *cert_chain = NULL;
CODE:
pkey = _load_pkey(pk, PEM_read_bio_PrivateKey);
cert_chain = _load_cert_chain(cert_chain_pem, PEM_X509_INFO_read_bio);
p12 = PKCS12_create(pass, name, pkey, sk_X509_shift(cert_chain), cert_chain, 0, 0, 0, 0, 0);
if (!p12) {
ERR_print_errors_fp(stderr);
croak("Error creating PKCS#12 structure\n");
}
if (!(fp = fopen(file, "wb"))) {
ERR_print_errors_fp(stderr);
croak("Error opening file %s\n", file);
}
i2d_PKCS12_fp(fp, p12);
PKCS12_free(p12);
fclose(fp);
RETVAL = &PL_sv_yes;
OUTPUT:
RETVAL
SV*
create_as_string(pkcs12, cert_chain_pem = "", pk = "", pass = 0, name = "PKCS12 Certificate")
char *cert_chain_pem
char *pk
char *pass
char *name
PREINIT:
BIO *bio;
EVP_PKEY* pkey;
PKCS12 *p12;
STACK_OF(X509) *cert_chain = NULL;
( run in 0.443 second using v1.01-cache-2.11-cpan-acf6aa7dc9e )