1 //
2 //  btls-pkcs12.c
3 //  MonoBtls
4 //
5 //  Created by Martin Baulig on 3/8/16.
6 //  Copyright © 2016 Xamarin. All rights reserved.
7 //
8 
9 #include <btls-pkcs12.h>
10 #include <openssl/pkcs12.h>
11 
12 struct MonoBtlsPkcs12 {
13 	STACK_OF(X509) *certs;
14 	EVP_PKEY *private_key;
15 	CRYPTO_refcount_t references;
16 };
17 
18 MONO_API MonoBtlsPkcs12 *
mono_btls_pkcs12_new(void)19 mono_btls_pkcs12_new (void)
20 {
21 	MonoBtlsPkcs12 *pkcs12 = (MonoBtlsPkcs12 *)OPENSSL_malloc (sizeof (MonoBtlsPkcs12));
22 	if (pkcs12 == NULL)
23 		return NULL;
24 
25 	memset (pkcs12, 0, sizeof(MonoBtlsPkcs12));
26 	pkcs12->certs = sk_X509_new_null ();
27 	pkcs12->references = 1;
28 	return pkcs12;
29 }
30 
31 MONO_API int
mono_btls_pkcs12_get_count(MonoBtlsPkcs12 * pkcs12)32 mono_btls_pkcs12_get_count (MonoBtlsPkcs12 *pkcs12)
33 {
34 	return (int)sk_X509_num (pkcs12->certs);
35 }
36 
37 MONO_API X509 *
mono_btls_pkcs12_get_cert(MonoBtlsPkcs12 * pkcs12,int index)38 mono_btls_pkcs12_get_cert (MonoBtlsPkcs12 *pkcs12, int index)
39 {
40 	X509 *cert;
41 
42 	if ((size_t)index >= sk_X509_num (pkcs12->certs))
43 		return NULL;
44 	cert = sk_X509_value (pkcs12->certs, index);
45 	if (cert)
46 		X509_up_ref (cert);
47 	return cert;
48 }
49 
STACK_OF(X509)50 MONO_API STACK_OF(X509) *
51 mono_btls_pkcs12_get_certs (MonoBtlsPkcs12 *pkcs12)
52 {
53 	return pkcs12->certs;
54 }
55 
56 MONO_API int
mono_btls_pkcs12_free(MonoBtlsPkcs12 * pkcs12)57 mono_btls_pkcs12_free (MonoBtlsPkcs12 *pkcs12)
58 {
59 	if (!CRYPTO_refcount_dec_and_test_zero (&pkcs12->references))
60 		return 0;
61 
62 	sk_X509_pop_free (pkcs12->certs, X509_free);
63 	OPENSSL_free (pkcs12);
64 	return 1;
65 }
66 
67 MONO_API MonoBtlsPkcs12 *
mono_btls_pkcs12_up_ref(MonoBtlsPkcs12 * pkcs12)68 mono_btls_pkcs12_up_ref (MonoBtlsPkcs12 *pkcs12)
69 {
70 	CRYPTO_refcount_inc (&pkcs12->references);
71 	return pkcs12;
72 }
73 
74 MONO_API void
mono_btls_pkcs12_add_cert(MonoBtlsPkcs12 * pkcs12,X509 * x509)75 mono_btls_pkcs12_add_cert (MonoBtlsPkcs12 *pkcs12, X509 *x509)
76 {
77 	X509_up_ref (x509);
78 	sk_X509_push (pkcs12->certs, x509);
79 }
80 
81 MONO_API int
mono_btls_pkcs12_import(MonoBtlsPkcs12 * pkcs12,const void * data,int len,const void * password)82 mono_btls_pkcs12_import (MonoBtlsPkcs12 *pkcs12, const void *data, int len, const void *password)
83 {
84 	CBS cbs;
85 	CBS_init (&cbs, data, len);
86 	return PKCS12_get_key_and_certs (&pkcs12->private_key, pkcs12->certs, &cbs, password);
87 }
88 
89 MONO_API int
mono_btls_pkcs12_has_private_key(MonoBtlsPkcs12 * pkcs12)90 mono_btls_pkcs12_has_private_key (MonoBtlsPkcs12 *pkcs12)
91 {
92 	return pkcs12->private_key != NULL;
93 }
94 
95 MONO_API EVP_PKEY *
mono_btls_pkcs12_get_private_key(MonoBtlsPkcs12 * pkcs12)96 mono_btls_pkcs12_get_private_key (MonoBtlsPkcs12 *pkcs12)
97 {
98 	if (!pkcs12->private_key)
99 		return NULL;
100 	return EVP_PKEY_up_ref (pkcs12->private_key);
101 }
102