Xamarin Public Jenkins (auto-signing) 0abdbe5a7d Imported Upstream version 5.18.0.142
Former-commit-id: 7467d4b717762eeaf652d77f1486dd11ffb1ff1f
2018-10-09 08:20:59 +00:00

113 lines
2.4 KiB
C

//
// btls-pkcs12.c
// MonoBtls
//
// Created by Martin Baulig on 3/8/16.
// Copyright © 2016 Xamarin. All rights reserved.
//
#include "btls-pkcs12.h"
#include <openssl/pkcs12.h>
struct MonoBtlsPkcs12 {
STACK_OF(X509) *certs;
EVP_PKEY *private_key;
CRYPTO_refcount_t references;
};
MONO_API MonoBtlsPkcs12 *
mono_btls_pkcs12_new (void)
{
MonoBtlsPkcs12 *pkcs12 = (MonoBtlsPkcs12 *)OPENSSL_malloc (sizeof (MonoBtlsPkcs12));
if (pkcs12 == NULL)
return NULL;
memset (pkcs12, 0, sizeof(MonoBtlsPkcs12));
pkcs12->certs = sk_X509_new_null ();
pkcs12->references = 1;
return pkcs12;
}
MONO_API int
mono_btls_pkcs12_get_count (MonoBtlsPkcs12 *pkcs12)
{
return (int)sk_X509_num (pkcs12->certs);
}
MONO_API X509 *
mono_btls_pkcs12_get_cert (MonoBtlsPkcs12 *pkcs12, int index)
{
X509 *cert;
if ((size_t)index >= sk_X509_num (pkcs12->certs))
return NULL;
cert = sk_X509_value (pkcs12->certs, index);
if (cert)
X509_up_ref (cert);
return cert;
}
MONO_API STACK_OF(X509) *
mono_btls_pkcs12_get_certs (MonoBtlsPkcs12 *pkcs12)
{
return pkcs12->certs;
}
MONO_API int
mono_btls_pkcs12_free (MonoBtlsPkcs12 *pkcs12)
{
if (!CRYPTO_refcount_dec_and_test_zero (&pkcs12->references))
return 0;
sk_X509_pop_free (pkcs12->certs, X509_free);
OPENSSL_free (pkcs12);
return 1;
}
MONO_API MonoBtlsPkcs12 *
mono_btls_pkcs12_up_ref (MonoBtlsPkcs12 *pkcs12)
{
CRYPTO_refcount_inc (&pkcs12->references);
return pkcs12;
}
MONO_API void
mono_btls_pkcs12_add_cert (MonoBtlsPkcs12 *pkcs12, X509 *x509)
{
X509_up_ref (x509);
sk_X509_push (pkcs12->certs, x509);
}
MONO_API int
mono_btls_pkcs12_import (MonoBtlsPkcs12 *pkcs12, const void *data, int len, const void *password)
{
CBS cbs;
CBS_init (&cbs, data, len);
int ret;
ret = PKCS12_get_key_and_certs (&pkcs12->private_key, pkcs12->certs, &cbs, password);
if ((ret == 1) || (password && strlen (password) > 0))
return ret;
// When passed an empty password, we try both NULL and the empty string.
CBS_init (&cbs, data, len);
if (password)
return PKCS12_get_key_and_certs (&pkcs12->private_key, pkcs12->certs, &cbs, NULL);
else
return PKCS12_get_key_and_certs (&pkcs12->private_key, pkcs12->certs, &cbs, "");
}
MONO_API int
mono_btls_pkcs12_has_private_key (MonoBtlsPkcs12 *pkcs12)
{
return pkcs12->private_key != NULL;
}
MONO_API EVP_PKEY *
mono_btls_pkcs12_get_private_key (MonoBtlsPkcs12 *pkcs12)
{
if (!pkcs12->private_key)
return NULL;
return EVP_PKEY_up_ref (pkcs12->private_key);
}