[pkg-opensc-commit] [pkcs11-helper] 207/253: split crypto engines into own sources

Eric Dorland eric at moszumanska.debian.org
Fri Jan 6 23:39:20 UTC 2017


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository pkcs11-helper.

commit 499edd117739876788d67d8a09149c8fbc0e0041
Author: Alon Bar-Lev <alon.barlev at gmail.com>
Date:   Mon Oct 24 23:11:18 2011 +0000

    split crypto engines into own sources
---
 lib/Makefile.am                 |    3 +
 lib/_pkcs11h-crypto-cryptoapi.c |  382 ++++++++++++
 lib/_pkcs11h-crypto-gnutls.c    |  299 ++++++++++
 lib/_pkcs11h-crypto-nss.c       |  248 ++++++++
 lib/_pkcs11h-crypto-openssl.c   |  326 +++++++++++
 lib/_pkcs11h-crypto-polarssl.c  |  222 +++++++
 lib/pkcs11h-crypto.c            | 1222 +--------------------------------------
 7 files changed, 1487 insertions(+), 1215 deletions(-)

diff --git a/lib/Makefile.am b/lib/Makefile.am
index d561b1b..d73c154 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -78,6 +78,9 @@ libpkcs11_helper_la_SOURCES= \
 	_pkcs11h-mem.h pkcs11h-mem.c \
 	_pkcs11h-sys.h pkcs11h-sys.c \
 	_pkcs11h-crypto.h pkcs11h-crypto.c \
+	_pkcs11h-crypto-openssl.c _pkcs11h-crypto-nss.c \
+	_pkcs11h-crypto-gnutls.c _pkcs11h-crypto-polarssl.c \
+	_pkcs11h-crypto-cryptoapi.c \
 	_pkcs11h-threading.h pkcs11h-threading.c \
 	_pkcs11h-util.h pkcs11h-util.c \
 	_pkcs11h-session.h pkcs11h-session.c \
diff --git a/lib/_pkcs11h-crypto-cryptoapi.c b/lib/_pkcs11h-crypto-cryptoapi.c
new file mode 100644
index 0000000..a28e304
--- /dev/null
+++ b/lib/_pkcs11h-crypto-cryptoapi.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2005-2011 Alon Bar-Lev <alon.barlev at gmail.com>
+ * All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, or the BSD license.
+ *
+ * GNU General Public License (GPL) Version 2
+ * ===========================================
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING.GPL included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * BSD License
+ * ============
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     o Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     o Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     o Neither the name of the Alon Bar-Lev nor the names of its
+ *       contributors may be used to endorse or promote products derived from
+ *       this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-core.h>
+#include "_pkcs11h-util.h"
+#include "_pkcs11h-sys.h"
+#include "_pkcs11h-crypto.h"
+
+#if defined(ENABLE_PKCS11H_ENGINE_WIN32)
+#include <wincrypt.h>
+#if !defined(CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT)
+#define CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT	0x02
+#endif
+#if !defined(CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT)
+#define CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT	0x02
+#endif
+#if !defined(CERT_NAME_STR_REVERSE_FLAG)
+#define CERT_NAME_STR_REVERSE_FLAG		0x02000000
+#endif
+
+typedef PCCERT_CONTEXT (WINAPI *__CertCreateCertificateContext_t) (
+	DWORD dwCertEncodingType,
+	const BYTE *pbCertEncoded,
+	DWORD cbCertEncoded
+);
+typedef BOOL (WINAPI *__CertFreeCertificateContext_t) (
+	PCCERT_CONTEXT pCertContext
+);
+typedef DWORD (WINAPI *CertNameToStrW_t) (
+	DWORD dwCertEncodingType,
+	PCERT_NAME_BLOB pName,
+	DWORD dwStrType,
+	LPWSTR psz,
+	DWORD csz
+);
+typedef BOOL (WINAPI *__CryptVerifyCertificateSignatureEx_t) (
+	void *hCryptProv,
+	DWORD dwCertEncodingType,
+	DWORD dwSubjectType,
+	void* pvSubject,
+	DWORD dwIssuerType,
+	void* pvIssuer,
+	DWORD dwFlags,
+	void* pvReserved
+);
+
+typedef struct __crypto_win32_data_s {
+	HMODULE handle;
+	__CertCreateCertificateContext_t p_CertCreateCertificateContext;
+	__CertFreeCertificateContext_t p_CertFreeCertificateContext;
+	CertNameToStrW_t p_CertNameToStrW;
+	__CryptVerifyCertificateSignatureEx_t p_CryptVerifyCertificateSignatureEx;
+} *__crypto_win32_data_t;
+
+static
+int
+__pkcs11h_crypto_win32_uninitialize (
+	IN void * const global_data
+) {
+	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
+
+	_PKCS11H_ASSERT (global_data!=NULL);
+
+	if (data->handle != NULL) {
+		FreeLibrary (data->handle);
+		data->handle = NULL;
+	}
+
+	memset (data, 0, sizeof (struct __crypto_win32_data_s));
+
+	return 1;
+}
+
+static
+int
+__pkcs11h_crypto_win32_initialize (
+	IN void * const global_data
+) {
+	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
+
+	_PKCS11H_ASSERT (global_data!=NULL);
+
+	__pkcs11h_crypto_win32_uninitialize (data);
+
+	data->handle = LoadLibraryA ("crypt32.dll");
+	if (data->handle == NULL) {
+		return 0;
+	}
+
+	data->p_CertCreateCertificateContext = (__CertCreateCertificateContext_t)GetProcAddress (
+		data->handle,
+		"CertCreateCertificateContext"
+	);
+	data->p_CertFreeCertificateContext = (__CertFreeCertificateContext_t)GetProcAddress (
+		data->handle,
+		"CertFreeCertificateContext"
+	);
+	data->p_CertNameToStrW = (CertNameToStrW_t)GetProcAddress (
+		data->handle,
+		"CertNameToStrW"
+	);
+	data->p_CryptVerifyCertificateSignatureEx = (__CryptVerifyCertificateSignatureEx_t)GetProcAddress (
+		data->handle,
+		"CryptVerifyCertificateSignatureEx"
+	);
+
+	if (
+		data->p_CertCreateCertificateContext == NULL ||
+		data->p_CertFreeCertificateContext == NULL ||
+		data->p_CertNameToStrW == NULL ||
+		data->p_CryptVerifyCertificateSignatureEx == NULL
+	) {
+		__pkcs11h_crypto_win32_uninitialize (data);
+		return 0;
+	}
+
+	return 1;
+}
+
+static
+int
+__pkcs11h_crypto_win32_certificate_get_expiration (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT time_t * const expiration
+) {
+	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
+	PCCERT_CONTEXT cert = NULL;
+	PKCS11H_BOOL ok = FALSE;
+	SYSTEMTIME ust, st;
+	struct tm tm1;
+
+	_PKCS11H_ASSERT (global_data!=NULL);
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (expiration!=NULL);
+
+	*expiration = (time_t)0;
+
+	if (
+		(cert = data->p_CertCreateCertificateContext (
+			PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+			blob,
+			blob_size
+		)) == NULL ||
+		!FileTimeToSystemTime (
+			&cert->pCertInfo->NotAfter,
+			&ust
+		)
+	) {
+		goto cleanup;
+	}
+
+	SystemTimeToTzSpecificLocalTime (NULL, &ust, &st);
+	memset (&tm1, 0, sizeof (tm1));
+	tm1.tm_year = st.wYear - 1900;
+	tm1.tm_mon  = st.wMonth - 1;
+	tm1.tm_mday = st.wDay;
+	tm1.tm_hour = st.wHour;
+	tm1.tm_min  = st.wMinute;
+	tm1.tm_sec  = st.wSecond;
+
+	*expiration = mktime (&tm1);
+
+	ok = TRUE;
+
+cleanup:
+
+	if (cert != NULL) {
+		data->p_CertFreeCertificateContext (cert);
+		cert = NULL;
+	}
+
+	return ok != FALSE;
+}
+
+static
+int
+__pkcs11h_crypto_win32_certificate_get_dn (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT char * const dn,
+	IN const size_t dn_max
+) {
+	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
+	PCCERT_CONTEXT cert = NULL;
+	PKCS11H_BOOL ok = TRUE;
+	DWORD wsize;
+	WCHAR *wstr = NULL;
+
+	_PKCS11H_ASSERT (global_data!=NULL);
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (dn!=NULL);
+	_PKCS11H_ASSERT (dn_max>0);
+
+	dn[0] = '\x0';
+
+	if (
+		(cert = data->p_CertCreateCertificateContext (
+			PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+			blob,
+			blob_size
+		)) == NULL ||
+		(wsize = data->p_CertNameToStrW (
+			X509_ASN_ENCODING,
+			&cert->pCertInfo->Subject,
+			CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+			NULL,
+			0
+		)) == 0
+	) {
+		goto cleanup;
+	}
+	
+	if ((wstr = (WCHAR *)_g_pkcs11h_sys_engine.malloc (wsize * sizeof (WCHAR))) == NULL) {
+		goto cleanup;
+	}
+			
+	if (
+		(wsize = data->p_CertNameToStrW (
+			X509_ASN_ENCODING,
+			&cert->pCertInfo->Subject,
+			CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+			wstr,
+			wsize
+		)) == 0 ||
+		WideCharToMultiByte (
+			CP_UTF8,
+			0,
+			wstr,
+			-1,
+			dn,
+			dn_max,
+			NULL,
+			NULL
+		) == 0
+	) {
+		goto cleanup;
+	}
+
+	ok = TRUE;
+
+cleanup:
+
+	if (wstr != NULL) {
+		_g_pkcs11h_sys_engine.free (wstr);
+		wstr = NULL;
+	}
+
+	if (cert != NULL) {
+		data->p_CertFreeCertificateContext (cert);
+		cert = NULL;
+	}
+
+	return ok != FALSE;
+}
+
+static
+int
+__pkcs11h_crypto_win32_certificate_is_issuer (
+	IN void * const global_data,
+	IN const unsigned char * const issuer_blob,
+	IN const size_t issuer_blob_size,
+	IN const unsigned char * const cert_blob,
+	IN const size_t cert_blob_size
+) {
+	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
+	PCCERT_CONTEXT cert_issuer = NULL;
+	PCCERT_CONTEXT cert_cert = NULL;
+	PKCS11H_BOOL issuer = FALSE;
+
+	_PKCS11H_ASSERT (global_data!=NULL);
+	_PKCS11H_ASSERT (issuer_blob!=NULL);
+	_PKCS11H_ASSERT (cert_blob!=NULL);
+
+	if (
+		(cert_issuer = data->p_CertCreateCertificateContext (
+			PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+			issuer_blob,
+			issuer_blob_size
+		)) == NULL ||
+		(cert_cert = data->p_CertCreateCertificateContext (
+			PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+			cert_blob,
+			cert_blob_size
+		)) == NULL
+	) {
+		goto cleanup;
+	}
+
+	if (
+		data->p_CryptVerifyCertificateSignatureEx (
+			NULL,
+			X509_ASN_ENCODING,
+			CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
+			(void *)cert_cert,
+			CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
+			(void *)cert_issuer,
+			0,
+			NULL
+		)
+	) {
+		issuer = TRUE;
+	}
+
+cleanup:
+
+	if (cert_issuer != NULL) {
+		data->p_CertFreeCertificateContext (cert_issuer);
+		cert_issuer = NULL;
+	}
+
+	if (cert_cert != NULL) {
+		data->p_CertFreeCertificateContext (cert_cert);
+		cert_cert = NULL;
+	}
+
+	return issuer != FALSE;
+}
+
+static struct __crypto_win32_data_s s_win32_data = { NULL };
+static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_win32 = {
+	&s_win32_data,
+	__pkcs11h_crypto_win32_initialize,
+	__pkcs11h_crypto_win32_uninitialize,
+	__pkcs11h_crypto_win32_certificate_get_expiration,
+	__pkcs11h_crypto_win32_certificate_get_dn,
+	__pkcs11h_crypto_win32_certificate_is_issuer
+};
+
+#endif				/* ENABLE_PKCS11H_ENGINE_WIN32 */
diff --git a/lib/_pkcs11h-crypto-gnutls.c b/lib/_pkcs11h-crypto-gnutls.c
new file mode 100644
index 0000000..a7e5109
--- /dev/null
+++ b/lib/_pkcs11h-crypto-gnutls.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2005-2011 Alon Bar-Lev <alon.barlev at gmail.com>
+ * All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, or the BSD license.
+ *
+ * GNU General Public License (GPL) Version 2
+ * ===========================================
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING.GPL included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * BSD License
+ * ============
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     o Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     o Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     o Neither the name of the Alon Bar-Lev nor the names of its
+ *       contributors may be used to endorse or promote products derived from
+ *       this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-core.h>
+#include "_pkcs11h-util.h"
+#include "_pkcs11h-sys.h"
+#include "_pkcs11h-crypto.h"
+
+#if defined(ENABLE_PKCS11H_ENGINE_GNUTLS)
+#include <gnutls/x509.h>
+
+static
+int
+__pkcs11h_crypto_gnutls_initialize (
+	IN void * const global_data
+) {
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	if (gnutls_global_init () != GNUTLS_E_SUCCESS) {
+		return FALSE;
+	}
+	else {
+		return TRUE;
+	}
+}
+
+static
+int
+__pkcs11h_crypto_gnutls_uninitialize (
+	IN void * const global_data
+) {
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	gnutls_global_deinit ();
+
+	return TRUE;
+}
+
+static
+int
+__pkcs11h_crypto_gnutls_certificate_get_expiration (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT time_t * const expiration
+) {
+	gnutls_x509_crt_t cert = NULL;
+	gnutls_datum_t datum;
+	time_t now = time (NULL);
+	time_t notBefore;
+	time_t notAfter;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (expiration!=NULL);
+
+	*expiration = (time_t)0;
+
+	if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) {
+		/* gnutls sets output */
+		cert = NULL;
+		goto cleanup;
+	}
+	
+	datum.data = (unsigned char *)blob;
+	datum.size = blob_size;
+
+	if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
+		goto cleanup;
+	}
+
+	notBefore = gnutls_x509_crt_get_activation_time (cert);
+	notAfter = gnutls_x509_crt_get_expiration_time (cert);
+
+	if (
+		now >= notBefore &&
+		now <= notAfter
+	) {
+		*expiration = notAfter;
+	}
+
+cleanup:
+
+	if (cert != NULL) {
+		gnutls_x509_crt_deinit (cert);
+		cert = NULL;
+	}
+
+	return *expiration != (time_t)0;
+}
+
+static
+int
+__pkcs11h_crypto_gnutls_certificate_get_dn (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT char * const dn,
+	IN const size_t dn_max
+) {
+	gnutls_x509_crt_t cert = NULL;
+	gnutls_datum_t datum;
+	size_t s;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (dn!=NULL);
+	_PKCS11H_ASSERT (dn_max>0);
+
+	dn[0] = '\x0';
+
+	if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) {
+		/* gnutls sets output */
+		cert = NULL;
+		goto cleanup;
+	}
+
+	datum.data = (unsigned char *)blob;
+	datum.size = blob_size;
+
+	if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
+		goto cleanup;
+	}
+
+	s = dn_max;
+	if (
+		gnutls_x509_crt_get_dn (
+			cert,
+			dn,
+			&s
+		) != GNUTLS_E_SUCCESS
+	) {
+		/* gnutls sets output */
+		dn[0] = '\x0';
+		goto cleanup;
+	}
+
+cleanup:
+
+	if (cert != NULL) {
+		gnutls_x509_crt_deinit (cert);
+		cert = NULL;
+	}
+
+	return dn[0] != '\x0';
+}
+
+static
+int
+__pkcs11h_crypto_gnutls_certificate_is_issuer (
+	IN void * const global_data,
+	IN const unsigned char * const issuer_blob,
+	IN const size_t issuer_blob_size,
+	IN const unsigned char * const cert_blob,
+	IN const size_t cert_blob_size
+) {
+	gnutls_x509_crt_t cert_issuer = NULL;
+	gnutls_x509_crt_t cert_cert = NULL;
+	gnutls_datum_t datum;
+	PKCS11H_BOOL is_issuer = FALSE;
+	unsigned int result = 0;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (issuer_blob!=NULL);
+	_PKCS11H_ASSERT (cert_blob!=NULL);
+
+	if (gnutls_x509_crt_init (&cert_issuer) != GNUTLS_E_SUCCESS) {
+		/* gnutls sets output */
+		cert_issuer = NULL;
+		goto cleanup;
+	}
+	if (gnutls_x509_crt_init (&cert_cert) != GNUTLS_E_SUCCESS) {
+		/* gnutls sets output */
+		cert_cert = NULL;
+		goto cleanup;
+	}
+
+	datum.data = (unsigned char *)issuer_blob;
+	datum.size = issuer_blob_size;
+
+	if (
+		gnutls_x509_crt_import (
+			cert_issuer,
+			&datum,
+			GNUTLS_X509_FMT_DER
+		) != GNUTLS_E_SUCCESS
+	) {
+		goto cleanup;
+	}
+
+	datum.data = (unsigned char *)cert_blob;
+	datum.size = cert_blob_size;
+
+	if (
+		gnutls_x509_crt_import (
+			cert_cert,
+			&datum,
+			GNUTLS_X509_FMT_DER
+		) != GNUTLS_E_SUCCESS
+	) {
+		goto cleanup;
+	}
+
+	if (
+		gnutls_x509_crt_verify (
+			cert_cert,
+			&cert_issuer,
+			1,
+			0,
+			&result
+		) &&
+		(result & GNUTLS_CERT_INVALID) == 0
+	) {
+		is_issuer = TRUE;
+	}
+
+cleanup:
+
+	if (cert_cert != NULL) {
+		gnutls_x509_crt_deinit (cert_cert);
+		cert_cert = NULL;
+	}
+
+	if (cert_issuer != NULL) {
+		gnutls_x509_crt_deinit (cert_issuer);
+		cert_issuer = NULL;
+	}
+
+	return is_issuer;
+}
+
+static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_gnutls = {
+	NULL,
+	__pkcs11h_crypto_gnutls_initialize,
+	__pkcs11h_crypto_gnutls_uninitialize,
+	__pkcs11h_crypto_gnutls_certificate_get_expiration,
+	__pkcs11h_crypto_gnutls_certificate_get_dn,
+	__pkcs11h_crypto_gnutls_certificate_is_issuer
+};
+
+#endif				/* ENABLE_PKCS11H_ENGINE_GNUTLS */
diff --git a/lib/_pkcs11h-crypto-nss.c b/lib/_pkcs11h-crypto-nss.c
new file mode 100644
index 0000000..19bcdb9
--- /dev/null
+++ b/lib/_pkcs11h-crypto-nss.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2005-2011 Alon Bar-Lev <alon.barlev at gmail.com>
+ * All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, or the BSD license.
+ *
+ * GNU General Public License (GPL) Version 2
+ * ===========================================
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING.GPL included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * BSD License
+ * ============
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     o Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     o Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     o Neither the name of the Alon Bar-Lev nor the names of its
+ *       contributors may be used to endorse or promote products derived from
+ *       this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-core.h>
+#include "_pkcs11h-util.h"
+#include "_pkcs11h-sys.h"
+#include "_pkcs11h-crypto.h"
+
+#if defined(ENABLE_PKCS11H_ENGINE_NSS)
+#define _PKCS11T_H_ /* required so no conflict with ours */
+#include <nss.h>
+#include <cert.h>
+
+static
+int
+__pkcs11h_crypto_nss_initialize (
+	IN void * const global_data
+) {
+	int ret = FALSE;
+
+	if (NSS_IsInitialized ()) {
+		*(int *)global_data = FALSE;
+	}
+	else {
+		if (NSS_NoDB_Init (NULL) != SECSuccess) {
+			goto cleanup;
+		}
+		*(int *)global_data = TRUE;
+	}
+
+	ret = TRUE;
+
+cleanup:
+
+	return ret;
+}
+
+static
+int
+__pkcs11h_crypto_nss_uninitialize (
+	IN void * const global_data
+) {
+	if (*(int *)global_data != FALSE) {
+		NSS_Shutdown ();
+	}
+
+	return TRUE;
+}
+
+static
+int
+__pkcs11h_crypto_nss_certificate_get_expiration (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT time_t * const expiration
+) {
+	CERTCertificate *cert = NULL;
+	PRTime pr_notBefore, pr_notAfter;
+	time_t notBefore, notAfter;
+	time_t now = time (NULL);
+
+	(void)global_data;
+
+	*expiration = (time_t)0;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (expiration!=NULL);
+
+	if ((cert = CERT_DecodeCertFromPackage ((char *)blob, blob_size)) == NULL) {
+		goto cleanup;
+	}
+
+	if (CERT_GetCertTimes (cert, &pr_notBefore, &pr_notAfter) != SECSuccess) {
+		goto cleanup;
+	}
+
+	notBefore = pr_notBefore/1000000;
+	notAfter = pr_notAfter/1000000;
+
+	notBefore = mktime (gmtime (&notBefore));
+	notBefore += (int)(mktime (localtime (&notBefore)) - mktime (gmtime (&notBefore)));
+	notAfter = mktime (gmtime (&notAfter));
+	notAfter += (int)(mktime (localtime (&notAfter)) - mktime (gmtime (&notAfter)));
+
+	if (
+		now >= notBefore &&
+		now <= notAfter
+	) {
+		*expiration = notAfter;
+	}
+
+cleanup:
+
+	if (cert != NULL) {
+		CERT_DestroyCertificate (cert);
+	}
+
+	return *expiration != (time_t)0;
+}
+
+static
+int
+__pkcs11h_crypto_nss_certificate_get_dn (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT char * const dn,
+	IN const size_t dn_max
+) {
+	CERTCertificate *cert = NULL;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (dn!=NULL);
+	_PKCS11H_ASSERT (dn_max>0);
+
+	dn[0] = '\x0';
+
+	if ((cert = CERT_DecodeCertFromPackage ((char *)blob, blob_size)) == NULL) {
+		goto cleanup;
+	}
+
+	if (strlen (cert->subjectName) >= dn_max) {
+		goto cleanup;
+	}
+
+	strcpy (dn, cert->subjectName);
+
+cleanup:
+
+	if (cert != NULL) {
+		CERT_DestroyCertificate (cert);
+	}
+
+	return dn[0] != '\x0';
+}
+
+static
+int
+__pkcs11h_crypto_nss_certificate_is_issuer (
+	IN void * const global_data,
+	IN const unsigned char * const issuer_blob,
+	IN const size_t issuer_blob_size,
+	IN const unsigned char * const cert_blob,
+	IN const size_t cert_blob_size
+) {
+	PKCS11H_BOOL is_issuer = FALSE;
+	CERTCertificate *cert = NULL;
+	CERTCertificate *issuer = NULL;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (issuer_blob!=NULL);
+	_PKCS11H_ASSERT (cert_blob!=NULL);
+
+	if ((issuer = CERT_DecodeCertFromPackage ((char *)issuer_blob, issuer_blob_size)) == NULL) {
+		goto cleanup;
+	}
+
+	if ((cert = CERT_DecodeCertFromPackage ((char *)cert_blob, cert_blob_size)) == NULL) {
+		goto cleanup;
+	}
+
+	is_issuer = CERT_VerifySignedDataWithPublicKeyInfo (
+		&cert->signatureWrap,
+		&issuer->subjectPublicKeyInfo,
+		NULL
+	) == SECSuccess;
+
+cleanup:
+
+	if (cert != NULL) {
+		CERT_DestroyCertificate (cert);
+	}
+
+	if (issuer != NULL) {
+		CERT_DestroyCertificate (issuer);
+	}
+
+	return is_issuer;
+}
+
+static int s_nss_data = 0;
+static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_nss = {
+	&s_nss_data,
+	__pkcs11h_crypto_nss_initialize,
+	__pkcs11h_crypto_nss_uninitialize,
+	__pkcs11h_crypto_nss_certificate_get_expiration,
+	__pkcs11h_crypto_nss_certificate_get_dn,
+	__pkcs11h_crypto_nss_certificate_is_issuer
+};
+
+#endif				/* ENABLE_PKCS11H_ENGINE_NSS */
diff --git a/lib/_pkcs11h-crypto-openssl.c b/lib/_pkcs11h-crypto-openssl.c
new file mode 100644
index 0000000..14f29f1
--- /dev/null
+++ b/lib/_pkcs11h-crypto-openssl.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2005-2011 Alon Bar-Lev <alon.barlev at gmail.com>
+ * All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, or the BSD license.
+ *
+ * GNU General Public License (GPL) Version 2
+ * ===========================================
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING.GPL included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * BSD License
+ * ============
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     o Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     o Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     o Neither the name of the Alon Bar-Lev nor the names of its
+ *       contributors may be used to endorse or promote products derived from
+ *       this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-core.h>
+#include "_pkcs11h-util.h"
+#include "_pkcs11h-sys.h"
+#include "_pkcs11h-crypto.h"
+
+#if defined(ENABLE_PKCS11H_ENGINE_OPENSSL)
+#include <openssl/x509.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
+# define RSA_get_default_method RSA_get_default_openssl_method
+#else
+# ifdef HAVE_ENGINE_GET_DEFAULT_RSA
+#  include <openssl/engine.h>
+#  if OPENSSL_VERSION_NUMBER < 0x0090704fL
+#   define BROKEN_OPENSSL_ENGINE
+#  endif
+# endif
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+#if !defined(RSA_PKCS1_PADDING_SIZE)
+#define RSA_PKCS1_PADDING_SIZE 11
+#endif
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x00908000L
+typedef unsigned char *__pkcs11_openssl_d2i_t;
+#else
+typedef const unsigned char *__pkcs11_openssl_d2i_t;
+#endif
+
+static
+int
+__pkcs11h_crypto_openssl_initialize (
+	IN void * const global_data
+) {
+	(void)global_data;
+
+	OpenSSL_add_all_digests ();
+
+	return TRUE;
+}
+
+static
+int
+__pkcs11h_crypto_openssl_uninitialize (
+	IN void * const global_data
+) {
+	(void)global_data;
+
+	return TRUE;
+}
+
+static
+int
+__pkcs11h_crypto_openssl_certificate_get_expiration (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT time_t * const expiration
+) {
+	X509 *x509 = NULL;
+	__pkcs11_openssl_d2i_t d2i;
+	ASN1_TIME *notBefore;
+	ASN1_TIME *notAfter;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (expiration!=NULL);
+
+	*expiration = (time_t)0;
+
+	if ((x509 = X509_new ()) == NULL) {
+		goto cleanup;
+	}
+
+	d2i = (__pkcs11_openssl_d2i_t)blob;
+
+	if (!d2i_X509 (&x509, &d2i, blob_size)) {
+		goto cleanup;
+	}
+
+	notBefore = X509_get_notBefore (x509);
+	notAfter = X509_get_notAfter (x509);
+
+	if (
+		notBefore != NULL &&
+		notAfter != NULL &&
+		X509_cmp_current_time (notBefore) <= 0 &&
+		X509_cmp_current_time (notAfter) >= 0 &&
+		notAfter->length >= 12
+	) {
+		struct tm tm1;
+
+		memset (&tm1, 0, sizeof (tm1));
+		tm1.tm_year = (notAfter->data[ 0] - '0') * 10 + (notAfter->data[ 1] - '0') + 100;
+		tm1.tm_mon  = (notAfter->data[ 2] - '0') * 10 + (notAfter->data[ 3] - '0') - 1;
+		tm1.tm_mday = (notAfter->data[ 4] - '0') * 10 + (notAfter->data[ 5] - '0');
+		tm1.tm_hour = (notAfter->data[ 6] - '0') * 10 + (notAfter->data[ 7] - '0');
+		tm1.tm_min  = (notAfter->data[ 8] - '0') * 10 + (notAfter->data[ 9] - '0');
+		tm1.tm_sec  = (notAfter->data[10] - '0') * 10 + (notAfter->data[11] - '0');
+
+		*expiration = mktime (&tm1);
+		*expiration += (int)(mktime (localtime (expiration)) - mktime (gmtime (expiration)));
+	}
+
+cleanup:
+
+	if (x509 != NULL) {
+		X509_free (x509);
+		x509 = NULL;
+	}
+
+	return *expiration != (time_t)0;
+}
+
+static
+int
+__pkcs11h_crypto_openssl_certificate_get_dn (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT char * const dn,
+	IN const size_t dn_max
+) {
+	X509 *x509 = NULL;
+	__pkcs11_openssl_d2i_t d2i;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (dn!=NULL);
+	_PKCS11H_ASSERT (dn_max>0);
+
+	dn[0] = '\x0';
+
+	if ((x509 = X509_new ()) == NULL) {
+		goto cleanup;
+	}
+
+	d2i = (__pkcs11_openssl_d2i_t)blob;
+
+	if (!d2i_X509 (&x509, &d2i, blob_size)) {
+		goto cleanup;
+	}
+
+	X509_NAME_oneline (
+		X509_get_subject_name (x509),
+		dn,
+		dn_max
+	);
+
+cleanup:
+
+	if (x509 != NULL) {
+		X509_free (x509);
+		x509 = NULL;
+	}
+
+	return dn[0] != '\x0';
+}
+
+static
+int
+__pkcs11h_crypto_openssl_certificate_is_issuer (
+	IN void * const global_data,
+	IN const unsigned char * const issuer_blob,
+	IN const size_t issuer_blob_size,
+	IN const unsigned char * const cert_blob,
+	IN const size_t cert_blob_size
+) {
+	X509 *x509_issuer = NULL;
+	X509 *x509_cert = NULL;
+	EVP_PKEY *pub_issuer = NULL;
+	__pkcs11_openssl_d2i_t d2i;
+	PKCS11H_BOOL is_issuer = FALSE;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (issuer_blob!=NULL);
+	_PKCS11H_ASSERT (cert_blob!=NULL);
+
+	if (
+		(x509_issuer = X509_new ()) == NULL ||
+		(x509_cert = X509_new ()) == NULL
+	) {
+		goto cleanup;
+	}
+
+	d2i = (__pkcs11_openssl_d2i_t)issuer_blob;
+	if (
+		!d2i_X509 (
+			&x509_issuer,
+			&d2i,
+			issuer_blob_size
+		)
+	) {
+		goto cleanup;
+	}
+
+	d2i = (__pkcs11_openssl_d2i_t)cert_blob;
+	if (
+		!d2i_X509 (
+			&x509_cert,
+			&d2i,
+			cert_blob_size
+		)
+	) {
+		goto cleanup;
+	}
+
+	if (
+		(pub_issuer = X509_get_pubkey (x509_issuer)) == NULL
+	) {
+		goto cleanup;
+	}
+
+	if (
+		!X509_NAME_cmp (
+			X509_get_subject_name (x509_issuer),
+			X509_get_issuer_name (x509_cert)
+		) &&
+		X509_verify (x509_cert, pub_issuer) == 1
+	) {
+		is_issuer = TRUE;
+	}
+
+cleanup:
+
+	if (pub_issuer != NULL) {
+		EVP_PKEY_free (pub_issuer);
+		pub_issuer = NULL;
+	}
+	if (x509_issuer != NULL) {
+		X509_free (x509_issuer);
+		x509_issuer = NULL;
+	}
+	if (x509_cert != NULL) {
+		X509_free (x509_cert);
+		x509_cert = NULL;
+	}
+
+	return is_issuer;
+}
+
+static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_openssl = {
+	NULL,
+	__pkcs11h_crypto_openssl_initialize,
+	__pkcs11h_crypto_openssl_uninitialize,
+	__pkcs11h_crypto_openssl_certificate_get_expiration,
+	__pkcs11h_crypto_openssl_certificate_get_dn,
+	__pkcs11h_crypto_openssl_certificate_is_issuer
+};
+
+/*======================================================================*
+ * FIXUPS
+ *======================================================================*/
+
+#ifdef BROKEN_OPENSSL_ENGINE
+static void broken_openssl_init(void) __attribute__ ((constructor));
+static void  broken_openssl_init(void)
+{
+	SSL_library_init();
+	ENGINE_load_openssl();
+	ENGINE_register_all_RSA();
+}
+#endif
+
+#endif				/* ENABLE_PKCS11H_ENGINE_OPENSSL */
diff --git a/lib/_pkcs11h-crypto-polarssl.c b/lib/_pkcs11h-crypto-polarssl.c
new file mode 100644
index 0000000..d5c2929
--- /dev/null
+++ b/lib/_pkcs11h-crypto-polarssl.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2005-2011 Alon Bar-Lev <alon.barlev at gmail.com>
+ * All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, or the BSD license.
+ *
+ * GNU General Public License (GPL) Version 2
+ * ===========================================
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING.GPL included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * BSD License
+ * ============
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     o Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     o Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     o Neither the name of the Alon Bar-Lev nor the names of its
+ *       contributors may be used to endorse or promote products derived from
+ *       this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-core.h>
+#include "_pkcs11h-util.h"
+#include "_pkcs11h-sys.h"
+#include "_pkcs11h-crypto.h"
+
+#if defined(ENABLE_PKCS11H_ENGINE_POLARSSL)
+#include <polarssl/x509.h>
+#include <polarssl/version.h>
+
+static
+int
+__pkcs11h_crypto_polarssl_initialize (
+	IN void * const global_data
+) {
+	(void)global_data;
+
+	return TRUE;
+}
+
+static
+int
+__pkcs11h_crypto_polarssl_uninitialize (
+	IN void * const global_data
+) {
+	(void)global_data;
+
+	return TRUE;
+}
+
+static
+int
+__pkcs11h_crypto_polarssl_certificate_get_expiration (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT time_t * const expiration
+) {
+	x509_cert x509;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (expiration!=NULL);
+
+	*expiration = (time_t)0;
+
+	memset(&x509, 0, sizeof(x509));
+	if (0 != x509parse_crt (&x509, blob, blob_size)) {
+		goto cleanup;
+	}
+
+	if (0 == x509parse_time_expired(&x509.valid_to)) {
+		struct tm tm1;
+
+		memset (&tm1, 0, sizeof (tm1));
+		tm1.tm_year = x509.valid_to.year - 1900;
+		tm1.tm_mon  = x509.valid_to.mon  - 1;
+		tm1.tm_mday = x509.valid_to.day;
+		tm1.tm_hour = x509.valid_to.hour - 1;
+		tm1.tm_min  = x509.valid_to.min  - 1;
+		tm1.tm_sec  = x509.valid_to.sec  - 1;
+
+		*expiration = mktime (&tm1);
+		*expiration += (int)(mktime (localtime (expiration)) - mktime (gmtime (expiration)));
+	}
+
+cleanup:
+
+	x509_free(&x509);
+
+	return *expiration != (time_t)0;
+}
+
+static
+int
+__pkcs11h_crypto_polarssl_certificate_get_dn (
+	IN void * const global_data,
+	IN const unsigned char * const blob,
+	IN const size_t blob_size,
+	OUT char * const dn,
+	IN const size_t dn_max
+) {
+	x509_cert x509;
+	int ret = FALSE;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (blob!=NULL);
+	_PKCS11H_ASSERT (dn!=NULL);
+	_PKCS11H_ASSERT (dn_max>0);
+
+	dn[0] = '\x0';
+
+	memset(&x509, 0, sizeof(x509));
+	if (0 != x509parse_crt (&x509, blob, blob_size)) {
+		goto cleanup;
+	}
+
+	if (-1 == x509parse_dn_gets(dn, dn_max, &x509.subject)) {
+		goto cleanup;
+	}
+
+	ret = TRUE;
+
+cleanup:
+
+	x509_free(&x509);
+
+	return ret;
+}
+
+static
+int
+__pkcs11h_crypto_polarssl_certificate_is_issuer (
+	IN void * const global_data,
+	IN const unsigned char * const issuer_blob,
+	IN const size_t issuer_blob_size,
+	IN const unsigned char * const cert_blob,
+	IN const size_t cert_blob_size
+) {
+	x509_cert x509_issuer;
+	x509_cert x509_cert;
+	int verify_flags = 0;
+
+	PKCS11H_BOOL is_issuer = FALSE;
+
+	(void)global_data;
+
+	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
+	_PKCS11H_ASSERT (issuer_blob!=NULL);
+	_PKCS11H_ASSERT (cert_blob!=NULL);
+
+	memset(&x509_issuer, 0, sizeof(x509_issuer));
+	if (0 != x509parse_crt (&x509_issuer, issuer_blob, issuer_blob_size)) {
+		goto cleanup;
+	}
+
+	memset(&x509_cert, 0, sizeof(x509_cert));
+	if (0 != x509parse_crt (&x509_cert, cert_blob, cert_blob_size)) {
+		goto cleanup;
+	}
+
+#if (POLARSSL_VERSION_MAJOR == 0)
+	if ( 0 == x509parse_verify(&x509_cert, &x509_issuer, NULL, NULL,
+		&verify_flags ))
+#else
+	if ( 0 == x509parse_verify(&x509_cert, &x509_issuer, NULL, NULL,
+		&verify_flags, NULL, NULL ))
+#endif
+
+cleanup:
+	x509_free(&x509_cert);
+	x509_free(&x509_issuer);
+
+	return is_issuer;
+}
+
+static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_polarssl = {
+	NULL,
+	__pkcs11h_crypto_polarssl_initialize,
+	__pkcs11h_crypto_polarssl_uninitialize,
+	__pkcs11h_crypto_polarssl_certificate_get_expiration,
+	__pkcs11h_crypto_polarssl_certificate_get_dn,
+	__pkcs11h_crypto_polarssl_certificate_is_issuer
+};
+
+#endif				/* ENABLE_PKCS11H_ENGINE_POLARSSL */
diff --git a/lib/pkcs11h-crypto.c b/lib/pkcs11h-crypto.c
index 66dd223..c064ee3 100644
--- a/lib/pkcs11h-crypto.c
+++ b/lib/pkcs11h-crypto.c
@@ -56,1230 +56,22 @@
 #include "_pkcs11h-sys.h"
 #include "_pkcs11h-crypto.h"
 
-#if defined(ENABLE_PKCS11H_ENGINE_OPENSSL)
-#include <openssl/x509.h>
-#endif
-
-#if defined(ENABLE_PKCS11H_ENGINE_GNUTLS)
-#include <gnutls/x509.h>
-#endif
-
-#if defined(ENABLE_PKCS11H_ENGINE_NSS)
-#define _PKCS11T_H_ /* required so no conflict with ours */
-#include <nss.h>
-#include <cert.h>
-#endif
-
-#if defined(ENABLE_PKCS11H_ENGINE_POLARSSL)
-#include <polarssl/x509.h>
-#include <polarssl/version.h>
-#endif
-
 #if defined(ENABLE_PKCS11H_ENGINE_WIN32)
-#include <wincrypt.h>
-#if !defined(CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT)
-#define CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT	0x02
-#endif
-#if !defined(CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT)
-#define CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT	0x02
-#endif
-#if !defined(CERT_NAME_STR_REVERSE_FLAG)
-#define CERT_NAME_STR_REVERSE_FLAG		0x02000000
-#endif
-
-#endif
-
-/*===========================================
- * Constants
- */
-
-#if defined(ENABLE_PKCS11H_ENGINE_OPENSSL)
-
-#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
-# define RSA_get_default_method RSA_get_default_openssl_method
-#else
-# ifdef HAVE_ENGINE_GET_DEFAULT_RSA
-#  include <openssl/engine.h>
-#  if OPENSSL_VERSION_NUMBER < 0x0090704fL
-#   define BROKEN_OPENSSL_ENGINE
-#  endif
-# endif
-#endif
-
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
-#if !defined(RSA_PKCS1_PADDING_SIZE)
-#define RSA_PKCS1_PADDING_SIZE 11
-#endif
-#endif
-
+extern pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_win32;
 #endif
-
 #if defined(ENABLE_PKCS11H_ENGINE_OPENSSL)
-
-#if OPENSSL_VERSION_NUMBER < 0x00908000L
-typedef unsigned char *__pkcs11_openssl_d2i_t;
-#else
-typedef const unsigned char *__pkcs11_openssl_d2i_t;
+extern pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_openssl;
 #endif
-
-#endif
-
-#if defined(ENABLE_PKCS11H_ENGINE_WIN32)
-
-typedef PCCERT_CONTEXT (WINAPI *__CertCreateCertificateContext_t) (
-	DWORD dwCertEncodingType,
-	const BYTE *pbCertEncoded,
-	DWORD cbCertEncoded
-);
-typedef BOOL (WINAPI *__CertFreeCertificateContext_t) (
-	PCCERT_CONTEXT pCertContext
-);
-typedef DWORD (WINAPI *CertNameToStrW_t) (
-	DWORD dwCertEncodingType,
-	PCERT_NAME_BLOB pName,
-	DWORD dwStrType,
-	LPWSTR psz,
-	DWORD csz
-);
-typedef BOOL (WINAPI *__CryptVerifyCertificateSignatureEx_t) (
-	void *hCryptProv,
-	DWORD dwCertEncodingType,
-	DWORD dwSubjectType,
-	void* pvSubject,
-	DWORD dwIssuerType,
-	void* pvIssuer,
-	DWORD dwFlags,
-	void* pvReserved
-);
-
-typedef struct __crypto_win32_data_s {
-	HMODULE handle;
-	__CertCreateCertificateContext_t p_CertCreateCertificateContext;
-	__CertFreeCertificateContext_t p_CertFreeCertificateContext;
-	CertNameToStrW_t p_CertNameToStrW;
-	__CryptVerifyCertificateSignatureEx_t p_CryptVerifyCertificateSignatureEx;
-} *__crypto_win32_data_t;
-
+#if defined(ENABLE_PKCS11H_ENGINE_NSS)
+extern pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_nss;
 #endif
-
-#if defined(ENABLE_PKCS11H_ENGINE_OPENSSL)
-
-static
-int
-__pkcs11h_crypto_openssl_initialize (
-	IN void * const global_data
-) {
-	(void)global_data;
-
-	OpenSSL_add_all_digests ();
-
-	return TRUE;
-}
-
-static
-int
-__pkcs11h_crypto_openssl_uninitialize (
-	IN void * const global_data
-) {
-	(void)global_data;
-
-	return TRUE;
-}
-
-static
-int
-__pkcs11h_crypto_openssl_certificate_get_expiration (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT time_t * const expiration
-) {
-	X509 *x509 = NULL;
-	__pkcs11_openssl_d2i_t d2i;
-	ASN1_TIME *notBefore;
-	ASN1_TIME *notAfter;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (expiration!=NULL);
-
-	*expiration = (time_t)0;
-
-	if ((x509 = X509_new ()) == NULL) {
-		goto cleanup;
-	}
-
-	d2i = (__pkcs11_openssl_d2i_t)blob;
-
-	if (!d2i_X509 (&x509, &d2i, blob_size)) {
-		goto cleanup;
-	}
-
-	notBefore = X509_get_notBefore (x509);
-	notAfter = X509_get_notAfter (x509);
-
-	if (
-		notBefore != NULL &&
-		notAfter != NULL &&
-		X509_cmp_current_time (notBefore) <= 0 &&
-		X509_cmp_current_time (notAfter) >= 0 &&
-		notAfter->length >= 12
-	) {
-		struct tm tm1;
-
-		memset (&tm1, 0, sizeof (tm1));
-		tm1.tm_year = (notAfter->data[ 0] - '0') * 10 + (notAfter->data[ 1] - '0') + 100;
-		tm1.tm_mon  = (notAfter->data[ 2] - '0') * 10 + (notAfter->data[ 3] - '0') - 1;
-		tm1.tm_mday = (notAfter->data[ 4] - '0') * 10 + (notAfter->data[ 5] - '0');
-		tm1.tm_hour = (notAfter->data[ 6] - '0') * 10 + (notAfter->data[ 7] - '0');
-		tm1.tm_min  = (notAfter->data[ 8] - '0') * 10 + (notAfter->data[ 9] - '0');
-		tm1.tm_sec  = (notAfter->data[10] - '0') * 10 + (notAfter->data[11] - '0');
-
-		*expiration = mktime (&tm1);
-		*expiration += (int)(mktime (localtime (expiration)) - mktime (gmtime (expiration)));
-	}
-
-cleanup:
-
-	if (x509 != NULL) {
-		X509_free (x509);
-		x509 = NULL;
-	}
-
-	return *expiration != (time_t)0;
-}
-
-static
-int
-__pkcs11h_crypto_openssl_certificate_get_dn (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT char * const dn,
-	IN const size_t dn_max
-) {
-	X509 *x509 = NULL;
-	__pkcs11_openssl_d2i_t d2i;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (dn!=NULL);
-	_PKCS11H_ASSERT (dn_max>0);
-
-	dn[0] = '\x0';
-
-	if ((x509 = X509_new ()) == NULL) {
-		goto cleanup;
-	}
-
-	d2i = (__pkcs11_openssl_d2i_t)blob;
-
-	if (!d2i_X509 (&x509, &d2i, blob_size)) {
-		goto cleanup;
-	}
-
-	X509_NAME_oneline (
-		X509_get_subject_name (x509),
-		dn,
-		dn_max
-	);
-
-cleanup:
-
-	if (x509 != NULL) {
-		X509_free (x509);
-		x509 = NULL;
-	}
-
-	return dn[0] != '\x0';
-}
-
-static
-int
-__pkcs11h_crypto_openssl_certificate_is_issuer (
-	IN void * const global_data,
-	IN const unsigned char * const issuer_blob,
-	IN const size_t issuer_blob_size,
-	IN const unsigned char * const cert_blob,
-	IN const size_t cert_blob_size
-) {
-	X509 *x509_issuer = NULL;
-	X509 *x509_cert = NULL;
-	EVP_PKEY *pub_issuer = NULL;
-	__pkcs11_openssl_d2i_t d2i;
-	PKCS11H_BOOL is_issuer = FALSE;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (issuer_blob!=NULL);
-	_PKCS11H_ASSERT (cert_blob!=NULL);
-
-	if (
-		(x509_issuer = X509_new ()) == NULL ||
-		(x509_cert = X509_new ()) == NULL
-	) {
-		goto cleanup;
-	}
-
-	d2i = (__pkcs11_openssl_d2i_t)issuer_blob;
-	if (
-		!d2i_X509 (
-			&x509_issuer,
-			&d2i,
-			issuer_blob_size
-		)
-	) {
-		goto cleanup;
-	}
-
-	d2i = (__pkcs11_openssl_d2i_t)cert_blob;
-	if (
-		!d2i_X509 (
-			&x509_cert,
-			&d2i,
-			cert_blob_size
-		)
-	) {
-		goto cleanup;
-	}
-
-	if (
-		(pub_issuer = X509_get_pubkey (x509_issuer)) == NULL
-	) {
-		goto cleanup;
-	}
-
-	if (
-		!X509_NAME_cmp (
-			X509_get_subject_name (x509_issuer),
-			X509_get_issuer_name (x509_cert)
-		) &&
-		X509_verify (x509_cert, pub_issuer) == 1
-	) {
-		is_issuer = TRUE;
-	}
-
-cleanup:
-
-	if (pub_issuer != NULL) {
-		EVP_PKEY_free (pub_issuer);
-		pub_issuer = NULL;
-	}
-	if (x509_issuer != NULL) {
-		X509_free (x509_issuer);
-		x509_issuer = NULL;
-	}
-	if (x509_cert != NULL) {
-		X509_free (x509_cert);
-		x509_cert = NULL;
-	}
-
-	return is_issuer;
-}
-
-static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_openssl = {
-	NULL,
-	__pkcs11h_crypto_openssl_initialize,
-	__pkcs11h_crypto_openssl_uninitialize,
-	__pkcs11h_crypto_openssl_certificate_get_expiration,
-	__pkcs11h_crypto_openssl_certificate_get_dn,
-	__pkcs11h_crypto_openssl_certificate_is_issuer
-};
-
-/*======================================================================*
- * FIXUPS
- *======================================================================*/
-
-#ifdef BROKEN_OPENSSL_ENGINE
-static void broken_openssl_init(void) __attribute__ ((constructor));
-static void  broken_openssl_init(void)
-{
-	SSL_library_init();
-	ENGINE_load_openssl();
-	ENGINE_register_all_RSA();
-}
+#if defined(ENABLE_PKCS11H_ENGINE_POLARSSL)
+extern pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_polarssl;
 #endif
-
-#endif				/* ENABLE_PKCS11H_ENGINE_OPENSSL */
-
 #if defined(ENABLE_PKCS11H_ENGINE_GNUTLS)
-
-static
-int
-__pkcs11h_crypto_gnutls_initialize (
-	IN void * const global_data
-) {
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	if (gnutls_global_init () != GNUTLS_E_SUCCESS) {
-		return FALSE;
-	}
-	else {
-		return TRUE;
-	}
-}
-
-static
-int
-__pkcs11h_crypto_gnutls_uninitialize (
-	IN void * const global_data
-) {
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	gnutls_global_deinit ();
-
-	return TRUE;
-}
-
-static
-int
-__pkcs11h_crypto_gnutls_certificate_get_expiration (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT time_t * const expiration
-) {
-	gnutls_x509_crt_t cert = NULL;
-	gnutls_datum_t datum;
-	time_t now = time (NULL);
-	time_t notBefore;
-	time_t notAfter;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (expiration!=NULL);
-
-	*expiration = (time_t)0;
-
-	if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) {
-		/* gnutls sets output */
-		cert = NULL;
-		goto cleanup;
-	}
-	
-	datum.data = (unsigned char *)blob;
-	datum.size = blob_size;
-
-	if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
-		goto cleanup;
-	}
-
-	notBefore = gnutls_x509_crt_get_activation_time (cert);
-	notAfter = gnutls_x509_crt_get_expiration_time (cert);
-
-	if (
-		now >= notBefore &&
-		now <= notAfter
-	) {
-		*expiration = notAfter;
-	}
-
-cleanup:
-
-	if (cert != NULL) {
-		gnutls_x509_crt_deinit (cert);
-		cert = NULL;
-	}
-
-	return *expiration != (time_t)0;
-}
-
-static
-int
-__pkcs11h_crypto_gnutls_certificate_get_dn (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT char * const dn,
-	IN const size_t dn_max
-) {
-	gnutls_x509_crt_t cert = NULL;
-	gnutls_datum_t datum;
-	size_t s;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (dn!=NULL);
-	_PKCS11H_ASSERT (dn_max>0);
-
-	dn[0] = '\x0';
-
-	if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) {
-		/* gnutls sets output */
-		cert = NULL;
-		goto cleanup;
-	}
-
-	datum.data = (unsigned char *)blob;
-	datum.size = blob_size;
-
-	if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
-		goto cleanup;
-	}
-
-	s = dn_max;
-	if (
-		gnutls_x509_crt_get_dn (
-			cert,
-			dn,
-			&s
-		) != GNUTLS_E_SUCCESS
-	) {
-		/* gnutls sets output */
-		dn[0] = '\x0';
-		goto cleanup;
-	}
-
-cleanup:
-
-	if (cert != NULL) {
-		gnutls_x509_crt_deinit (cert);
-		cert = NULL;
-	}
-
-	return dn[0] != '\x0';
-}
-
-static
-int
-__pkcs11h_crypto_gnutls_certificate_is_issuer (
-	IN void * const global_data,
-	IN const unsigned char * const issuer_blob,
-	IN const size_t issuer_blob_size,
-	IN const unsigned char * const cert_blob,
-	IN const size_t cert_blob_size
-) {
-	gnutls_x509_crt_t cert_issuer = NULL;
-	gnutls_x509_crt_t cert_cert = NULL;
-	gnutls_datum_t datum;
-	PKCS11H_BOOL is_issuer = FALSE;
-	unsigned int result = 0;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (issuer_blob!=NULL);
-	_PKCS11H_ASSERT (cert_blob!=NULL);
-
-	if (gnutls_x509_crt_init (&cert_issuer) != GNUTLS_E_SUCCESS) {
-		/* gnutls sets output */
-		cert_issuer = NULL;
-		goto cleanup;
-	}
-	if (gnutls_x509_crt_init (&cert_cert) != GNUTLS_E_SUCCESS) {
-		/* gnutls sets output */
-		cert_cert = NULL;
-		goto cleanup;
-	}
-
-	datum.data = (unsigned char *)issuer_blob;
-	datum.size = issuer_blob_size;
-
-	if (
-		gnutls_x509_crt_import (
-			cert_issuer,
-			&datum,
-			GNUTLS_X509_FMT_DER
-		) != GNUTLS_E_SUCCESS
-	) {
-		goto cleanup;
-	}
-
-	datum.data = (unsigned char *)cert_blob;
-	datum.size = cert_blob_size;
-
-	if (
-		gnutls_x509_crt_import (
-			cert_cert,
-			&datum,
-			GNUTLS_X509_FMT_DER
-		) != GNUTLS_E_SUCCESS
-	) {
-		goto cleanup;
-	}
-
-	if (
-		gnutls_x509_crt_verify (
-			cert_cert,
-			&cert_issuer,
-			1,
-			0,
-			&result
-		) &&
-		(result & GNUTLS_CERT_INVALID) == 0
-	) {
-		is_issuer = TRUE;
-	}
-
-cleanup:
-
-	if (cert_cert != NULL) {
-		gnutls_x509_crt_deinit (cert_cert);
-		cert_cert = NULL;
-	}
-
-	if (cert_issuer != NULL) {
-		gnutls_x509_crt_deinit (cert_issuer);
-		cert_issuer = NULL;
-	}
-
-	return is_issuer;
-}
-
-static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_gnutls = {
-	NULL,
-	__pkcs11h_crypto_gnutls_initialize,
-	__pkcs11h_crypto_gnutls_uninitialize,
-	__pkcs11h_crypto_gnutls_certificate_get_expiration,
-	__pkcs11h_crypto_gnutls_certificate_get_dn,
-	__pkcs11h_crypto_gnutls_certificate_is_issuer
-};
-
-#endif				/* ENABLE_PKCS11H_ENGINE_GNUTLS */
-
-#if defined(ENABLE_PKCS11H_ENGINE_NSS)
-
-static
-int
-__pkcs11h_crypto_nss_initialize (
-	IN void * const global_data
-) {
-	int ret = FALSE;
-
-	if (NSS_IsInitialized ()) {
-		*(int *)global_data = FALSE;
-	}
-	else {
-		if (NSS_NoDB_Init (NULL) != SECSuccess) {
-			goto cleanup;
-		}
-		*(int *)global_data = TRUE;
-	}
-
-	ret = TRUE;
-
-cleanup:
-
-	return ret;
-}
-
-static
-int
-__pkcs11h_crypto_nss_uninitialize (
-	IN void * const global_data
-) {
-	if (*(int *)global_data != FALSE) {
-		NSS_Shutdown ();
-	}
-
-	return TRUE;
-}
-
-static
-int
-__pkcs11h_crypto_nss_certificate_get_expiration (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT time_t * const expiration
-) {
-	CERTCertificate *cert = NULL;
-	PRTime pr_notBefore, pr_notAfter;
-	time_t notBefore, notAfter;
-	time_t now = time (NULL);
-
-	(void)global_data;
-
-	*expiration = (time_t)0;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (expiration!=NULL);
-
-	if ((cert = CERT_DecodeCertFromPackage ((char *)blob, blob_size)) == NULL) {
-		goto cleanup;
-	}
-
-	if (CERT_GetCertTimes (cert, &pr_notBefore, &pr_notAfter) != SECSuccess) {
-		goto cleanup;
-	}
-
-	notBefore = pr_notBefore/1000000;
-	notAfter = pr_notAfter/1000000;
-
-	notBefore = mktime (gmtime (&notBefore));
-	notBefore += (int)(mktime (localtime (&notBefore)) - mktime (gmtime (&notBefore)));
-	notAfter = mktime (gmtime (&notAfter));
-	notAfter += (int)(mktime (localtime (&notAfter)) - mktime (gmtime (&notAfter)));
-
-	if (
-		now >= notBefore &&
-		now <= notAfter
-	) {
-		*expiration = notAfter;
-	}
-
-cleanup:
-
-	if (cert != NULL) {
-		CERT_DestroyCertificate (cert);
-	}
-
-	return *expiration != (time_t)0;
-}
-
-static
-int
-__pkcs11h_crypto_nss_certificate_get_dn (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT char * const dn,
-	IN const size_t dn_max
-) {
-	CERTCertificate *cert = NULL;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (dn!=NULL);
-	_PKCS11H_ASSERT (dn_max>0);
-
-	dn[0] = '\x0';
-
-	if ((cert = CERT_DecodeCertFromPackage ((char *)blob, blob_size)) == NULL) {
-		goto cleanup;
-	}
-
-	if (strlen (cert->subjectName) >= dn_max) {
-		goto cleanup;
-	}
-
-	strcpy (dn, cert->subjectName);
-
-cleanup:
-
-	if (cert != NULL) {
-		CERT_DestroyCertificate (cert);
-	}
-
-	return dn[0] != '\x0';
-}
-
-static
-int
-__pkcs11h_crypto_nss_certificate_is_issuer (
-	IN void * const global_data,
-	IN const unsigned char * const issuer_blob,
-	IN const size_t issuer_blob_size,
-	IN const unsigned char * const cert_blob,
-	IN const size_t cert_blob_size
-) {
-	PKCS11H_BOOL is_issuer = FALSE;
-	CERTCertificate *cert = NULL;
-	CERTCertificate *issuer = NULL;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (issuer_blob!=NULL);
-	_PKCS11H_ASSERT (cert_blob!=NULL);
-
-	if ((issuer = CERT_DecodeCertFromPackage ((char *)issuer_blob, issuer_blob_size)) == NULL) {
-		goto cleanup;
-	}
-
-	if ((cert = CERT_DecodeCertFromPackage ((char *)cert_blob, cert_blob_size)) == NULL) {
-		goto cleanup;
-	}
-
-	is_issuer = CERT_VerifySignedDataWithPublicKeyInfo (
-		&cert->signatureWrap,
-		&issuer->subjectPublicKeyInfo,
-		NULL
-	) == SECSuccess;
-
-cleanup:
-
-	if (cert != NULL) {
-		CERT_DestroyCertificate (cert);
-	}
-
-	if (issuer != NULL) {
-		CERT_DestroyCertificate (issuer);
-	}
-
-	return is_issuer;
-}
-
-static int s_nss_data = 0;
-static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_nss = {
-	&s_nss_data,
-	__pkcs11h_crypto_nss_initialize,
-	__pkcs11h_crypto_nss_uninitialize,
-	__pkcs11h_crypto_nss_certificate_get_expiration,
-	__pkcs11h_crypto_nss_certificate_get_dn,
-	__pkcs11h_crypto_nss_certificate_is_issuer
-};
-
-#endif				/* ENABLE_PKCS11H_ENGINE_NSS */
-
-#if defined(ENABLE_PKCS11H_ENGINE_WIN32)
-
-static
-int
-__pkcs11h_crypto_win32_uninitialize (
-	IN void * const global_data
-) {
-	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
-
-	_PKCS11H_ASSERT (global_data!=NULL);
-
-	if (data->handle != NULL) {
-		FreeLibrary (data->handle);
-		data->handle = NULL;
-	}
-
-	memset (data, 0, sizeof (struct __crypto_win32_data_s));
-
-	return 1;
-}
-
-static
-int
-__pkcs11h_crypto_win32_initialize (
-	IN void * const global_data
-) {
-	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
-
-	_PKCS11H_ASSERT (global_data!=NULL);
-
-	__pkcs11h_crypto_win32_uninitialize (data);
-
-	data->handle = LoadLibraryA ("crypt32.dll");
-	if (data->handle == NULL) {
-		return 0;
-	}
-
-	data->p_CertCreateCertificateContext = (__CertCreateCertificateContext_t)GetProcAddress (
-		data->handle,
-		"CertCreateCertificateContext"
-	);
-	data->p_CertFreeCertificateContext = (__CertFreeCertificateContext_t)GetProcAddress (
-		data->handle,
-		"CertFreeCertificateContext"
-	);
-	data->p_CertNameToStrW = (CertNameToStrW_t)GetProcAddress (
-		data->handle,
-		"CertNameToStrW"
-	);
-	data->p_CryptVerifyCertificateSignatureEx = (__CryptVerifyCertificateSignatureEx_t)GetProcAddress (
-		data->handle,
-		"CryptVerifyCertificateSignatureEx"
-	);
-
-	if (
-		data->p_CertCreateCertificateContext == NULL ||
-		data->p_CertFreeCertificateContext == NULL ||
-		data->p_CertNameToStrW == NULL ||
-		data->p_CryptVerifyCertificateSignatureEx == NULL
-	) {
-		__pkcs11h_crypto_win32_uninitialize (data);
-		return 0;
-	}
-
-	return 1;
-}
-
-static
-int
-__pkcs11h_crypto_win32_certificate_get_expiration (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT time_t * const expiration
-) {
-	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
-	PCCERT_CONTEXT cert = NULL;
-	PKCS11H_BOOL ok = FALSE;
-	SYSTEMTIME ust, st;
-	struct tm tm1;
-
-	_PKCS11H_ASSERT (global_data!=NULL);
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (expiration!=NULL);
-
-	*expiration = (time_t)0;
-
-	if (
-		(cert = data->p_CertCreateCertificateContext (
-			PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-			blob,
-			blob_size
-		)) == NULL ||
-		!FileTimeToSystemTime (
-			&cert->pCertInfo->NotAfter,
-			&ust
-		)
-	) {
-		goto cleanup;
-	}
-
-	SystemTimeToTzSpecificLocalTime (NULL, &ust, &st);
-	memset (&tm1, 0, sizeof (tm1));
-	tm1.tm_year = st.wYear - 1900;
-	tm1.tm_mon  = st.wMonth - 1;
-	tm1.tm_mday = st.wDay;
-	tm1.tm_hour = st.wHour;
-	tm1.tm_min  = st.wMinute;
-	tm1.tm_sec  = st.wSecond;
-
-	*expiration = mktime (&tm1);
-
-	ok = TRUE;
-
-cleanup:
-
-	if (cert != NULL) {
-		data->p_CertFreeCertificateContext (cert);
-		cert = NULL;
-	}
-
-	return ok != FALSE;
-}
-
-static
-int
-__pkcs11h_crypto_win32_certificate_get_dn (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT char * const dn,
-	IN const size_t dn_max
-) {
-	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
-	PCCERT_CONTEXT cert = NULL;
-	PKCS11H_BOOL ok = TRUE;
-	DWORD wsize;
-	WCHAR *wstr = NULL;
-
-	_PKCS11H_ASSERT (global_data!=NULL);
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (dn!=NULL);
-	_PKCS11H_ASSERT (dn_max>0);
-
-	dn[0] = '\x0';
-
-	if (
-		(cert = data->p_CertCreateCertificateContext (
-			PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-			blob,
-			blob_size
-		)) == NULL ||
-		(wsize = data->p_CertNameToStrW (
-			X509_ASN_ENCODING,
-			&cert->pCertInfo->Subject,
-			CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
-			NULL,
-			0
-		)) == 0
-	) {
-		goto cleanup;
-	}
-	
-	if ((wstr = (WCHAR *)_g_pkcs11h_sys_engine.malloc (wsize * sizeof (WCHAR))) == NULL) {
-		goto cleanup;
-	}
-			
-	if (
-		(wsize = data->p_CertNameToStrW (
-			X509_ASN_ENCODING,
-			&cert->pCertInfo->Subject,
-			CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
-			wstr,
-			wsize
-		)) == 0 ||
-		WideCharToMultiByte (
-			CP_UTF8,
-			0,
-			wstr,
-			-1,
-			dn,
-			dn_max,
-			NULL,
-			NULL
-		) == 0
-	) {
-		goto cleanup;
-	}
-
-	ok = TRUE;
-
-cleanup:
-
-	if (wstr != NULL) {
-		_g_pkcs11h_sys_engine.free (wstr);
-		wstr = NULL;
-	}
-
-	if (cert != NULL) {
-		data->p_CertFreeCertificateContext (cert);
-		cert = NULL;
-	}
-
-	return ok != FALSE;
-}
-
-static
-int
-__pkcs11h_crypto_win32_certificate_is_issuer (
-	IN void * const global_data,
-	IN const unsigned char * const issuer_blob,
-	IN const size_t issuer_blob_size,
-	IN const unsigned char * const cert_blob,
-	IN const size_t cert_blob_size
-) {
-	__crypto_win32_data_t data = (__crypto_win32_data_t)global_data;
-	PCCERT_CONTEXT cert_issuer = NULL;
-	PCCERT_CONTEXT cert_cert = NULL;
-	PKCS11H_BOOL issuer = FALSE;
-
-	_PKCS11H_ASSERT (global_data!=NULL);
-	_PKCS11H_ASSERT (issuer_blob!=NULL);
-	_PKCS11H_ASSERT (cert_blob!=NULL);
-
-	if (
-		(cert_issuer = data->p_CertCreateCertificateContext (
-			PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-			issuer_blob,
-			issuer_blob_size
-		)) == NULL ||
-		(cert_cert = data->p_CertCreateCertificateContext (
-			PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-			cert_blob,
-			cert_blob_size
-		)) == NULL
-	) {
-		goto cleanup;
-	}
-
-	if (
-		data->p_CryptVerifyCertificateSignatureEx (
-			NULL,
-			X509_ASN_ENCODING,
-			CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
-			(void *)cert_cert,
-			CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
-			(void *)cert_issuer,
-			0,
-			NULL
-		)
-	) {
-		issuer = TRUE;
-	}
-
-cleanup:
-
-	if (cert_issuer != NULL) {
-		data->p_CertFreeCertificateContext (cert_issuer);
-		cert_issuer = NULL;
-	}
-
-	if (cert_cert != NULL) {
-		data->p_CertFreeCertificateContext (cert_cert);
-		cert_cert = NULL;
-	}
-
-	return issuer != FALSE;
-}
-
-static struct __crypto_win32_data_s s_win32_data = { NULL };
-static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_win32 = {
-	&s_win32_data,
-	__pkcs11h_crypto_win32_initialize,
-	__pkcs11h_crypto_win32_uninitialize,
-	__pkcs11h_crypto_win32_certificate_get_expiration,
-	__pkcs11h_crypto_win32_certificate_get_dn,
-	__pkcs11h_crypto_win32_certificate_is_issuer
-};
-
-#endif				/* ENABLE_PKCS11H_ENGINE_WIN32 */
-
-#if defined(ENABLE_PKCS11H_ENGINE_POLARSSL)
-
-static
-int
-__pkcs11h_crypto_polarssl_initialize (
-	IN void * const global_data
-) {
-	(void)global_data;
-
-	return TRUE;
-}
-
-static
-int
-__pkcs11h_crypto_polarssl_uninitialize (
-	IN void * const global_data
-) {
-	(void)global_data;
-
-	return TRUE;
-}
-
-static
-int
-__pkcs11h_crypto_polarssl_certificate_get_expiration (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT time_t * const expiration
-) {
-	x509_cert x509;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (expiration!=NULL);
-
-	*expiration = (time_t)0;
-
-	memset(&x509, 0, sizeof(x509));
-	if (0 != x509parse_crt (&x509, blob, blob_size)) {
-		goto cleanup;
-	}
-
-	if (0 == x509parse_time_expired(&x509.valid_to)) {
-		struct tm tm1;
-
-		memset (&tm1, 0, sizeof (tm1));
-		tm1.tm_year = x509.valid_to.year - 1900;
-		tm1.tm_mon  = x509.valid_to.mon  - 1;
-		tm1.tm_mday = x509.valid_to.day;
-		tm1.tm_hour = x509.valid_to.hour - 1;
-		tm1.tm_min  = x509.valid_to.min  - 1;
-		tm1.tm_sec  = x509.valid_to.sec  - 1;
-
-		*expiration = mktime (&tm1);
-		*expiration += (int)(mktime (localtime (expiration)) - mktime (gmtime (expiration)));
-	}
-
-cleanup:
-
-	x509_free(&x509);
-
-	return *expiration != (time_t)0;
-}
-
-static
-int
-__pkcs11h_crypto_polarssl_certificate_get_dn (
-	IN void * const global_data,
-	IN const unsigned char * const blob,
-	IN const size_t blob_size,
-	OUT char * const dn,
-	IN const size_t dn_max
-) {
-	x509_cert x509;
-	int ret = FALSE;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (blob!=NULL);
-	_PKCS11H_ASSERT (dn!=NULL);
-	_PKCS11H_ASSERT (dn_max>0);
-
-	dn[0] = '\x0';
-
-	memset(&x509, 0, sizeof(x509));
-	if (0 != x509parse_crt (&x509, blob, blob_size)) {
-		goto cleanup;
-	}
-
-	if (-1 == x509parse_dn_gets(dn, dn_max, &x509.subject)) {
-		goto cleanup;
-	}
-
-	ret = TRUE;
-
-cleanup:
-
-	x509_free(&x509);
-
-	return ret;
-}
-
-static
-int
-__pkcs11h_crypto_polarssl_certificate_is_issuer (
-	IN void * const global_data,
-	IN const unsigned char * const issuer_blob,
-	IN const size_t issuer_blob_size,
-	IN const unsigned char * const cert_blob,
-	IN const size_t cert_blob_size
-) {
-	x509_cert x509_issuer;
-	x509_cert x509_cert;
-	int verify_flags = 0;
-
-	PKCS11H_BOOL is_issuer = FALSE;
-
-	(void)global_data;
-
-	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
-	_PKCS11H_ASSERT (issuer_blob!=NULL);
-	_PKCS11H_ASSERT (cert_blob!=NULL);
-
-	memset(&x509_issuer, 0, sizeof(x509_issuer));
-	if (0 != x509parse_crt (&x509_issuer, issuer_blob, issuer_blob_size)) {
-		goto cleanup;
-	}
-
-	memset(&x509_cert, 0, sizeof(x509_cert));
-	if (0 != x509parse_crt (&x509_cert, cert_blob, cert_blob_size)) {
-		goto cleanup;
-	}
-
-#if (POLARSSL_VERSION_MAJOR == 0)
-	if ( 0 == x509parse_verify(&x509_cert, &x509_issuer, NULL, NULL,
-		&verify_flags ))
-#else
-	if ( 0 == x509parse_verify(&x509_cert, &x509_issuer, NULL, NULL,
-		&verify_flags, NULL, NULL ))
+extern pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_gnutls;
 #endif
 
-cleanup:
-	x509_free(&x509_cert);
-	x509_free(&x509_issuer);
-
-	return is_issuer;
-}
-
-static const pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine_polarssl = {
-	NULL,
-	__pkcs11h_crypto_polarssl_initialize,
-	__pkcs11h_crypto_polarssl_uninitialize,
-	__pkcs11h_crypto_polarssl_certificate_get_expiration,
-	__pkcs11h_crypto_polarssl_certificate_get_dn,
-	__pkcs11h_crypto_polarssl_certificate_is_issuer
-};
-
-#endif				/* ENABLE_PKCS11H_ENGINE_POLARSSL */
-
 pkcs11h_engine_crypto_t _g_pkcs11h_crypto_engine = {
 	NULL,
 	NULL,

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/pkcs11-helper.git



More information about the pkg-opensc-commit mailing list