gnome-keyring r1403 - in trunk: . pkcs11 pkcs11/gck pkcs11/gck/tests pkcs11/gck/tests/test-data tests
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1403 - in trunk: . pkcs11 pkcs11/gck pkcs11/gck/tests pkcs11/gck/tests/test-data tests
- Date: Mon, 22 Dec 2008 20:21:06 +0000 (UTC)
Author: nnielsen
Date: Mon Dec 22 20:21:06 2008
New Revision: 1403
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1403&view=rev
Log:
* pkcs11/gck/tests/*: (added)
* pkcs11/gck/gck-crypto.c:
* pkcs11/gck/gck-crypto.h:
* pkcs11/gck/gck-data-asn1.c:
* pkcs11/gck/gck-data-asn1.h:
* pkcs11/gck/gck-data-der.c: (added)
* pkcs11/gck/gck-data-der.h: (added)
* pkcs11/gck/gck-data-openssl.c: (added)
* pkcs11/gck/gck-data-openssl.h: (added)
* pkcs11/gck/gck-data-pem.c: (added)
* pkcs11/gck/gck-data-pem.h: (added)
* pkcs11/gck/gck-data-types.h: (added)
* pkcs11/gck/gck-file-tracker.c: (added)
* pkcs11/gck/gck-file-tracker.h: (added)
* pkcs11/gck/gck-module.c:
* pkcs11/gck/gck-module.h:
* pkcs11/gck/gck-module-ep.h:
* pkcs11/gck/temporary-test.c:
* pkcs11/gck/Makefile.am:
* pkcs11/gck/pk.asn: (added)
* pkcs11/gck/pkix.asn: (added)
* pkcs11/Makefile.am:
* tests/gtest-helpers.c:
* tests/gtest.make:
* configure.in: Migrate lots of data processing code over to
new GCK component. Vet for thread-safety, add unit-tests,
and disable code not covered by unit tests.
Added:
trunk/pkcs11/gck/gck-data-asn1.c
trunk/pkcs11/gck/gck-data-asn1.h
trunk/pkcs11/gck/gck-data-der.c
trunk/pkcs11/gck/gck-data-der.h
trunk/pkcs11/gck/gck-data-openssl.c
trunk/pkcs11/gck/gck-data-openssl.h
trunk/pkcs11/gck/gck-data-pem.c
trunk/pkcs11/gck/gck-data-pem.h
trunk/pkcs11/gck/gck-data-types.h
trunk/pkcs11/gck/gck-file-tracker.c
trunk/pkcs11/gck/gck-file-tracker.h
trunk/pkcs11/gck/pk.asn
trunk/pkcs11/gck/pkix.asn
trunk/pkcs11/gck/tests/ (props changed)
trunk/pkcs11/gck/tests/Makefile.am
trunk/pkcs11/gck/tests/test-data/
trunk/pkcs11/gck/tests/test-data/pem-rsa-enc.key
trunk/pkcs11/gck/tests/test.asn
trunk/pkcs11/gck/tests/unit-test-crypto.c
trunk/pkcs11/gck/tests/unit-test-data-asn1.c
trunk/pkcs11/gck/tests/unit-test-data-der.c
trunk/pkcs11/gck/tests/unit-test-data-openssl.c
trunk/pkcs11/gck/tests/unit-test-file-tracker.c
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/pkcs11/Makefile.am
trunk/pkcs11/gck/ (props changed)
trunk/pkcs11/gck/Makefile.am
trunk/pkcs11/gck/gck-crypto.c
trunk/pkcs11/gck/gck-crypto.h
trunk/pkcs11/gck/gck-module-ep.h
trunk/pkcs11/gck/gck-module.c
trunk/pkcs11/gck/gck-module.h
trunk/pkcs11/gck/temporary-test.c
trunk/tests/gtest-helpers.c
trunk/tests/gtest.make
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Mon Dec 22 20:21:06 2008
@@ -513,7 +513,9 @@
pam/Makefile
pam/tests/Makefile
pkcs11/Makefile
+pkcs11/dot-ssh/Makefile
pkcs11/gck/Makefile
+pkcs11/gck/tests/Makefile
pkcs11/rpc/Makefile
pkcs11/tests/Makefile
po/Makefile.in
Modified: trunk/pkcs11/Makefile.am
==============================================================================
--- trunk/pkcs11/Makefile.am (original)
+++ trunk/pkcs11/Makefile.am Mon Dec 22 20:21:06 2008
@@ -41,5 +41,5 @@
TESTS_DIR =
endif
-SUBDIRS = . rpc gck $(TESTS_DIR)
+SUBDIRS = . rpc gck dot-ssh $(TESTS_DIR)
Modified: trunk/pkcs11/gck/Makefile.am
==============================================================================
--- trunk/pkcs11/gck/Makefile.am (original)
+++ trunk/pkcs11/gck/Makefile.am Mon Dec 22 20:21:06 2008
@@ -7,13 +7,22 @@
$(GLIB_CFLAGS)
# ------------------------------------------------------------------------------
-# The dispatch code
+# The GCK library
noinst_LTLIBRARIES = \
libgck.la
+BUILT_SOURCES = \
+ asn1-def-pk.h asn1-def-pkix.h
+
libgck_la_SOURCES = \
gck-crypto.c gck-crypto.h \
+ gck-data-asn1.c gck-data-asn1.h \
+ gck-data-der.c gck-data-der.h \
+ gck-data-openssl.c gck-data-openssl.h \
+ gck-data-pem.c gck-data-pem.h \
+ gck-data-types.h \
+ gck-file-tracker.c gck-file-tracker.h \
gck-key.c gck-key.h \
gck-manager.c gck-manager.h \
gck-module.c gck-module.h gck-module-ep.h \
@@ -24,6 +33,16 @@
gck-sexp.c gck-sexp.h \
gck-util.c gck-util.h
+asn1-def-pk.h: pk.asn
+ asn1Parser -o asn1-def-pk.h pk.asn
+
+asn1-def-pkix.h: pkix.asn
+ asn1Parser -o asn1-def-pkix.h pkix.asn
+
+EXTRA_DIST = \
+ pkix.asn \
+ pk.asn
+
# ------------------------------------------------------------------------------
# TEMPORARY TEST BINARY
@@ -32,10 +51,23 @@
temporary_test_SOURCES = \
temporary-test.c
+
+temporary_test_LDFLAGS = \
+ -lpthread
temporary_test_LDADD = \
libgck.la \
+ $(top_builddir)/common/libgkr-module-common.la \
$(GOBJECT_LIBS) \
$(LIBGCRYPT_LIBS) \
- $(GLIB_LIBS)
-
\ No newline at end of file
+ $(GLIB_LIBS)
+
+# -------------------------------------------------------------------------------
+
+if WITH_TESTS
+TESTS_DIR = tests
+else
+TESTS_DIR =
+endif
+
+SUBDIRS = . $(TESTS_DIR)
Modified: trunk/pkcs11/gck/gck-crypto.c
==============================================================================
--- trunk/pkcs11/gck/gck-crypto.c (original)
+++ trunk/pkcs11/gck/gck-crypto.c Mon Dec 22 20:21:06 2008
@@ -23,6 +23,8 @@
#include "gck-crypto.h"
+#include "common/gkr-secure-memory.h"
+
/* ----------------------------------------------------------------------------
* INTERNAL
*/
@@ -886,3 +888,574 @@
{
return unpad_rsa_pkcs1 (0x02, bits, padded, n_padded, n_raw);
}
+
+/* -----------------------------------------------------------------------------
+ * PASSWORD TO KEY/IV
+ */
+
+gboolean
+gck_crypto_symkey_generate_simple (int cipher_algo, int hash_algo,
+ const gchar *password, const guchar *salt,
+ gsize n_salt, int iterations, guchar **key,
+ guchar **iv)
+{
+ gcry_md_hd_t mdh;
+ gcry_error_t gcry;
+ guchar *digest;
+ guchar *digested;
+ guint n_digest;
+ gint pass, i;
+ gint needed_iv, needed_key;
+ guchar *at_iv, *at_key;
+
+ g_assert (cipher_algo);
+ g_assert (hash_algo);
+
+ g_return_val_if_fail (iterations >= 1, FALSE);
+
+ /*
+ * If cipher algo needs more bytes than hash algo has available
+ * then the entire hashing process is done again (with the previous
+ * hash bytes as extra input), and so on until satisfied.
+ */
+
+ needed_key = gcry_cipher_get_algo_keylen (cipher_algo);
+ needed_iv = gcry_cipher_get_algo_blklen (cipher_algo);
+
+ gcry = gcry_md_open (&mdh, hash_algo, 0);
+ if (gcry) {
+ g_warning ("couldn't create '%s' hash context: %s",
+ gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
+ return FALSE;
+ }
+
+ n_digest = gcry_md_get_algo_dlen (hash_algo);
+ g_return_val_if_fail (n_digest > 0, FALSE);
+
+ digest = gkr_secure_alloc (n_digest);
+ g_return_val_if_fail (digest, FALSE);
+ if (key) {
+ *key = gkr_secure_alloc (needed_key);
+ g_return_val_if_fail (*key, FALSE);
+ }
+ if (iv)
+ *iv = g_new0 (guchar, needed_iv);
+
+ at_key = key ? *key : NULL;
+ at_iv = iv ? *iv : NULL;
+
+ for (pass = 0; TRUE; ++pass) {
+ gcry_md_reset (mdh);
+
+ /* Hash in the previous buffer on later passes */
+ if (pass > 0)
+ gcry_md_write (mdh, digest, n_digest);
+
+ if (password)
+ gcry_md_write (mdh, password, strlen (password));
+ if (salt && n_salt)
+ gcry_md_write (mdh, salt, n_salt);
+ gcry_md_final (mdh);
+ digested = gcry_md_read (mdh, 0);
+ g_return_val_if_fail (digested, FALSE);
+ memcpy (digest, digested, n_digest);
+
+ for (i = 1; i < iterations; ++i) {
+ gcry_md_reset (mdh);
+ gcry_md_write (mdh, digest, n_digest);
+ gcry_md_final (mdh);
+ digested = gcry_md_read (mdh, 0);
+ g_return_val_if_fail (digested, FALSE);
+ memcpy (digest, digested, n_digest);
+ }
+
+ /* Copy as much as possible into the destinations */
+ i = 0;
+ while (needed_key && i < n_digest) {
+ if (at_key)
+ *(at_key++) = digest[i];
+ needed_key--;
+ i++;
+ }
+ while (needed_iv && i < n_digest) {
+ if (at_iv)
+ *(at_iv++) = digest[i];
+ needed_iv--;
+ i++;
+ }
+
+ if (needed_key == 0 && needed_iv == 0)
+ break;
+ }
+
+ gkr_secure_free (digest);
+ gcry_md_close (mdh);
+
+ return TRUE;
+}
+
+gboolean
+gck_crypto_symkey_generate_pbe (int cipher_algo, int hash_algo, const gchar *password,
+ const guchar *salt, gsize n_salt, int iterations,
+ guchar **key, guchar **iv)
+{
+ gcry_md_hd_t mdh;
+ gcry_error_t gcry;
+ guchar *digest;
+ guchar *digested;
+ guint i, n_digest;
+ gint needed_iv, needed_key;
+
+ g_assert (cipher_algo);
+ g_assert (hash_algo);
+
+ g_return_val_if_fail (iterations >= 1, FALSE);
+
+ /*
+ * We only do one pass here.
+ *
+ * The key ends up as the first needed_key bytes of the hash buffer.
+ * The iv ends up as the last needed_iv bytes of the hash buffer.
+ *
+ * The IV may overlap the key (which is stupid) if the wrong pair of
+ * hash/cipher algorithms are chosen.
+ */
+
+ n_digest = gcry_md_get_algo_dlen (hash_algo);
+ g_return_val_if_fail (n_digest > 0, FALSE);
+
+ needed_key = gcry_cipher_get_algo_keylen (cipher_algo);
+ needed_iv = gcry_cipher_get_algo_blklen (cipher_algo);
+ if (needed_iv + needed_key > 16 || needed_iv + needed_key > n_digest) {
+ g_warning ("using PBE symkey generation with %s using an algorithm that needs "
+ "too many bytes of key and/or IV: %s",
+ gcry_cipher_algo_name (hash_algo),
+ gcry_cipher_algo_name (cipher_algo));
+ return FALSE;
+ }
+
+ gcry = gcry_md_open (&mdh, hash_algo, 0);
+ if (gcry) {
+ g_warning ("couldn't create '%s' hash context: %s",
+ gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
+ return FALSE;
+ }
+
+ digest = gkr_secure_alloc (n_digest);
+ g_return_val_if_fail (digest, FALSE);
+ if (key) {
+ *key = gkr_secure_alloc (needed_key);
+ g_return_val_if_fail (*key, FALSE);
+ }
+ if (iv)
+ *iv = g_new0 (guchar, needed_iv);
+
+ if (password)
+ gcry_md_write (mdh, password, strlen (password));
+ if (salt && n_salt)
+ gcry_md_write (mdh, salt, n_salt);
+ gcry_md_final (mdh);
+ digested = gcry_md_read (mdh, 0);
+ g_return_val_if_fail (digested, FALSE);
+ memcpy (digest, digested, n_digest);
+
+ for (i = 1; i < iterations; ++i)
+ gcry_md_hash_buffer (hash_algo, digest, digest, n_digest);
+
+ /* The first x bytes are the key */
+ if (key) {
+ g_assert (needed_key <= n_digest);
+ memcpy (*key, digest, needed_key);
+ }
+
+ /* The last 16 - x bytes are the iv */
+ if (iv) {
+ g_assert (needed_iv <= n_digest && n_digest >= 16);
+ memcpy (*iv, digest + (16 - needed_iv), needed_iv);
+ }
+
+ gkr_secure_free (digest);
+ gcry_md_close (mdh);
+
+ return TRUE;
+}
+
+static gboolean
+generate_pkcs12 (int hash_algo, int type, const gchar *utf8_password,
+ const guchar *salt, gsize n_salt, int iterations,
+ guchar *output, gsize n_output)
+{
+ gcry_mpi_t num_b1, num_ij;
+ guchar *hash, *buf_i, *buf_b;
+ gcry_md_hd_t mdh;
+ const gchar *p2;
+ guchar *p;
+ gsize n_hash, i;
+ gunichar unich;
+ gcry_error_t gcry;
+
+ num_b1 = num_ij = NULL;
+
+ n_hash = gcry_md_get_algo_dlen (hash_algo);
+ g_return_val_if_fail (n_hash > 0, FALSE);
+
+ gcry = gcry_md_open (&mdh, hash_algo, 0);
+ if (gcry) {
+ g_warning ("couldn't create '%s' hash context: %s",
+ gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
+ return FALSE;
+ }
+
+ /* Reqisition me a buffer */
+ hash = gkr_secure_alloc (n_hash);
+ buf_i = gkr_secure_alloc (128);
+ buf_b = gkr_secure_alloc (64);
+ g_return_val_if_fail (hash && buf_i && buf_b, FALSE);
+
+ /* Bring in the salt */
+ p = buf_i;
+ if (salt) {
+ for (i = 0; i < 64; ++i)
+ *(p++) = salt[i % n_salt];
+ } else {
+ memset (p, 0, 64);
+ p += 64;
+ }
+
+ /* Bring in the password, as 16bits per character BMP string, ie: UCS2 */
+ if (utf8_password) {
+ p2 = utf8_password;
+ for (i = 0; i < 64; i += 2) {
+ unich = *p2 ? g_utf8_get_char (p2) : 0;
+ *(p++) = (unich & 0xFF00) >> 8;
+ *(p++) = (unich & 0xFF);
+ if (*p2) /* Loop back to beginning if more bytes are needed */
+ p2 = g_utf8_next_char (p2);
+ else
+ p2 = utf8_password;
+ }
+ } else {
+ memset (p, 0, 64);
+ p += 64;
+ }
+
+ /* Hash and bash */
+ for (;;) {
+ gcry_md_reset (mdh);
+
+ /* Put in the PKCS#12 type of key */
+ for (i = 0; i < 64; ++i)
+ gcry_md_putc (mdh, type);
+
+ /* Bring in the password */
+ gcry_md_write (mdh, buf_i, utf8_password ? 128 : 64);
+
+ /* First iteration done */
+ memcpy (hash, gcry_md_read (mdh, hash_algo), n_hash);
+
+ /* All the other iterations */
+ for (i = 1; i < iterations; i++)
+ gcry_md_hash_buffer (hash_algo, hash, hash, n_hash);
+
+ /* Take out as much as we need */
+ for (i = 0; i < n_hash && n_output; ++i) {
+ *(output++) = hash[i];
+ --n_output;
+ }
+
+ /* Is that enough generated keying material? */
+ if (!n_output)
+ break;
+
+ /* Need more bytes, do some voodoo */
+ for (i = 0; i < 64; ++i)
+ buf_b[i] = hash[i % n_hash];
+ gcry = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, 64, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ gcry_mpi_add_ui (num_b1, num_b1, 1);
+ for (i = 0; i < 128; i += 64) {
+ gcry = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, 64, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ gcry_mpi_add (num_ij, num_ij, num_b1);
+ gcry_mpi_clear_highbit (num_ij, 64 * 8);
+ gcry = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, 64, NULL, num_ij);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ gcry_mpi_release (num_ij);
+ }
+ }
+
+ gkr_secure_free (buf_i);
+ gkr_secure_free (buf_b);
+ gkr_secure_free (hash);
+ gcry_mpi_release (num_b1);
+ gcry_md_close (mdh);
+
+ return TRUE;
+}
+
+gboolean
+gck_crypto_symkey_generate_pkcs12 (int cipher_algo, int hash_algo, const gchar *password,
+ const guchar *salt, gsize n_salt,
+ int iterations, guchar **key, guchar **iv)
+{
+ gsize n_block, n_key;
+ gboolean ret = TRUE;
+
+ g_return_val_if_fail (cipher_algo, FALSE);
+ g_return_val_if_fail (hash_algo, FALSE);
+ g_return_val_if_fail (iterations > 0, FALSE);
+
+ n_key = gcry_cipher_get_algo_keylen (cipher_algo);
+ n_block = gcry_cipher_get_algo_blklen (cipher_algo);
+
+ if (password && !g_utf8_validate (password, -1, NULL)) {
+ g_warning ("invalid non-UTF8 password");
+ g_return_val_if_reached (FALSE);
+ }
+
+ if (key)
+ *key = NULL;
+ if (iv)
+ *iv = NULL;
+
+ /* Generate us an key */
+ if (key) {
+ *key = gkr_secure_alloc (n_key);
+ g_return_val_if_fail (*key != NULL, FALSE);
+ ret = generate_pkcs12 (hash_algo, 1, password, salt, n_salt,
+ iterations, *key, n_key);
+ }
+
+ /* Generate us an iv */
+ if (ret && iv) {
+ if (n_block > 1) {
+ *iv = g_malloc (n_block);
+ ret = generate_pkcs12 (hash_algo, 2, password, salt, n_salt,
+ iterations, *iv, n_block);
+ } else {
+ *iv = NULL;
+ }
+ }
+
+ /* Cleanup in case of failure */
+ if (!ret) {
+ g_free (iv ? *iv : NULL);
+ g_free (key ? *key : NULL);
+ }
+
+ return ret;
+}
+
+static gboolean
+generate_pbkdf2 (int hash_algo, const gchar *password, gsize n_password,
+ const guchar *salt, gsize n_salt, guint iterations,
+ guchar *output, gsize n_output)
+{
+ gcry_md_hd_t mdh;
+ guint u, l, r, i, k;
+ gcry_error_t gcry;
+ guchar *U, *T, *buf;
+ gsize n_buf, n_hash;
+
+ g_return_val_if_fail (hash_algo > 0, FALSE);
+ g_return_val_if_fail (iterations > 0, FALSE);
+ g_return_val_if_fail (n_output > 0, FALSE);
+ g_return_val_if_fail (n_output < G_MAXUINT32, FALSE);
+
+ n_hash = gcry_md_get_algo_dlen (hash_algo);
+ g_return_val_if_fail (n_hash > 0, FALSE);
+
+ gcry = gcry_md_open (&mdh, hash_algo, GCRY_MD_FLAG_HMAC);
+ if (gcry != 0) {
+ g_warning ("couldn't create '%s' hash context: %s",
+ gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
+ return FALSE;
+ }
+
+ /* Get us a temporary buffers */
+ T = gkr_secure_alloc (n_hash);
+ U = gkr_secure_alloc (n_hash);
+ n_buf = n_salt + 4;
+ buf = gkr_secure_alloc (n_buf);
+ g_return_val_if_fail (buf && T && U, FALSE);
+
+ /* n_hash blocks in output, rounding up */
+ l = ((n_output - 1) / n_hash) + 1;
+
+ /* number of bytes in last, rounded up, n_hash block */
+ r = n_output - (l - 1) * n_hash;
+
+ memcpy (buf, salt, n_salt);
+ for (i = 1; i <= l; i++) {
+ memset (T, 0, n_hash);
+ for (u = 1; u <= iterations; u++) {
+ gcry_md_reset (mdh);
+
+ gcry = gcry_md_setkey (mdh, password, n_password);
+ g_return_val_if_fail (gcry == 0, FALSE);
+
+ /* For first iteration on each block add 4 extra bytes */
+ if (u == 1) {
+ buf[n_salt + 0] = (i & 0xff000000) >> 24;
+ buf[n_salt + 1] = (i & 0x00ff0000) >> 16;
+ buf[n_salt + 2] = (i & 0x0000ff00) >> 8;
+ buf[n_salt + 3] = (i & 0x000000ff) >> 0;
+
+ gcry_md_write (mdh, buf, n_buf);
+
+ /* Other iterations, any block */
+ } else {
+ gcry_md_write (mdh, U, n_hash);
+ }
+
+ memcpy (U, gcry_md_read (mdh, hash_algo), n_hash);
+
+ for (k = 0; k < n_hash; k++)
+ T[k] ^= U[k];
+ }
+
+ memcpy (output + (i - 1) * n_hash, T, i == l ? r : n_hash);
+ }
+
+ gkr_secure_free (T);
+ gkr_secure_free (U);
+ gkr_secure_free (buf);
+ gcry_md_close (mdh);
+ return TRUE;
+}
+
+gboolean
+gck_crypto_symkey_generate_pbkdf2 (int cipher_algo, int hash_algo,
+ const gchar *password, const guchar *salt,
+ gsize n_salt, int iterations,
+ guchar **key, guchar **iv)
+{
+ gsize n_key, n_block, n_password;
+ gboolean ret = TRUE;
+
+ g_return_val_if_fail (hash_algo, FALSE);
+ g_return_val_if_fail (cipher_algo, FALSE);
+ g_return_val_if_fail (iterations > 0, FALSE);
+
+ n_key = gcry_cipher_get_algo_keylen (cipher_algo);
+ n_block = gcry_cipher_get_algo_blklen (cipher_algo);
+
+ if (key)
+ *key = NULL;
+ if (iv)
+ *iv = NULL;
+
+ n_password = password ? strlen (password) : 0;
+
+ /* Generate us an key */
+ if (key) {
+ *key = gkr_secure_alloc (n_key);
+ g_return_val_if_fail (*key != NULL, FALSE);
+ ret = generate_pbkdf2 (hash_algo, password, n_password, salt, n_salt,
+ iterations, *key, n_key);
+ }
+
+ /* Generate us an iv */
+ if (ret && iv) {
+ if (n_block > 1) {
+ *iv = g_malloc (n_block);
+ gcry_create_nonce (*iv, n_block);
+ } else {
+ *iv = NULL;
+ }
+ }
+
+ /* Cleanup in case of failure */
+ if (!ret) {
+ g_free (iv ? *iv : NULL);
+ g_free (key ? *key : NULL);
+ }
+
+ return ret;
+}
+
+/* --------------------------------------------------------------------------
+ * INITIALIZATION
+ */
+
+static void
+log_handler (gpointer unused, int unknown, const gchar *msg, va_list va)
+{
+ /* TODO: Figure out additional arguments */
+ g_logv ("gcrypt", G_LOG_LEVEL_MESSAGE, msg, va);
+}
+
+static int
+no_mem_handler (gpointer unused, size_t sz, unsigned int unknown)
+{
+ /* TODO: Figure out additional arguments */
+ g_error ("couldn't allocate %lu bytes of memory",
+ (unsigned long int)sz);
+ return 0;
+}
+
+static void
+fatal_handler (gpointer unused, int unknown, const gchar *msg)
+{
+ /* TODO: Figure out additional arguments */
+ g_log ("gcrypt", G_LOG_LEVEL_ERROR, "%s", msg);
+}
+
+static int
+glib_thread_mutex_init (void **lock)
+{
+ *lock = g_mutex_new ();
+ return 0;
+}
+
+static int
+glib_thread_mutex_destroy (void **lock)
+{
+ g_mutex_free (*lock);
+ return 0;
+}
+
+static int
+glib_thread_mutex_lock (void **lock)
+{
+ g_mutex_lock (*lock);
+ return 0;
+}
+
+static int
+glib_thread_mutex_unlock (void **lock)
+{
+ g_mutex_unlock (*lock);
+ return 0;
+}
+
+static struct gcry_thread_cbs glib_thread_cbs = {
+ GCRY_THREAD_OPTION_USER, NULL,
+ glib_thread_mutex_init, glib_thread_mutex_destroy,
+ glib_thread_mutex_lock, glib_thread_mutex_unlock,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+void
+gck_crypto_initialize (void)
+{
+ static gsize gcrypt_initialized = FALSE;
+ unsigned seed;
+
+ if (g_once_init_enter (&gcrypt_initialized)) {
+ gcry_control (GCRYCTL_SET_THREAD_CBS, &glib_thread_cbs);
+ gcry_check_version (LIBGCRYPT_VERSION);
+ gcry_set_log_handler (log_handler, NULL);
+ gcry_set_outofcore_handler (no_mem_handler, NULL);
+ gcry_set_fatalerror_handler (fatal_handler, NULL);
+ gcry_set_allocation_handler ((gcry_handler_alloc_t)g_malloc,
+ (gcry_handler_alloc_t)gkr_secure_alloc,
+ gkr_secure_check,
+ (gcry_handler_realloc_t)gkr_secure_realloc,
+ gkr_secure_free);
+ gcry_create_nonce (&seed, sizeof (seed));
+ srand (seed);
+
+ g_once_init_leave (&gcrypt_initialized, 1);
+ }
+}
Modified: trunk/pkcs11/gck/gck-crypto.h
==============================================================================
--- trunk/pkcs11/gck/gck-crypto.h (original)
+++ trunk/pkcs11/gck/gck-crypto.h Mon Dec 22 20:21:06 2008
@@ -40,6 +40,8 @@
CKM_DSA
};
+void gck_crypto_initialize (void);
+
CK_RV gck_crypto_perform (gcry_sexp_t sexp,
CK_MECHANISM_TYPE mech,
CK_ATTRIBUTE_TYPE method,
@@ -157,4 +159,40 @@
gsize n_padded,
gsize *n_raw);
+gboolean gck_crypto_symkey_generate_simple (int cipher_algo,
+ int hash_algo,
+ const gchar *password,
+ const guchar *salt,
+ gsize n_salt,
+ int iterations,
+ guchar **key,
+ guchar **iv);
+
+gboolean gck_crypto_symkey_generate_pbe (int cipher_algo,
+ int hash_algo,
+ const gchar *password,
+ const guchar *salt,
+ gsize n_salt,
+ int iterations,
+ guchar **key,
+ guchar **iv);
+
+gboolean gck_crypto_symkey_generate_pkcs12 (int cipher_algo,
+ int hash_algo,
+ const gchar *password,
+ const guchar *salt,
+ gsize n_salt,
+ int iterations,
+ guchar **key,
+ guchar **iv);
+
+gboolean gck_crypto_symkey_generate_pbkdf2 (int cipher_algo,
+ int hash_algo,
+ const gchar *password,
+ const guchar *salt,
+ gsize n_salt,
+ int iterations,
+ guchar **key,
+ guchar **iv);
+
#endif /* GCKCRYPTO_H_ */
Added: trunk/pkcs11/gck/gck-data-asn1.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-asn1.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,798 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gkr-pkix-asn1.c - ASN.1 helper routines
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gck-data-asn1.h"
+
+#include "common/gkr-buffer.h"
+#include "common/gkr-secure-memory.h"
+
+#include <libtasn1.h>
+
+/*
+ * HACK: asn1Parser defines these arrays as extern const, which gives
+ * gcc a fit. So we def it out.
+ */
+
+#define extern
+#include "asn1-def-pk.h"
+#include "asn1-def-pkix.h"
+#undef extern
+
+static ASN1_TYPE asn1_pk = NULL;
+static ASN1_TYPE asn1_pkix = NULL;
+
+static void
+init_asn1_trees (void)
+{
+ static gsize asn1_initialized = 0;
+ int res;
+
+ if (g_once_init_enter (&asn1_initialized)) {
+ res = asn1_array2tree (pk_asn1_tab, &asn1_pk, NULL);
+ g_return_if_fail (res == ASN1_SUCCESS);
+ res = asn1_array2tree (pkix_asn1_tab, &asn1_pkix, NULL);
+ g_return_if_fail (res == ASN1_SUCCESS);
+ g_once_init_leave (&asn1_initialized, 1);
+ }
+}
+
+ASN1_TYPE
+gck_data_asn1_get_pk_asn1type (void)
+{
+ init_asn1_trees ();
+ return asn1_pk;
+}
+
+ASN1_TYPE
+gck_data_asn1_get_pkix_asn1type (void)
+{
+ init_asn1_trees ();
+ return asn1_pkix;
+}
+
+ASN1_TYPE
+gck_data_asn1_decode (const gchar *type, const guchar *data, gsize n_data)
+{
+ ASN1_TYPE base = ASN1_TYPE_EMPTY;
+ ASN1_TYPE asn;
+ int res;
+
+ if (strncmp (type, "PKIX1.", 6) == 0)
+ base = gck_data_asn1_get_pkix_asn1type ();
+ else if (strncmp (type, "PK.", 3) == 0)
+ base = gck_data_asn1_get_pk_asn1type ();
+ else
+ g_return_val_if_reached (NULL);
+
+ res = asn1_create_element (base, type, &asn);
+ g_return_val_if_fail (res == ASN1_SUCCESS, NULL);
+
+ res = asn1_der_decoding (&asn, data, n_data, NULL);
+ if (res != ASN1_SUCCESS) {
+ asn1_delete_structure (&asn);
+ return NULL;
+ }
+
+ return asn;
+}
+
+guchar*
+gck_data_asn1_encode (ASN1_TYPE asn, const gchar* part, gsize *n_data,
+ GkrBufferAllocator alloc)
+{
+ guchar *data;
+ int res, len;
+
+ g_assert (asn);
+ g_assert (n_data);
+
+ len = 0;
+ res = asn1_der_coding (asn, part, NULL, &len, NULL);
+ g_return_val_if_fail (res == ASN1_MEM_ERROR, NULL);
+
+ if (!alloc)
+ alloc = (GkrBufferAllocator)g_realloc;
+
+ data = (alloc) (NULL, len);
+ g_return_val_if_fail (data != NULL, NULL);
+
+ res = asn1_der_coding (asn, part, data, &len, NULL);
+ if (res != ASN1_SUCCESS) {
+ (alloc) (data, 0);
+ return NULL;
+ }
+
+ *n_data = len;
+ return data;
+}
+
+gint
+gck_data_asn1_element_length (const guchar *data, gsize n_data)
+{
+ guchar cls;
+ int counter = 0;
+ int cb, len;
+ gulong tag;
+
+ if (asn1_get_tag_der (data, n_data, &cls, &cb, &tag) == ASN1_SUCCESS) {
+ counter += cb;
+ len = asn1_get_length_der (data + cb, n_data - cb, &cb);
+ counter += cb;
+ if (len >= 0) {
+ len += counter;
+ if (n_data >= len)
+ return len;
+ }
+ }
+
+ return -1;
+}
+
+#ifdef UNTESTED_CODE
+
+const guchar*
+gck_data_asn1_read_element (ASN1_TYPE asn, const guchar *data, gsize n_data,
+ const gchar *part, gsize *n_element)
+{
+ int beg, end, res;
+
+ g_return_val_if_fail (asn != NULL, NULL);
+ g_return_val_if_fail (part != NULL, NULL);
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (n_element != NULL, NULL);
+
+ res = asn1_der_decoding_startEnd (asn, data, n_data, part, &beg, &end);
+ if (res != ASN1_SUCCESS)
+ return NULL;
+
+ *n_element = end - beg + 1;
+ return data + beg;
+}
+
+const guchar*
+gck_data_asn1_read_content (ASN1_TYPE asn, const guchar *data, gsize n_data,
+ const gchar *part, gsize *n_content)
+{
+ const guchar *raw;
+ gsize n_raw;
+
+ g_return_val_if_fail (asn != NULL, NULL);
+ g_return_val_if_fail (part != NULL, NULL);
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (n_content != NULL, NULL);
+
+ raw = gck_data_asn1_read_element (asn, data, n_data, part, &n_raw);
+ if (!raw)
+ return NULL;
+
+ return gck_data_asn1_element_content (raw, n_raw, n_content);
+}
+
+#endif /* UNTESTED_CODE */
+
+const guchar*
+gck_data_asn1_element_content (const guchar *data, gsize n_data, gsize *n_content)
+{
+ int counter = 0;
+ guchar cls;
+ gulong tag;
+ int cb, len;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (n_content != NULL, NULL);
+
+ /* Now get the data out of this element */
+ if (asn1_get_tag_der (data, n_data, &cls, &cb, &tag) != ASN1_SUCCESS)
+ return NULL;
+
+ counter += cb;
+ len = asn1_get_length_der (data + cb, n_data - cb, &cb);
+ if (len < 0)
+ return NULL;
+ counter += cb;
+
+ *n_content = len;
+ return data + counter;
+}
+
+guchar*
+gck_data_asn1_read_value (ASN1_TYPE asn, const gchar *part, gsize *len,
+ GkrBufferAllocator allocator)
+{
+ int l, res;
+ guchar *buf;
+
+ g_return_val_if_fail (asn != NULL, NULL);
+ g_return_val_if_fail (part != NULL, NULL);
+ g_return_val_if_fail (len != NULL, NULL);
+
+ if (allocator == NULL)
+ allocator = (GkrBufferAllocator)g_realloc;
+
+ *len = 0;
+
+ l = 0;
+ res = asn1_read_value (asn, part, NULL, &l);
+ g_return_val_if_fail (res != ASN1_SUCCESS, NULL);
+ if (res != ASN1_MEM_ERROR)
+ return NULL;
+
+ /* Always null terminate it, just for convenience */
+ buf = (allocator) (NULL, l + 1);
+ g_return_val_if_fail (buf, NULL);
+ memset (buf, 0, *len + 1);
+
+ res = asn1_read_value (asn, part, buf, &l);
+ if (res != ASN1_SUCCESS) {
+ (allocator) (buf, 0);
+ buf = NULL;
+ } else {
+ *len = l;
+ }
+
+ return buf;
+}
+
+gboolean
+gck_data_asn1_write_value (ASN1_TYPE asn, const gchar *part,
+ const guchar* value, gsize len)
+{
+ int res;
+
+ g_return_val_if_fail (asn, FALSE);
+ g_return_val_if_fail (part, FALSE);
+ g_return_val_if_fail (!len || value, FALSE);
+
+ res = asn1_write_value (asn, part, (const void*)value, (int)len);
+ return res == ASN1_SUCCESS;
+}
+
+#ifdef UNTESTED_CODE
+
+gboolean
+gck_data_asn1_read_boolean (ASN1_TYPE asn, const gchar *part, gboolean *val)
+{
+ gchar buffer[32];
+ int n_buffer = sizeof (buffer) - 1;
+ int res;
+
+ memset (buffer, 0, sizeof (buffer));
+
+ res = asn1_read_value (asn, part, buffer, &n_buffer);
+ if (res != ASN1_SUCCESS)
+ return FALSE;
+
+ if (g_ascii_strcasecmp (buffer, "TRUE") == 0)
+ *val = TRUE;
+ else
+ *val = FALSE;
+
+ return TRUE;
+}
+
+#endif /* UNTESTED_CODE */
+
+gboolean
+gck_data_asn1_read_uint (ASN1_TYPE asn, const gchar *part, guint *val)
+{
+ guchar buf[4];
+ int n_buf = sizeof (buf);
+ gsize i;
+ int res;
+
+ res = asn1_read_value (asn, part, buf, &n_buf);
+ if(res != ASN1_SUCCESS)
+ return FALSE;
+
+ if (n_buf > 4 || n_buf < 1)
+ return FALSE;
+
+ *val = 0;
+ for (i = 0; i < n_buf; ++i)
+ *val |= buf[i] << (8 * ((n_buf - 1) - i));
+
+ return TRUE;
+}
+
+gboolean
+gck_data_asn1_write_uint (ASN1_TYPE asn, const gchar *part, guint32 val)
+{
+ guchar buf[4];
+ int res, bytes;
+
+ buf[0] = (val >> 24) & 0xff;
+ buf[1] = (val >> 16) & 0xff;
+ buf[2] = (val >> 8) & 0xff;
+ buf[3] = (val >> 0) & 0xff;
+
+ for (bytes = 3; bytes >= 0; --bytes)
+ if (!buf[bytes])
+ break;
+
+ bytes = 4 - (bytes + 1);
+ if (bytes == 0)
+ bytes = 1;
+ res = asn1_write_value (asn, part, buf + (4 - bytes), bytes);
+ return res == ASN1_SUCCESS;
+}
+
+#ifdef UNTESTED_CODE
+
+GQuark
+gck_data_asn1_read_oid (ASN1_TYPE asn, const gchar *part)
+{
+ GQuark quark;
+ guchar *buf;
+ gsize n_buf;
+
+ buf = gck_data_asn1_read_value (asn, part, &n_buf, NULL);
+ if (!buf)
+ return 0;
+
+ /* TODO: This should probably just 'try' */
+ quark = g_quark_from_string ((gchar*)buf);
+ g_free (buf);
+
+ return quark;
+}
+
+gboolean
+gck_data_asn1_write_oid (ASN1_TYPE asn, const gchar *part, GQuark val)
+{
+ const gchar* oid;
+
+ g_return_val_if_fail (val, FALSE);
+
+ oid = g_quark_to_string (val);
+ g_return_val_if_fail (oid, FALSE);
+
+ return gck_data_asn1_write_value (asn, part, (const guchar*)oid,
+ 1 /* any non-null value for OID */);
+}
+
+#endif /* UNTESTED_CODE */
+
+gboolean
+gck_data_asn1_read_mpi (ASN1_TYPE asn, const gchar *part, gcry_mpi_t *mpi)
+{
+ gcry_error_t gcry;
+ gsize sz;
+ guchar *buf;
+
+ buf = gck_data_asn1_read_value (asn, part, &sz, (GkrBufferAllocator)g_realloc);
+ if (!buf)
+ return FALSE;
+
+ gcry = gcry_mpi_scan (mpi, GCRYMPI_FMT_STD, buf, sz, &sz);
+ g_free (buf);
+
+ if (gcry != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gck_data_asn1_read_secure_mpi (ASN1_TYPE asn, const gchar *part, gcry_mpi_t *mpi)
+{
+ gcry_error_t gcry;
+ gsize sz;
+ guchar *buf;
+
+ buf = gck_data_asn1_read_value (asn, part, &sz, gkr_secure_realloc);
+ if (!buf)
+ return FALSE;
+
+ gcry = gcry_mpi_scan (mpi, GCRYMPI_FMT_STD, buf, sz, &sz);
+ gkr_secure_free (buf);
+
+ if (gcry != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gck_data_asn1_write_mpi (ASN1_TYPE asn, const gchar *part, gcry_mpi_t mpi)
+{
+ gcry_error_t gcry;
+ gsize len;
+ guchar *buf;
+ int res;
+
+ g_assert (asn);
+ g_assert (part);
+ g_assert (mpi);
+
+ /* Get the size */
+ gcry = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &len, mpi);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ g_return_val_if_fail (len > 0, FALSE);
+
+ buf = gkr_secure_alloc (len);
+
+ gcry = gcry_mpi_print (GCRYMPI_FMT_STD, buf, len, &len, mpi);
+ g_return_val_if_fail (gcry == 0, FALSE);
+
+ res = asn1_write_value (asn, part, buf, len);
+ gkr_secure_free (buf);
+
+ if (res != ASN1_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int
+atoin (const char *p, int digits)
+{
+ int ret = 0, base = 1;
+ while(--digits >= 0) {
+ if (p[digits] < '0' || p[digits] > '9')
+ return -1;
+ ret += (p[digits] - '0') * base;
+ base *= 10;
+ }
+ return ret;
+}
+
+static int
+two_to_four_digit_year (int year)
+{
+ time_t now;
+ struct tm tm;
+ int century, current;
+
+ g_return_val_if_fail (year >= 0 && year <= 99, -1);
+
+ /* Get the current year */
+ now = time (NULL);
+ g_return_val_if_fail (now >= 0, -1);
+ if (!gmtime_r (&now, &tm))
+ g_return_val_if_reached (-1);
+
+ current = (tm.tm_year % 100);
+ century = (tm.tm_year + 1900) - current;
+
+ /*
+ * Check if it's within 40 years before the
+ * current date.
+ */
+ if (current < 40) {
+ if (year < current)
+ return century + year;
+ if (year > 100 - (40 - current))
+ return (century - 100) + year;
+ } else {
+ if (year < current && year > (current - 40))
+ return century + year;
+ }
+
+ /*
+ * If it's after then adjust for overflows to
+ * the next century.
+ */
+ if (year < current)
+ return century + 100 + year;
+ else
+ return century + year;
+}
+
+#ifndef HAVE_TIMEGM
+time_t timegm(struct tm *t)
+{
+ time_t tl, tb;
+ struct tm *tg;
+
+ tl = mktime (t);
+ if (tl == -1)
+ {
+ t->tm_hour--;
+ tl = mktime (t);
+ if (tl == -1)
+ return -1; /* can't deal with output from strptime */
+ tl += 3600;
+ }
+ tg = gmtime (&tl);
+ tg->tm_isdst = 0;
+ tb = mktime (tg);
+ if (tb == -1)
+ {
+ tg->tm_hour--;
+ tb = mktime (tg);
+ if (tb == -1)
+ return -1; /* can't deal with output from gmtime */
+ tb += 3600;
+ }
+ return (tl - (tb - tl));
+}
+#endif //NOT_HAVE_TIMEGM
+
+time_t
+gck_data_asn1_parse_utc_time (const gchar *time)
+{
+ struct tm when;
+ guint n_time;
+ time_t result;
+ const char *p, *e;
+ int year;
+
+ g_assert (time);
+ n_time = strlen (time);
+
+ /* YYMMDDhhmmss.ffff Z | +0000 */
+ if (n_time < 6 || n_time >= 28)
+ return -1;
+
+ /* Reset everything to default legal values */
+ memset (&when, 0, sizeof (when));
+ when.tm_mday = 1;
+
+ /* Select the digits part of it */
+ p = time;
+ for (e = p; *e >= '0' && *e <= '9'; ++e);
+
+ if (p + 2 <= e) {
+ year = atoin (p, 2);
+ p += 2;
+
+ /*
+ * 40 years in the past is our century. 60 years
+ * in the future is the next century.
+ */
+ when.tm_year = two_to_four_digit_year (year) - 1900;
+ }
+ if (p + 2 <= e) {
+ when.tm_mon = atoin (p, 2) - 1;
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when.tm_mday = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when.tm_hour = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when.tm_min = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when.tm_sec = atoin (p, 2);
+ p += 2;
+ }
+
+ if (when.tm_year < 0 || when.tm_year > 9999 ||
+ when.tm_mon < 0 || when.tm_mon > 11 ||
+ when.tm_mday < 1 || when.tm_mday > 31 ||
+ when.tm_hour < 0 || when.tm_hour > 23 ||
+ when.tm_min < 0 || when.tm_min > 59 ||
+ when.tm_sec < 0 || when.tm_sec > 59)
+ return -1;
+
+ /* Make sure all that got parsed */
+ if (p != e)
+ return -1;
+
+ /* In order to work with 32 bit time_t. */
+ if (sizeof (time_t) <= 4 && when.tm_year >= 2038)
+ return (time_t) 2145914603; /* 2037-12-31 23:23:23 */
+
+ /* Covnvert to seconds since epoch */
+ result = timegm (&when);
+
+ /* Now the remaining optional stuff */
+ e = time + n_time;
+
+ /* See if there's a fraction, and discard it if so */
+ if (p < e && *p == '.' && p + 5 <= e)
+ p += 5;
+
+ /* See if it's UTC */
+ if (p < e && *p == 'Z') {
+ p += 1;
+
+ /* See if it has a timezone */
+ } else if ((*p == '-' || *p == '+') && p + 3 <= e) {
+ int off, neg;
+
+ neg = *p == '-';
+ ++p;
+
+ off = atoin (p, 2) * 3600;
+ if (off < 0 || off > 86400)
+ return -1;
+ p += 2;
+
+ if (p + 2 <= e) {
+ off += atoin (p, 2) * 60;
+ p += 2;
+ }
+
+ /* Use TZ offset */
+ if (neg)
+ result -= off;
+ else
+ result += off;
+ }
+
+ /* Make sure everything got parsed */
+ if (p != e)
+ return -1;
+
+ return result;
+}
+
+time_t
+gck_data_asn1_parse_general_time (const gchar *time)
+{
+ struct tm when;
+ guint n_time;
+ time_t result;
+ const char *p, *e;
+
+ g_assert (time);
+ n_time = strlen (time);
+
+ /* YYYYMMDDhhmmss.ffff Z | +0000 */
+ if (n_time < 8 || n_time >= 30)
+ return -1;
+
+ /* Reset everything to default legal values */
+ memset (&when, 0, sizeof (when));
+ when.tm_mday = 1;
+
+ /* Select the digits part of it */
+ p = time;
+ for (e = p; *e >= '0' && *e <= '9'; ++e);
+
+ if (p + 4 <= e) {
+ when.tm_year = atoin (p, 4) - 1900;
+ p += 4;
+ }
+ if (p + 2 <= e) {
+ when.tm_mon = atoin (p, 2) - 1;
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when.tm_mday = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when.tm_hour = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when.tm_min = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when.tm_sec = atoin (p, 2);
+ p += 2;
+ }
+
+ if (when.tm_year < 0 || when.tm_year > 9999 ||
+ when.tm_mon < 0 || when.tm_mon > 11 ||
+ when.tm_mday < 1 || when.tm_mday > 31 ||
+ when.tm_hour < 0 || when.tm_hour > 23 ||
+ when.tm_min < 0 || when.tm_min > 59 ||
+ when.tm_sec < 0 || when.tm_sec > 59)
+ return -1;
+
+ /* Make sure all that got parsed */
+ if (p != e)
+ return -1;
+
+ /* Covnvert to seconds since epoch */
+ result = timegm (&when);
+
+ /* Now the remaining optional stuff */
+ e = time + n_time;
+
+ /* See if there's a fraction, and discard it if so */
+ if (p < e && *p == '.' && p + 5 <= e)
+ p += 5;
+
+ /* See if it's UTC */
+ if (p < e && *p == 'Z') {
+ p += 1;
+
+ /* See if it has a timezone */
+ } else if ((*p == '-' || *p == '+') && p + 3 <= e) {
+ int off, neg;
+
+ neg = *p == '-';
+ ++p;
+
+ off = atoin (p, 2) * 3600;
+ if (off < 0 || off > 86400)
+ return -1;
+ p += 2;
+
+ if (p + 2 <= e) {
+ off += atoin (p, 2) * 60;
+ p += 2;
+ }
+
+ /* Use TZ offset */
+ if (neg)
+ result -= off;
+ else
+ result += off;
+ }
+
+ /* Make sure everything got parsed */
+ if (p != e)
+ return -1;
+
+ return result;
+}
+
+#ifdef UNTESTED_CODE
+
+gboolean
+gck_data_asn1_read_time (ASN1_TYPE asn, const gchar *part, time_t *val)
+{
+ #define MAX_TIME 1024
+ gchar ttime[MAX_TIME];
+ gchar *name;
+ int len, res;
+
+ len = sizeof (ttime) - 1;
+ res = asn1_read_value (asn, part, ttime, &len);
+ if (res != ASN1_SUCCESS)
+ return FALSE;
+
+ /* CHOICE */
+ if (strcmp (ttime, "generalTime") == 0) {
+ name = g_strconcat (part, ".generalTime", NULL);
+ len = sizeof (ttime) - 1;
+ res = asn1_read_value (asn, name, ttime, &len);
+ g_free (name);
+ if (res != ASN1_SUCCESS)
+ return FALSE;
+
+ *val = gck_data_asn1_parse_general_time (ttime);
+
+ /* UTCTIME */
+ } else {
+ name = g_strconcat (part, ".utcTime", NULL);
+ len = sizeof (ttime) - 1;
+ res = asn1_read_value (asn, name, ttime, &len);
+ g_free (name);
+ if (res != ASN1_SUCCESS)
+ return FALSE;
+
+ *val = gck_data_asn1_parse_utc_time (ttime);
+ }
+
+ if (*val < (time_t)0)
+ return FALSE;
+
+ return TRUE;
+}
+
+#endif /* UNTESTED_CODE */
Added: trunk/pkcs11/gck/gck-data-asn1.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-asn1.h Mon Dec 22 20:21:06 2008
@@ -0,0 +1,84 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-data-asn1.h - ASN.1 helper routines
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef GCK_DATA_ASN_H_
+#define GCK_DATA_ASN_H_
+
+#include <libtasn1.h>
+#include <gcrypt.h>
+#include <glib.h>
+
+#include "gck-data-types.h"
+
+ASN1_TYPE gck_data_asn1_get_pk_asn1type (void);
+
+ASN1_TYPE gck_data_asn1_get_pkix_asn1type (void);
+
+ASN1_TYPE gck_data_asn1_decode (const gchar *type, const guchar *data,
+ gsize n_data);
+
+guchar* gck_data_asn1_encode (ASN1_TYPE asn, const gchar* part,
+ gsize *len, GckDataAllocator alloc);
+
+guchar* gck_data_asn1_read_value (ASN1_TYPE asn, const gchar *part,
+ gsize *len, GckDataAllocator alloc);
+
+gboolean gck_data_asn1_write_value (ASN1_TYPE asn, const gchar *part,
+ const guchar* value, gsize len);
+
+GQuark gck_data_asn1_read_oid (ASN1_TYPE asn, const gchar *part);
+
+gboolean gck_data_asn1_write_oid (ASN1_TYPE asn, const gchar *part, GQuark val);
+
+gboolean gck_data_asn1_read_boolean (ASN1_TYPE asn, const gchar *part, gboolean *val);
+
+gboolean gck_data_asn1_read_uint (ASN1_TYPE asn, const gchar *part, guint *val);
+
+gboolean gck_data_asn1_read_time (ASN1_TYPE asn, const gchar *part, time_t *val);
+
+const guchar* gck_data_asn1_read_content (ASN1_TYPE asn, const guchar *data, gsize n_data,
+ const gchar *part, gsize *n_content);
+
+const guchar* gck_data_asn1_read_element (ASN1_TYPE asn, const guchar *data, gsize n_data,
+ const gchar *part, gsize *n_element);
+
+gboolean gck_data_asn1_write_uint (ASN1_TYPE asn, const gchar *part, guint val);
+
+gboolean gck_data_asn1_read_mpi (ASN1_TYPE asn, const gchar *part,
+ gcry_mpi_t *mpi);
+
+gboolean gck_data_asn1_read_secure_mpi (ASN1_TYPE asn, const gchar *part,
+ gcry_mpi_t *mpi);
+
+gboolean gck_data_asn1_write_mpi (ASN1_TYPE asn, const gchar *part,
+ gcry_mpi_t mpi);
+
+gint gck_data_asn1_element_length (const guchar *data, gsize n_data);
+
+const guchar* gck_data_asn1_element_content (const guchar *data, gsize n_data, gsize *n_content);
+
+time_t gck_data_asn1_parse_utc_time (const gchar* value);
+
+time_t gck_data_asn1_parse_general_time (const gchar* value);
+
+#endif /*GCK_DATA_ASN_H_*/
Added: trunk/pkcs11/gck/gck-data-der.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-der.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,1399 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-data-der.c - parsing and serializing of common crypto DER structures
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gck-crypto.h"
+#include "gck-data-asn1.h"
+#include "gck-data-der.h"
+#include "gck-data-types.h"
+
+#include "common/gkr-secure-memory.h"
+
+#include <glib.h>
+#include <gcrypt.h>
+#include <libtasn1.h>
+
+/* -----------------------------------------------------------------------------
+ * QUARKS
+ */
+
+#ifdef UNTESTED_CODE
+
+static GQuark OID_PKIX1_RSA;
+static GQuark OID_PKIX1_DSA;
+
+static GQuark OID_PBE_MD2_DES_CBC;
+static GQuark OID_PBE_MD5_DES_CBC;
+static GQuark OID_PBE_MD2_RC2_CBC;
+static GQuark OID_PBE_MD5_RC2_CBC;
+static GQuark OID_PBE_SHA1_DES_CBC;
+static GQuark OID_PBE_SHA1_RC2_CBC;
+static GQuark OID_PBES2;
+static GQuark OID_PBKDF2;
+
+static GQuark OID_DES_CBC;
+static GQuark OID_DES_RC2_CBC;
+static GQuark OID_DES_EDE3_CBC;
+static GQuark OID_DES_RC5_CBC;
+
+static GQuark OID_PKCS12_PBE_ARCFOUR_SHA1;
+static GQuark OID_PKCS12_PBE_RC4_40_SHA1;
+static GQuark OID_PKCS12_PBE_3DES_SHA1;
+static GQuark OID_PKCS12_PBE_2DES_SHA1;
+static GQuark OID_PKCS12_PBE_RC2_128_SHA1;
+static GQuark OID_PKCS12_PBE_RC2_40_SHA1;
+
+static void
+init_quarks (void)
+{
+ static gsize quarks_inited = 0;
+
+ if (g_once_init_enter (&quarks_inited)) {
+
+ #define QUARK(name, value) \
+ name = g_quark_from_static_string(value)
+
+ QUARK (OID_PKIX1_RSA, "1.2.840.113549.1.1.1");
+ QUARK (OID_PKIX1_DSA, "1.2.840.10040.4.1");
+
+ QUARK (OID_PBE_MD2_DES_CBC, "1.2.840.113549.1.5.1");
+ QUARK (OID_PBE_MD5_DES_CBC, "1.2.840.113549.1.5.3");
+ QUARK (OID_PBE_MD2_RC2_CBC, "1.2.840.113549.1.5.4");
+ QUARK (OID_PBE_MD5_RC2_CBC, "1.2.840.113549.1.5.6");
+ QUARK (OID_PBE_SHA1_DES_CBC, "1.2.840.113549.1.5.10");
+ QUARK (OID_PBE_SHA1_RC2_CBC, "1.2.840.113549.1.5.11");
+
+ QUARK (OID_PBES2, "1.2.840.113549.1.5.13");
+
+ QUARK (OID_PBKDF2, "1.2.840.113549.1.5.12");
+
+ QUARK (OID_DES_CBC, "1.3.14.3.2.7");
+ QUARK (OID_DES_RC2_CBC, "1.2.840.113549.3.2");
+ QUARK (OID_DES_EDE3_CBC, "1.2.840.113549.3.7");
+ QUARK (OID_DES_RC5_CBC, "1.2.840.113549.3.9");
+
+ QUARK (OID_PKCS12_PBE_ARCFOUR_SHA1, "1.2.840.113549.1.12.1.1");
+ QUARK (OID_PKCS12_PBE_RC4_40_SHA1, "1.2.840.113549.1.12.1.2");
+ QUARK (OID_PKCS12_PBE_3DES_SHA1, "1.2.840.113549.1.12.1.3");
+ QUARK (OID_PKCS12_PBE_2DES_SHA1, "1.2.840.113549.1.12.1.4");
+ QUARK (OID_PKCS12_PBE_RC2_128_SHA1, "1.2.840.113549.1.12.1.5");
+ QUARK (OID_PKCS12_PBE_RC2_40_SHA1, "1.2.840.113549.1.12.1.6");
+
+ #undef QUARK
+
+ g_once_init_leave (&quarks_inited, 1);
+ }
+}
+
+#endif UNTESTED_CODE
+
+/* -----------------------------------------------------------------------------
+ * KEY PARSING
+ */
+
+#define SEXP_PUBLIC_RSA \
+ "(public-key" \
+ " (rsa" \
+ " (n %m)" \
+ " (e %m)))"
+
+GckDataResult
+gck_data_der_read_public_key_rsa (const guchar *data, gsize n_data, gcry_sexp_t *s_key)
+{
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_mpi_t n, e;
+ int res;
+
+ n = e = NULL;
+
+ asn = gck_data_asn1_decode ("PK.RSAPublicKey", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ if (!gck_data_asn1_read_mpi (asn, "modulus", &n) ||
+ !gck_data_asn1_read_mpi (asn, "publicExponent", &e))
+ goto done;
+
+ res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_RSA, n, e);
+ if (res)
+ goto done;
+
+ g_assert (*s_key);
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (n);
+ gcry_mpi_release (e);
+
+ if (ret == GCK_DATA_FAILURE)
+ g_message ("invalid RSA public key");
+
+ return ret;
+}
+
+#define SEXP_PRIVATE_RSA \
+ "(private-key" \
+ " (rsa" \
+ " (n %m)" \
+ " (e %m)" \
+ " (d %m)" \
+ " (p %m)" \
+ " (q %m)" \
+ " (u %m)))"
+
+GckDataResult
+gck_data_der_read_private_key_rsa (const guchar *data, gsize n_data, gcry_sexp_t *s_key)
+{
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ gcry_mpi_t n, e, d, p, q, u;
+ gcry_mpi_t tmp;
+ guint version;
+ int res;
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+
+ n = e = d = p = q = u = NULL;
+
+ asn = gck_data_asn1_decode ("PK.RSAPrivateKey", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ if (!gck_data_asn1_read_uint (asn, "version", &version))
+ goto done;
+
+ /* We only support simple version */
+ if (version != 0) {
+ ret = GCK_DATA_UNRECOGNIZED;
+ g_message ("unsupported version of RSA key: %u", version);
+ goto done;
+ }
+
+ if (!gck_data_asn1_read_secure_mpi (asn, "modulus", &n) ||
+ !gck_data_asn1_read_secure_mpi (asn, "publicExponent", &e) ||
+ !gck_data_asn1_read_secure_mpi (asn, "privateExponent", &d) ||
+ !gck_data_asn1_read_secure_mpi (asn, "prime1", &p) ||
+ !gck_data_asn1_read_secure_mpi (asn, "prime2", &q) ||
+ !gck_data_asn1_read_secure_mpi (asn, "coefficient", &u))
+ goto done;
+
+ /* Fix up the incoming key so gcrypt likes it */
+ if (gcry_mpi_cmp (p, q) > 0) {
+ /* P shall be smaller then Q! Swap primes. iqmp becomes u. */
+ tmp = p;
+ p = q;
+ q = tmp;
+ } else {
+ /* U needs to be recomputed. */
+ gcry_mpi_invm (u, p, q);
+ }
+
+ res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_RSA, n, e, d, p, q, u);
+ if (res)
+ goto done;
+
+ g_assert (*s_key);
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (n);
+ gcry_mpi_release (e);
+ gcry_mpi_release (d);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (u);
+
+ if (ret == GCK_DATA_FAILURE)
+ g_message ("invalid RSA key");
+
+ return ret;
+}
+
+#define SEXP_PUBLIC_DSA \
+ "(public-key" \
+ " (dsa" \
+ " (p %m)" \
+ " (q %m)" \
+ " (g %m)" \
+ " (y %m)))"
+
+GckDataResult
+gck_data_der_read_public_key_dsa (const guchar *data, gsize n_data, gcry_sexp_t *s_key)
+{
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_mpi_t p, q, g, y;
+ int res;
+
+ p = q = g = y = NULL;
+
+ asn = gck_data_asn1_decode ("PK.DSAPublicKey", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ if (!gck_data_asn1_read_mpi (asn, "p", &p) ||
+ !gck_data_asn1_read_mpi (asn, "q", &q) ||
+ !gck_data_asn1_read_mpi (asn, "g", &g) ||
+ !gck_data_asn1_read_mpi (asn, "Y", &y))
+ goto done;
+
+ res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_DSA, p, q, g, y);
+ if (res)
+ goto done;
+
+ g_assert (*s_key);
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (g);
+ gcry_mpi_release (y);
+
+ if (ret == GCK_DATA_FAILURE)
+ g_message ("invalid public DSA key");
+
+ return ret;
+}
+
+#ifdef UNTESTED_CODE
+
+GckDataResult
+gck_data_der_read_public_key_dsa_parts (const guchar *keydata, gsize n_keydata,
+ const guchar *params, gsize n_params,
+ gcry_sexp_t *s_key)
+{
+ gcry_mpi_t p, q, g, y;
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ ASN1_TYPE asn_params = ASN1_TYPE_EMPTY;
+ ASN1_TYPE asn_key = ASN1_TYPE_EMPTY;
+ int res;
+
+ p = q = g = y = NULL;
+
+ asn_params = gck_data_asn1_decode ("PK.DSAParameters", params, n_params);
+ asn_key = gck_data_asn1_decode ("PK.DSAPublicPart", keydata, n_keydata);
+ if (!asn_params || !asn_key)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ if (!gck_data_asn1_read_mpi (asn_params, "p", &p) ||
+ !gck_data_asn1_read_mpi (asn_params, "q", &q) ||
+ !gck_data_asn1_read_mpi (asn_params, "g", &g))
+ goto done;
+
+ if (!gck_data_asn1_read_mpi (asn_key, "", &y))
+ goto done;
+
+ res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_DSA, p, q, g, y);
+ if (res)
+ goto done;
+
+ g_assert (*s_key);
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn_key)
+ asn1_delete_structure (&asn_key);
+ if (asn_params)
+ asn1_delete_structure (&asn_params);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (g);
+ gcry_mpi_release (y);
+
+ if (ret == GCK_DATA_FAILURE)
+ g_message ("invalid DSA key");
+
+ return ret;
+}
+
+#endif /* UNTESTED_CODE */
+
+#define SEXP_PRIVATE_DSA \
+ "(private-key" \
+ " (dsa" \
+ " (p %m)" \
+ " (q %m)" \
+ " (g %m)" \
+ " (y %m)" \
+ " (x %m)))"
+
+GckDataResult
+gck_data_der_read_private_key_dsa (const guchar *data, gsize n_data, gcry_sexp_t *s_key)
+{
+ gcry_mpi_t p, q, g, y, x;
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ int res;
+ ASN1_TYPE asn;
+
+ p = q = g = y = x = NULL;
+
+ asn = gck_data_asn1_decode ("PK.DSAPrivateKey", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ if (!gck_data_asn1_read_secure_mpi (asn, "p", &p) ||
+ !gck_data_asn1_read_secure_mpi (asn, "q", &q) ||
+ !gck_data_asn1_read_secure_mpi (asn, "g", &g) ||
+ !gck_data_asn1_read_secure_mpi (asn, "Y", &y) ||
+ !gck_data_asn1_read_secure_mpi (asn, "priv", &x))
+ goto done;
+
+ res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_DSA, p, q, g, y, x);
+ if (res)
+ goto done;
+
+ g_assert (*s_key);
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (g);
+ gcry_mpi_release (y);
+ gcry_mpi_release (x);
+
+ if (ret == GCK_DATA_FAILURE)
+ g_message ("invalid DSA key");
+
+ return ret;
+}
+
+GckDataResult
+gck_data_der_read_private_key_dsa_parts (const guchar *keydata, gsize n_keydata,
+ const guchar *params, gsize n_params,
+ gcry_sexp_t *s_key)
+{
+ gcry_mpi_t p, q, g, y, x;
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ int res;
+ ASN1_TYPE asn_params = ASN1_TYPE_EMPTY;
+ ASN1_TYPE asn_key = ASN1_TYPE_EMPTY;
+
+ p = q = g = y = x = NULL;
+
+ asn_params = gck_data_asn1_decode ("PK.DSAParameters", params, n_params);
+ asn_key = gck_data_asn1_decode ("PK.DSAPrivatePart", keydata, n_keydata);
+ if (!asn_params || !asn_key)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ if (!gck_data_asn1_read_secure_mpi (asn_params, "p", &p) ||
+ !gck_data_asn1_read_secure_mpi (asn_params, "q", &q) ||
+ !gck_data_asn1_read_secure_mpi (asn_params, "g", &g))
+ goto done;
+
+ if (!gck_data_asn1_read_secure_mpi (asn_key, "", &x))
+ goto done;
+
+ /* Now we calculate y */
+ y = gcry_mpi_snew (1024);
+ gcry_mpi_powm (y, g, x, p);
+
+ res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_DSA, p, q, g, y, x);
+ if (res)
+ goto done;
+
+ g_assert (*s_key);
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn_key)
+ asn1_delete_structure (&asn_key);
+ if (asn_params)
+ asn1_delete_structure (&asn_params);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (g);
+ gcry_mpi_release (y);
+ gcry_mpi_release (x);
+
+ if (ret == GCK_DATA_FAILURE)
+ g_message ("invalid DSA key");
+
+ return ret;
+}
+
+GckDataResult
+gck_data_der_read_public_key (const guchar *data, gsize n_data, gcry_sexp_t *s_key)
+{
+ GckDataResult res;
+
+ res = gck_data_der_read_public_key_rsa (data, n_data, s_key);
+ if (res == GCK_DATA_UNRECOGNIZED)
+ res = gck_data_der_read_public_key_dsa (data, n_data, s_key);
+
+ return res;
+}
+
+#ifdef UNTESTED_CODE
+
+GckDataResult
+gck_data_der_read_public_key_info (const guchar* data, gsize n_data, gcry_sexp_t* s_key)
+{
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ GQuark oid;
+ ASN1_TYPE asn;
+ gsize n_key, n_params;
+ const guchar *params;
+ guchar *key = NULL;
+
+ init_quarks ();
+
+ asn = gck_data_asn1_decode ("PKIX1.SubjectPublicKeyInfo", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ /* Figure out the algorithm */
+ oid = gck_data_asn1_read_oid (asn, "algorithm.algorithm");
+ if (!oid)
+ goto done;
+
+ /* A bit string so we cannot process in place */
+ key = gck_data_asn1_read_value (asn, "subjectPublicKey", &n_key, NULL);
+ if (!key)
+ goto done;
+ n_key /= 8;
+
+ /* An RSA key is simple */
+ if (oid == OID_PKIX1_RSA) {
+ ret = gck_data_der_read_public_key_rsa (key, n_key, s_key);
+
+ /* A DSA key paramaters are stored separately */
+ } else if (oid == OID_PKIX1_DSA) {
+ params = gck_data_asn1_read_element (asn, data, n_data, "algorithm.parameters", &n_params);
+ if (!params)
+ goto done;
+ ret = gck_data_der_read_public_key_dsa_parts (key, n_key, params, n_params, s_key);
+
+ } else {
+ g_message ("unsupported key algorithm in certificate: %s", g_quark_to_string (oid));
+ goto done;
+ }
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+
+ g_free (key);
+
+ if (ret == GCK_DATA_FAILURE)
+ g_message ("invalid subject public-key info");
+
+ return ret;
+}
+
+#endif /* UNTESTED_CODE */
+
+GckDataResult
+gck_data_der_read_private_key (const guchar *data, gsize n_data, gcry_sexp_t *s_key)
+{
+ GckDataResult res;
+
+ res = gck_data_der_read_private_key_rsa (data, n_data, s_key);
+ if (res == GCK_DATA_UNRECOGNIZED)
+ res = gck_data_der_read_private_key_dsa (data, n_data, s_key);
+
+ return res;
+}
+
+guchar*
+gck_data_der_write_public_key_rsa (gcry_sexp_t s_key, gsize *len)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_mpi_t n, e;
+ guchar *result = NULL;
+ int res;
+
+ n = e = NULL;
+
+ res = asn1_create_element (gck_data_asn1_get_pk_asn1type (),
+ "PK.RSAPublicKey", &asn);
+ g_return_val_if_fail (res == ASN1_SUCCESS, NULL);
+
+ if (!gck_crypto_sexp_extract_mpi (s_key, &n, "rsa", "n", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &e, "rsa", "e", NULL))
+ goto done;
+
+ if (!gck_data_asn1_write_mpi (asn, "modulus", n) ||
+ !gck_data_asn1_write_mpi (asn, "publicExponent", e))
+ goto done;
+
+ result = gck_data_asn1_encode (asn, "", len, NULL);
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (n);
+ gcry_mpi_release (e);
+
+ return result;
+}
+
+guchar*
+gck_data_der_write_private_key_rsa (gcry_sexp_t s_key, gsize *n_key)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_mpi_t n, e, d, p, q, u, e1, e2, tmp;
+ guchar *result = NULL;
+ int res;
+
+ n = e = d = p = q = u = e1 = e2 = tmp = NULL;
+
+ res = asn1_create_element (gck_data_asn1_get_pk_asn1type (),
+ "PK.RSAPrivateKey", &asn);
+ g_return_val_if_fail (res == ASN1_SUCCESS, NULL);
+
+ if (!gck_crypto_sexp_extract_mpi (s_key, &n, "rsa", "n", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &e, "rsa", "e", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &d, "rsa", "d", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &p, "rsa", "p", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &q, "rsa", "q", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &u, "rsa", "u", NULL))
+ goto done;
+
+ if (!gck_data_asn1_write_mpi (asn, "modulus", n) ||
+ !gck_data_asn1_write_mpi (asn, "publicExponent", e) ||
+ !gck_data_asn1_write_mpi (asn, "privateExponent", d) ||
+ !gck_data_asn1_write_mpi (asn, "prime1", p) ||
+ !gck_data_asn1_write_mpi (asn, "prime2", q) ||
+ !gck_data_asn1_write_mpi (asn, "coefficient", u))
+ goto done;
+
+ /* Calculate e1 and e2 */
+ tmp = gcry_mpi_snew (1024);
+ gcry_mpi_sub_ui (tmp, p, 1);
+ e1 = gcry_mpi_snew (1024);
+ gcry_mpi_mod (e1, d, tmp);
+ gcry_mpi_sub_ui (tmp, q, 1);
+ e2 = gcry_mpi_snew (1024);
+ gcry_mpi_mod (e2, d, tmp);
+
+ /* Write out calculated */
+ if (!gck_data_asn1_write_mpi (asn, "exponent1", e1) ||
+ !gck_data_asn1_write_mpi (asn, "exponent2", e2))
+ goto done;
+
+ /* Write out the version */
+ if (!gck_data_asn1_write_uint (asn, "version", 0))
+ goto done;
+
+ result = gck_data_asn1_encode (asn, "", n_key, NULL);
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (n);
+ gcry_mpi_release (e);
+ gcry_mpi_release (d);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (u);
+
+ gcry_mpi_release (tmp);
+ gcry_mpi_release (e1);
+ gcry_mpi_release (e2);
+
+ return result;
+}
+
+guchar*
+gck_data_der_write_public_key_dsa (gcry_sexp_t s_key, gsize *len)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_mpi_t p, q, g, y;
+ guchar *result = NULL;
+ int res;
+
+ p = q = g = y = NULL;
+
+ res = asn1_create_element (gck_data_asn1_get_pk_asn1type (),
+ "PK.DSAPublicKey", &asn);
+ g_return_val_if_fail (res == ASN1_SUCCESS, NULL);
+
+ if (!gck_crypto_sexp_extract_mpi (s_key, &p, "dsa", "p", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &q, "dsa", "q", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &g, "dsa", "g", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &y, "dsa", "y", NULL))
+ goto done;
+
+ if (!gck_data_asn1_write_mpi (asn, "p", p) ||
+ !gck_data_asn1_write_mpi (asn, "q", q) ||
+ !gck_data_asn1_write_mpi (asn, "g", g) ||
+ !gck_data_asn1_write_mpi (asn, "Y", y))
+ goto done;
+
+ if (!gck_data_asn1_write_uint (asn, "version", 0))
+ goto done;
+
+ result = gck_data_asn1_encode (asn, "", len, NULL);
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (g);
+ gcry_mpi_release (y);
+
+ return result;
+}
+
+guchar*
+gck_data_der_write_private_key_dsa_part (gcry_sexp_t skey, gsize *n_key)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_mpi_t x;
+ guchar *result = NULL;
+ int res;
+
+ x = NULL;
+
+ res = asn1_create_element (gck_data_asn1_get_pk_asn1type (),
+ "PK.DSAPrivatePart", &asn);
+ g_return_val_if_fail (res == ASN1_SUCCESS, NULL);
+
+ if (!gck_crypto_sexp_extract_mpi (skey, &x, "dsa", "x", NULL))
+ goto done;
+
+ if (!gck_data_asn1_write_mpi (asn, "", x))
+ goto done;
+
+ result = gck_data_asn1_encode (asn, "", n_key, NULL);
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (x);
+
+ return result;
+}
+
+guchar*
+gck_data_der_write_private_key_dsa_params (gcry_sexp_t skey, gsize *n_params)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_mpi_t p, q, g;
+ guchar *result = NULL;
+ int res;
+
+ p = q = g = NULL;
+
+ res = asn1_create_element (gck_data_asn1_get_pk_asn1type (),
+ "PK.DSAParameters", &asn);
+ g_return_val_if_fail (res == ASN1_SUCCESS, NULL);
+
+ if (!gck_crypto_sexp_extract_mpi (skey, &p, "dsa", "p", NULL) ||
+ !gck_crypto_sexp_extract_mpi (skey, &q, "dsa", "q", NULL) ||
+ !gck_crypto_sexp_extract_mpi (skey, &g, "dsa", "g", NULL))
+ goto done;
+
+ if (!gck_data_asn1_write_mpi (asn, "p", p) ||
+ !gck_data_asn1_write_mpi (asn, "q", q) ||
+ !gck_data_asn1_write_mpi (asn, "g", g))
+ goto done;
+
+ result = gck_data_asn1_encode (asn, "", n_params, NULL);
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (g);
+
+ return result;
+}
+
+guchar*
+gck_data_der_write_private_key_dsa (gcry_sexp_t s_key, gsize *len)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_mpi_t p, q, g, y, x;
+ guchar *result = NULL;
+ int res;
+
+ p = q = g = y = x = NULL;
+
+ res = asn1_create_element (gck_data_asn1_get_pk_asn1type (),
+ "PK.DSAPrivateKey", &asn);
+ g_return_val_if_fail (res == ASN1_SUCCESS, NULL);
+
+ if (!gck_crypto_sexp_extract_mpi (s_key, &p, "dsa", "p", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &q, "dsa", "q", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &g, "dsa", "g", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &y, "dsa", "y", NULL) ||
+ !gck_crypto_sexp_extract_mpi (s_key, &x, "dsa", "x", NULL))
+ goto done;
+
+ if (!gck_data_asn1_write_mpi (asn, "p", p) ||
+ !gck_data_asn1_write_mpi (asn, "q", q) ||
+ !gck_data_asn1_write_mpi (asn, "g", g) ||
+ !gck_data_asn1_write_mpi (asn, "Y", y) ||
+ !gck_data_asn1_write_mpi (asn, "priv", x))
+ goto done;
+
+ if (!gck_data_asn1_write_uint (asn, "version", 0))
+ goto done;
+
+ result = gck_data_asn1_encode (asn, "", len, NULL);
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (g);
+ gcry_mpi_release (y);
+ gcry_mpi_release (x);
+
+ return result;
+}
+
+guchar*
+gck_data_der_write_public_key (gcry_sexp_t s_key, gsize *len)
+{
+ gboolean is_priv;
+ int algorithm;
+
+ g_return_val_if_fail (s_key != NULL, NULL);
+
+ if (!gck_crypto_sexp_parse_key (s_key, &algorithm, &is_priv, NULL))
+ g_return_val_if_reached (NULL);
+
+ g_return_val_if_fail (!is_priv, NULL);
+
+ switch (algorithm) {
+ case GCRY_PK_RSA:
+ return gck_data_der_write_public_key_rsa (s_key, len);
+ case GCRY_PK_DSA:
+ return gck_data_der_write_public_key_dsa (s_key, len);
+ default:
+ g_return_val_if_reached (NULL);
+ }
+}
+
+guchar*
+gck_data_der_write_private_key (gcry_sexp_t s_key, gsize *len)
+{
+ gboolean is_priv;
+ int algorithm;
+
+ g_return_val_if_fail (s_key != NULL, NULL);
+
+ if (!gck_crypto_sexp_parse_key (s_key, &algorithm, &is_priv, NULL))
+ g_return_val_if_reached (NULL);
+
+ g_return_val_if_fail (is_priv, NULL);
+
+ switch (algorithm) {
+ case GCRY_PK_RSA:
+ return gck_data_der_write_private_key_rsa (s_key, len);
+ case GCRY_PK_DSA:
+ return gck_data_der_write_private_key_dsa (s_key, len);
+ default:
+ g_return_val_if_reached (NULL);
+ }
+}
+
+#ifdef UNTESTED_CODE
+
+/* -----------------------------------------------------------------------------
+ * CERTIFICATES
+ */
+
+GckDataResult
+gck_data_der_read_certificate (const guchar *data, gsize n_data, ASN1_TYPE *asn1)
+{
+ *asn1 = gck_data_asn1_decode ("PKIX1.Certificate", data, n_data);
+ if (!*asn1)
+ return GCK_DATA_UNRECOGNIZED;
+
+ return GCK_DATA_SUCCESS;
+}
+
+GckDataResult
+gck_data_der_read_basic_constraints (const guchar *data, gsize n_data,
+ gboolean *is_ca, guint *path_len)
+{
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ ASN1_TYPE asn;
+
+ asn = gck_data_asn1_decode ("PKIX1.BasicConstraints", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ if (path_len) {
+ if (!gck_data_asn1_read_uint (asn, "pathLenConstraint", path_len))
+ goto done;
+ }
+
+ if (is_ca) {
+ if (!gck_data_asn1_read_boolean (asn, "cA", is_ca))
+ *is_ca = FALSE;
+ }
+
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+
+ if (ret == GCK_DATA_FAILURE)
+ g_message ("invalid basic constraints");
+
+ return ret;
+}
+
+GckDataResult
+gck_data_der_read_key_usage (const guchar *data, gsize n_data, guint *key_usage)
+{
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ ASN1_TYPE asn;
+ guchar buf[4];
+ int res, len;
+
+ asn = gck_data_asn1_decode ("PKIX1.KeyUsage", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ memset (buf, 0, sizeof (buf));
+ len = sizeof (buf);
+ res = asn1_read_value (asn, "", buf, &len);
+ if (res != ASN1_SUCCESS)
+ goto done;
+
+ *key_usage = buf[0] | (buf[1] << 8);
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ return ret;
+}
+
+GckDataResult
+gck_data_der_read_enhanced_usage (const guchar *data, gsize n_data, GQuark **usage_oids)
+{
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+ ASN1_TYPE asn;
+ gchar *part;
+ GArray *array;
+ GQuark oid;
+ int i;
+
+ asn = gck_data_asn1_decode ("PKIX1.ExtKeyUsageSyntax", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ array = g_array_new (TRUE, TRUE, sizeof (GQuark));
+ for (i = 0; TRUE; ++i) {
+ part = g_strdup_printf ("?%d", i + 1);
+ oid = gck_data_asn1_read_oid (asn, part);
+ g_free (part);
+
+ if (!oid)
+ break;
+
+ g_array_append_val (array, oid);
+ }
+
+ *usage_oids = (GQuark*)g_array_free (array, FALSE);
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (asn)
+ asn1_delete_structure (&asn);
+ return ret;
+}
+
+guchar*
+gck_data_der_write_certificate (ASN1_TYPE asn1, gsize *n_data)
+{
+ g_return_val_if_fail (asn1, NULL);
+ g_return_val_if_fail (n_data, NULL);
+
+ return gck_data_asn1_encode (asn1, "", n_data, NULL);
+}
+
+/* -----------------------------------------------------------------------------
+ * CIPHER/KEY DESCRIPTIONS
+ */
+
+GckDataResult
+gck_data_der_read_cipher (GQuark oid_scheme, const gchar *password,
+ const guchar *data, gsize n_data, gcry_cipher_hd_t *cih)
+{
+ GckDataResult ret = GCK_DATA_UNRECOGNIZED;
+
+ g_return_val_if_fail (oid_scheme != 0, GCK_DATA_FAILURE);
+ g_return_val_if_fail (cih != NULL, GCK_DATA_FAILURE);
+ g_return_val_if_fail (data != NULL && n_data != 0, GCK_DATA_FAILURE);
+
+ init_quarks ();
+
+ /* PKCS#5 PBE */
+ if (oid_scheme == OID_PBE_MD2_DES_CBC)
+ ret = gck_data_der_read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
+ GCRY_MD_MD2, password, data, n_data, cih);
+
+ else if (oid_scheme == OID_PBE_MD2_RC2_CBC)
+ /* RC2-64 has no implementation in libgcrypt */
+ ret = GCK_DATA_UNRECOGNIZED;
+ else if (oid_scheme == OID_PBE_MD5_DES_CBC)
+ ret = gck_data_der_read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
+ GCRY_MD_MD5, password, data, n_data, cih);
+ else if (oid_scheme == OID_PBE_MD5_RC2_CBC)
+ /* RC2-64 has no implementation in libgcrypt */
+ ret = GCK_DATA_UNRECOGNIZED;
+ else if (oid_scheme == OID_PBE_SHA1_DES_CBC)
+ ret = gck_data_der_read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
+ GCRY_MD_SHA1, password, data, n_data, cih);
+ else if (oid_scheme == OID_PBE_SHA1_RC2_CBC)
+ /* RC2-64 has no implementation in libgcrypt */
+ ret = GCK_DATA_UNRECOGNIZED;
+
+
+ /* PKCS#5 PBES2 */
+ else if (oid_scheme == OID_PBES2)
+ ret = gck_data_der_read_cipher_pkcs5_pbes2 (password, data, n_data, cih);
+
+
+ /* PKCS#12 PBE */
+ else if (oid_scheme == OID_PKCS12_PBE_ARCFOUR_SHA1)
+ ret = gck_data_der_read_cipher_pkcs12_pbe (GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM,
+ password, data, n_data, cih);
+ else if (oid_scheme == OID_PKCS12_PBE_RC4_40_SHA1)
+ /* RC4-40 has no implementation in libgcrypt */;
+
+ else if (oid_scheme == OID_PKCS12_PBE_3DES_SHA1)
+ ret = gck_data_der_read_cipher_pkcs12_pbe (GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC,
+ password, data, n_data, cih);
+ else if (oid_scheme == OID_PKCS12_PBE_2DES_SHA1)
+ /* 2DES has no implementation in libgcrypt */;
+
+ else if (oid_scheme == OID_PKCS12_PBE_RC2_128_SHA1)
+ ret = gck_data_der_read_cipher_pkcs12_pbe (GCRY_CIPHER_RFC2268_128, GCRY_CIPHER_MODE_CBC,
+ password, data, n_data, cih);
+
+ else if (oid_scheme == OID_PKCS12_PBE_RC2_40_SHA1)
+ ret = gck_data_der_read_cipher_pkcs12_pbe (GCRY_CIPHER_RFC2268_40, GCRY_CIPHER_MODE_CBC,
+ password, data, n_data, cih);
+
+ if (ret == GCK_DATA_UNRECOGNIZED)
+ g_message ("unsupported or unrecognized cipher oid: %s", g_quark_to_string (oid_scheme));
+ return ret;
+}
+
+GckDataResult
+gck_data_der_read_cipher_pkcs5_pbe (int cipher_algo, int cipher_mode,
+ int hash_algo, const gchar *password, const guchar *data,
+ gsize n_data, gcry_cipher_hd_t *cih)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_error_t gcry;
+ GckDataResult ret;
+ const guchar *salt;
+ gsize n_salt;
+ gsize n_block, n_key;
+ guint iterations;
+ guchar *key = NULL;
+ guchar *iv = NULL;
+
+ g_return_val_if_fail (cipher_algo != 0 && cipher_mode != 0, GCK_DATA_FAILURE);
+ g_return_val_if_fail (cih != NULL, GCK_DATA_FAILURE);
+ g_return_val_if_fail (data != NULL && n_data != 0, GCK_DATA_FAILURE);
+
+ *cih = NULL;
+ ret = GCK_DATA_UNRECOGNIZED;
+
+ /* Check if we can use this algorithm */
+ if (gcry_cipher_algo_info (cipher_algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0 ||
+ gcry_md_test_algo (hash_algo) != 0)
+ goto done;
+
+ asn = gck_data_asn1_decode ("PKIX1.pkcs-5-PBE-params", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ salt = gck_data_asn1_read_content (asn, data, n_data, "salt", &n_salt);
+ if (!salt)
+ goto done;
+ if (!gck_data_asn1_read_uint (asn, "iterationCount", &iterations))
+ iterations = 1;
+
+ n_key = gcry_cipher_get_algo_keylen (cipher_algo);
+ g_return_val_if_fail (n_key > 0, GCK_DATA_FAILURE);
+ n_block = gcry_cipher_get_algo_blklen (cipher_algo);
+
+ if (!gck_crypto_symkey_generate_pbe (cipher_algo, hash_algo, password, salt,
+ n_salt, iterations, &key, n_block > 1 ? &iv : NULL))
+ goto done;
+
+ gcry = gcry_cipher_open (cih, cipher_algo, cipher_mode, 0);
+ if (gcry != 0) {
+ g_warning ("couldn't create cipher: %s", gcry_strerror (gcry));
+ goto done;
+ }
+
+ if (iv)
+ gcry_cipher_setiv (*cih, iv, n_block);
+ gcry_cipher_setkey (*cih, key, n_key);
+
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ gkr_secure_free (iv);
+ gkr_secure_free (key);
+
+ if (asn)
+ asn1_delete_structure (&asn);
+
+ return ret;
+}
+
+static gboolean
+setup_pkcs5_rc2_params (const guchar *data, guchar n_data, gcry_cipher_hd_t cih)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_error_t gcry;
+ const guchar *iv;
+ gsize n_iv;
+ guint version;
+
+ g_assert (data);
+
+ asn = gck_data_asn1_decode ("PKIX1.pkcs-5-rc2-CBC-params", data, n_data);
+ if (!asn)
+ return GCK_DATA_UNRECOGNIZED;
+
+ if (!gck_data_asn1_read_uint (asn, "rc2ParameterVersion", &version))
+ return GCK_DATA_FAILURE;
+
+ iv = gck_data_asn1_read_content (asn, data, n_data, "iv", &n_iv);
+ asn1_delete_structure (&asn);
+
+ if (!iv)
+ return GCK_DATA_FAILURE;
+
+ gcry = gcry_cipher_setiv (cih, iv, n_iv);
+
+ if (gcry != 0) {
+ g_message ("couldn't set %lu byte iv on cipher", (gulong)n_iv);
+ return GCK_DATA_FAILURE;
+ }
+
+ return GCK_DATA_SUCCESS;
+}
+
+static gboolean
+setup_pkcs5_des_params (const guchar *data, guchar n_data, gcry_cipher_hd_t cih)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_error_t gcry;
+ const guchar *iv;
+ gsize n_iv;
+
+ g_assert (data);
+
+ asn = gck_data_asn1_decode ("PKIX1.pkcs-5-des-EDE3-CBC-params", data, n_data);
+ if (!asn)
+ asn = gck_data_asn1_decode ("PKIX1.pkcs-5-des-CBC-params", data, n_data);
+ if (!asn)
+ return GCK_DATA_UNRECOGNIZED;
+
+ iv = gck_data_asn1_read_content (asn, data, n_data, "", &n_iv);
+ asn1_delete_structure (&asn);
+
+ if (!iv)
+ return GCK_DATA_FAILURE;
+
+ gcry = gcry_cipher_setiv (cih, iv, n_iv);
+
+ if (gcry != 0) {
+ g_message ("couldn't set %lu byte iv on cipher", (gulong)n_iv);
+ return GCK_DATA_FAILURE;
+ }
+
+ return GCK_DATA_SUCCESS;
+}
+
+static GckDataResult
+setup_pkcs5_pbkdf2_params (const gchar *password, const guchar *data,
+ gsize n_data, int cipher_algo, gcry_cipher_hd_t cih)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GckDataResult ret;
+ gcry_error_t gcry;
+ guchar *key = NULL;
+ const guchar *salt;
+ gsize n_salt, n_key;
+ guint iterations;
+
+ g_assert (cipher_algo);
+ g_assert (data);
+
+ ret = GCK_DATA_UNRECOGNIZED;
+
+ asn = gck_data_asn1_decode ("PKIX1.pkcs-5-PBKDF2-params", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ if (!gck_data_asn1_read_uint (asn, "iterationCount", &iterations))
+ iterations = 1;
+ salt = gck_data_asn1_read_content (asn, data, n_data, "salt.specified", &n_salt);
+ if (!salt)
+ goto done;
+
+ if (!gck_crypto_symkey_generate_pbkdf2 (cipher_algo, GCRY_MD_SHA1, password,
+ salt, n_salt, iterations, &key, NULL))
+ goto done;
+
+ n_key = gcry_cipher_get_algo_keylen (cipher_algo);
+ g_return_val_if_fail (n_key > 0, GCK_DATA_FAILURE);
+
+ gcry = gcry_cipher_setkey (cih, key, n_key);
+ if (gcry != 0) {
+ g_message ("couldn't set %lu byte key on cipher", (gulong)n_key);
+ goto done;
+ }
+
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ gkr_secure_free (key);
+ if (asn)
+ asn1_delete_structure (&asn);
+ return ret;
+}
+
+GckDataResult
+gck_data_der_read_cipher_pkcs5_pbes2 (const gchar *password, const guchar *data,
+ gsize n_data, gcry_cipher_hd_t *cih)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GckDataResult r, ret;
+ GQuark key_deriv_algo, enc_oid;
+ gcry_error_t gcry;
+ int algo, mode;
+ int beg, end, res;
+
+ g_return_val_if_fail (cih != NULL, GCK_DATA_FAILURE);
+ g_return_val_if_fail (data != NULL && n_data != 0, GCK_DATA_FAILURE);
+
+ init_quarks ();
+
+ *cih = NULL;
+ ret = GCK_DATA_UNRECOGNIZED;
+
+ asn = gck_data_asn1_decode ("PKIX1.pkcs-5-PBES2-params", data, n_data);
+ if (!asn)
+ goto done;
+
+ res = GCK_DATA_FAILURE;
+ algo = mode = 0;
+
+ /* Read in all the encryption type */
+ enc_oid = gck_data_asn1_read_oid (asn, "encryptionScheme.algorithm");
+ if (!enc_oid)
+ goto done;
+ if (enc_oid == OID_DES_EDE3_CBC)
+ algo = GCRY_CIPHER_3DES;
+ else if (enc_oid == OID_DES_CBC)
+ algo = GCRY_CIPHER_DES;
+ else if (enc_oid == OID_DES_RC2_CBC)
+ algo = GCRY_CIPHER_RFC2268_128;
+ else if (enc_oid == OID_DES_RC5_CBC)
+ /* RC5 doesn't exist in libgcrypt */;
+
+ /* Unsupported? */
+ if (algo == 0 || gcry_cipher_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0) {
+ ret = GCK_DATA_UNRECOGNIZED;
+ goto done;
+ }
+
+ /* Instantiate our cipher */
+ gcry = gcry_cipher_open (cih, algo, GCRY_CIPHER_MODE_CBC, 0);
+ if (gcry != 0) {
+ g_warning ("couldn't create cipher: %s", gcry_cipher_algo_name (algo));
+ goto done;
+ }
+
+ /* Read out the parameters */
+ if (asn1_der_decoding_startEnd (asn, data, n_data, "encryptionScheme.parameters",
+ &beg, &end) != ASN1_SUCCESS)
+ goto done;
+
+ switch (algo) {
+ case GCRY_CIPHER_3DES:
+ case GCRY_CIPHER_DES:
+ r = setup_pkcs5_des_params (data + beg, end - beg + 1, *cih);
+ break;
+ case GCRY_CIPHER_RFC2268_128:
+ r = setup_pkcs5_rc2_params (data + beg, end - beg + 1, *cih);
+ break;
+ default:
+ /* Should have been caught on the oid check above */
+ g_assert_not_reached ();
+ r = GCK_DATA_UNRECOGNIZED;
+ break;
+ };
+
+ if (r != GCK_DATA_SUCCESS) {
+ ret = r;
+ goto done;
+ }
+
+ /* Read out the key creation paramaters */
+ key_deriv_algo = gck_data_asn1_read_oid (asn, "keyDerivationFunc.algorithm");
+ if (!key_deriv_algo)
+ goto done;
+ if (key_deriv_algo != OID_PBKDF2) {
+ g_message ("unsupported key derivation algorithm: %s", g_quark_to_string (key_deriv_algo));
+ ret = GCK_DATA_UNRECOGNIZED;
+ goto done;
+ }
+
+ if (asn1_der_decoding_startEnd (asn, data, n_data, "keyDerivationFunc.parameters",
+ &beg, &end) != ASN1_SUCCESS)
+ goto done;
+
+ ret = setup_pkcs5_pbkdf2_params (password, data + beg, end - beg + 1, algo, *cih);
+
+done:
+ if (ret != GCK_DATA_SUCCESS && *cih) {
+ gcry_cipher_close (*cih);
+ *cih = NULL;
+ }
+
+ if (asn)
+ asn1_delete_structure (&asn);
+
+ return ret;
+}
+
+GckDataResult
+gck_data_der_read_cipher_pkcs12_pbe (int cipher_algo, int cipher_mode, const gchar *password,
+ const guchar *data, gsize n_data, gcry_cipher_hd_t *cih)
+{
+ ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ gcry_error_t gcry;
+ GckDataResult ret;
+ const guchar *salt;
+ gsize n_salt;
+ gsize n_block, n_key;
+ guint iterations;
+ guchar *key = NULL;
+ guchar *iv = NULL;
+
+ g_return_val_if_fail (cipher_algo != 0 && cipher_mode != 0, GCK_DATA_FAILURE);
+ g_return_val_if_fail (cih != NULL, GCK_DATA_FAILURE);
+ g_return_val_if_fail (data != NULL && n_data != 0, GCK_DATA_FAILURE);
+
+ *cih = NULL;
+ ret = GCK_DATA_UNRECOGNIZED;
+
+ /* Check if we can use this algorithm */
+ if (gcry_cipher_algo_info (cipher_algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0)
+ goto done;
+
+ asn = gck_data_asn1_decode ("PKIX1.pkcs-12-PbeParams", data, n_data);
+ if (!asn)
+ goto done;
+
+ ret = GCK_DATA_FAILURE;
+
+ salt = gck_data_asn1_read_content (asn, data, n_data, "salt", &n_salt);
+ if (!salt)
+ goto done;
+ if (!gck_data_asn1_read_uint (asn, "iterations", &iterations))
+ goto done;
+
+ n_block = gcry_cipher_get_algo_blklen (cipher_algo);
+ n_key = gcry_cipher_get_algo_keylen (cipher_algo);
+
+ /* Generate IV and key using salt read above */
+ if (!gck_crypto_symkey_generate_pkcs12 (cipher_algo, GCRY_MD_SHA1, password,
+ salt, n_salt, iterations, &key,
+ n_block > 1 ? &iv : NULL))
+ goto done;
+
+ gcry = gcry_cipher_open (cih, cipher_algo, cipher_mode, 0);
+ if (gcry != 0) {
+ g_warning ("couldn't create encryption cipher: %s", gcry_strerror (gcry));
+ goto done;
+ }
+
+ if (iv)
+ gcry_cipher_setiv (*cih, iv, n_block);
+ gcry_cipher_setkey (*cih, key, n_key);
+
+ ret = GCK_DATA_SUCCESS;
+
+done:
+ if (ret != GCK_DATA_SUCCESS && *cih) {
+ gcry_cipher_close (*cih);
+ *cih = NULL;
+ }
+
+ gkr_secure_free (iv);
+ gkr_secure_free (key);
+
+ if (asn)
+ asn1_delete_structure (&asn);
+
+ return ret;
+}
+
+#endif /* UNTESTED_CODE */
Added: trunk/pkcs11/gck/gck-data-der.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-der.h Mon Dec 22 20:21:06 2008
@@ -0,0 +1,126 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-data-der.h - parsing and serializing of common crypto DER structures
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef GKRPKIXDER_H_
+#define GKRPKIXDER_H_
+
+#include <glib.h>
+#include <gcrypt.h>
+#include <libtasn1.h>
+
+#include "gck-data-types.h"
+
+/* -----------------------------------------------------------------------------
+ * PRIVATE KEYS
+ */
+
+GckDataResult gck_data_der_read_private_key_rsa (const guchar *data, gsize n_data,
+ gcry_sexp_t *s_key);
+
+GckDataResult gck_data_der_read_private_key_dsa (const guchar *data, gsize n_data,
+ gcry_sexp_t *s_key);
+
+GckDataResult gck_data_der_read_private_key_dsa_parts (const guchar *keydata, gsize n_keydata,
+ const guchar *params, gsize n_params,
+ gcry_sexp_t *s_key);
+
+GckDataResult gck_data_der_read_private_key (const guchar *data, gsize n_data,
+ gcry_sexp_t *s_key);
+
+guchar* gck_data_der_write_private_key_rsa (gcry_sexp_t s_key, gsize *n_data);
+
+guchar* gck_data_der_write_private_key_dsa (gcry_sexp_t s_key, gsize *len);
+
+guchar* gck_data_der_write_private_key_dsa_part (gcry_sexp_t skey, gsize *n_key);
+
+guchar* gck_data_der_write_private_key_dsa_params (gcry_sexp_t skey, gsize *n_params);
+
+guchar* gck_data_der_write_private_key (gcry_sexp_t s_key, gsize *n_data);
+
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC KEYS
+ */
+
+GckDataResult gck_data_der_read_public_key_rsa (const guchar *data, gsize n_data,
+ gcry_sexp_t *s_key);
+
+GckDataResult gck_data_der_read_public_key_dsa (const guchar *data, gsize n_data,
+ gcry_sexp_t *s_key);
+
+GckDataResult gck_data_der_read_public_key_dsa_parts (const guchar *keydata, gsize n_keydata,
+ const guchar *params, gsize n_params,
+ gcry_sexp_t *s_key);
+
+GckDataResult gck_data_der_read_public_key (const guchar *data, gsize n_data,
+ gcry_sexp_t *s_key);
+
+GckDataResult gck_data_der_read_public_key_info (const guchar *data, gsize n_data,
+ gcry_sexp_t *s_key);
+
+guchar* gck_data_der_write_public_key_rsa (gcry_sexp_t s_key, gsize *len);
+
+guchar* gck_data_der_write_public_key_dsa (gcry_sexp_t s_key, gsize *len);
+
+guchar* gck_data_der_write_public_key (gcry_sexp_t s_key, gsize *len);
+
+
+/* -----------------------------------------------------------------------------
+ * CERTIFICATES
+ */
+
+GckDataResult gck_data_der_read_certificate (const guchar *data, gsize n_data,
+ ASN1_TYPE *asn1);
+
+GckDataResult gck_data_der_read_basic_constraints (const guchar *data, gsize n_data,
+ gboolean *is_ca, guint *path_len);
+
+GckDataResult gck_data_der_read_key_usage (const guchar *data, gsize n_data,
+ guint *key_usage);
+
+GckDataResult gck_data_der_read_enhanced_usage (const guchar *data, gsize n_data,
+ GQuark **oids);
+
+guchar* gck_data_der_write_certificate (ASN1_TYPE asn1, gsize *n_data);
+
+/* -----------------------------------------------------------------------------
+ * CIPHERS
+ */
+
+GckDataResult gck_data_der_read_cipher (GQuark oid_scheme, const gchar *password,
+ const guchar *data, gsize n_data,
+ gcry_cipher_hd_t *cih);
+
+GckDataResult gck_data_der_read_cipher_pkcs5_pbe (int cipher_algo, int cipher_mode,
+ int hash_algo, const gchar *password,
+ const guchar *data, gsize n_data,
+ gcry_cipher_hd_t *cih);
+
+GckDataResult gck_data_der_read_cipher_pkcs5_pbes2 (const gchar *password, const guchar *data,
+ gsize n_data, gcry_cipher_hd_t *cih);
+
+GckDataResult gck_data_der_read_cipher_pkcs12_pbe (int cipher_algo, int cipher_mode,
+ const gchar *password, const guchar *data,
+ gsize n_data, gcry_cipher_hd_t *cih);
+
+#endif /*GKRPKIXDER_H_*/
Added: trunk/pkcs11/gck/gck-data-openssl.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-openssl.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,451 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-data-openssl.c - OpenSSL compatibility functionality
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gck-crypto.h"
+#include "gck-data-openssl.h"
+
+#include "common/gkr-secure-memory.h"
+
+#include <gcrypt.h>
+#include <libtasn1.h>
+
+#include <glib.h>
+
+/* ----------------------------------------------------------------------------
+ * DEFINITIONS
+ */
+
+const static struct {
+ const gchar *desc;
+ int algo;
+ int mode;
+} openssl_algos[] = {
+ { "DES-ECB", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB },
+ { "DES-CFB64", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CFB },
+ { "DES-CFB", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CFB },
+ /* DES-CFB1 */
+ /* DES-CFB8 */
+ /* DESX-CBC */
+ /* DES-EDE */
+ /* DES-EDE-CBC */
+ /* DES-EDE-ECB */
+ /* DES-EDE-CFB64 DES-EDE-CFB */
+ /* DES-EDE-CFB1 */
+ /* DES-EDE-CFB8 */
+ /* DES-EDE-OFB */
+ /* DES-EDE3 */
+ { "DES-EDE3-ECB", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_ECB },
+ { "DES-EDE3-CFB64", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CFB },
+ { "DES-EDE3-CFB", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CFB },
+ /* DES-EDE3-CFB1 */
+ /* DES-EDE3-CFB8 */
+ { "DES-OFB", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_OFB },
+ { "DES-EDE3-OFB", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_OFB },
+ { "DES-CBC", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC },
+ { "DES-EDE3-CBC", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC },
+ /* RC2-ECB */
+ /* RC2-CBC */
+ /* RC2-40-CBC */
+ /* RC2-64-CBC */
+ /* RC2-CFB64 RC2-CFB */
+ /* RC2-OFB */
+ { "RC4", GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM },
+ { "RC4-40", GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM },
+ { "IDEA-ECB", GCRY_CIPHER_IDEA, GCRY_CIPHER_MODE_ECB },
+ { "IDEA-CFB64", GCRY_CIPHER_IDEA, GCRY_CIPHER_MODE_CFB },
+ { "IDEA-OFB", GCRY_CIPHER_IDEA, GCRY_CIPHER_MODE_OFB },
+ { "IDEA-CBC", GCRY_CIPHER_IDEA, GCRY_CIPHER_MODE_CBC },
+ { "BF-ECB", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB },
+ { "BF-CBC", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC },
+ { "BF-CFB64", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CFB },
+ { "BF-CFB", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CFB },
+ { "BF-OFB", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB },
+ { "CAST5-ECB", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_ECB },
+ { "CAST5-CBC", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC },
+ { "CAST5-CFB64", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CFB },
+ { "CAST5-CFB", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CFB },
+ { "CAST5-OFB", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_OFB },
+ /* RC5-32-12-16-CBC */
+ /* RC5-32-12-16-ECB */
+ /* RC5-32-12-16-CFB64 RC5-32-12-16-CFB */
+ /* RC5-32-12-16-OFB */
+ { "AES-128-ECB", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB },
+ { "AES-128-CBC", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC },
+ /* AES-128-CFB1 */
+ /* AES-128-CFB8 */
+ { "AES-128-CFB128", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CFB },
+ { "AES-128-CFB", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CFB },
+ { "AES-128-OFB", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_OFB },
+ { "AES-128-CTR", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR },
+ { "AES-192-ECB", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_ECB },
+ { "AES-192-CBC", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC },
+ /* AES-192-CFB1 */
+ /* AES-192-CFB8 */
+ { "AES-192-CFB128", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CFB },
+ { "AES-192-CFB", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CFB },
+ { "AES-192-OFB", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_OFB },
+ { "AES-192-CTR", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR },
+ { "AES-256-ECB", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB },
+ { "AES-256-CBC", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC },
+ /* AES-256-CFB1 */
+ /* AES-256-CFB8 */
+ { "AES-256-CFB128", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB },
+ { "AES-256-CFB", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB },
+ { "AES-256-OFB", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB },
+ { "AES-256-CTR", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR },
+ /* CAMELLIA-128-ECB */
+ /* CAMELLIA-128-CBC */
+ /* CAMELLIA-128-CFB1 */
+ /* CAMELLIA-128-CFB8 */
+ /* CAMELLIA-128-CFB128 CAMELLIA-128-CFB */
+ /* CAMELLIA-128-OFB */
+ /* CAMELLIA-192-ECB */
+ /* CAMELLIA-192-CBC */
+ /* CAMELLIA-192-CFB1 */
+ /* CAMELLIA-192-CFB8 */
+ /* CAMELLIA-192-CFB128 CAMELLIA-192-CFB */
+ /* CAMELLIA-192_OFB */
+ /* CAMELLIA-256-ECB */
+ /* CAMELLIA-256-CBC */
+ /* CAMELLIA-256-CFB1 */
+ /* CAMELLIA-256-CFB8 */
+ /* CAMELLIA-256-CFB128 CAMELLIA-256-CFB */
+ /* CAMELLIA-256-OFB */
+};
+
+static const char HEXC[] = "0123456789ABCDEF";
+
+/* ------------------------------------------------------------------------- */
+
+static gboolean
+hex_decode (const gchar *data, gsize n_data,
+ guchar *decoded, gsize *n_decoded)
+{
+ gushort j;
+ gint state = 0;
+ const gchar* pos;
+
+ g_assert (data);
+ g_assert (decoded);
+ g_assert (n_decoded);
+
+ g_return_val_if_fail (*n_decoded >= n_data / 2, FALSE);
+ *n_decoded = 0;
+
+ while (n_data > 0)
+ {
+ if (!g_ascii_isspace (*data)) {
+
+ /* Find the position */
+ pos = strchr (HEXC, g_ascii_toupper (*data));
+ if (pos == 0)
+ break;
+
+ j = pos - HEXC;
+ if(!state) {
+ *decoded = (j & 0xf) << 4;
+ state = 1;
+ } else {
+ *decoded |= (j & 0xf);
+ (*n_decoded)++;
+ decoded++;
+ state = 0;
+ }
+ }
+
+ ++data;
+ --n_data;
+ }
+
+ g_return_val_if_fail (state == 0, FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+hex_encode (const guchar *data, gsize n_data,
+ gchar *encoded, gsize *n_encoded)
+{
+ guchar j;
+
+ g_return_val_if_fail (*n_encoded >= n_data * 2 + 1, FALSE);
+
+ while(n_data > 0) {
+ j = *(data) >> 4 & 0xf;
+ *(encoded++) = HEXC[j];
+
+ j = *(data++) & 0xf;
+ *(encoded++) = HEXC[j];
+
+ n_data--;
+ }
+
+ /* Null terminate */
+ *encoded = 0;
+ return TRUE;
+}
+
+int
+gck_data_openssl_parse_algo (const char *name, int *mode)
+{
+ static GQuark openssl_quarks[G_N_ELEMENTS(openssl_algos)] = { 0, };
+ static gsize openssl_quarks_inited = 0;
+ GQuark q;
+ int i;
+
+ if (g_once_init_enter (&openssl_quarks_inited)) {
+ for (i = 0; i < G_N_ELEMENTS(openssl_algos); ++i)
+ openssl_quarks[i] = g_quark_from_static_string (openssl_algos[i].desc);
+ g_once_init_leave (&openssl_quarks_inited, 1);
+ }
+
+ q = g_quark_try_string (name);
+ if (q) {
+ for (i = 0; i < G_N_ELEMENTS(openssl_algos); ++i) {
+ if (q == openssl_quarks[i]) {
+ *mode = openssl_algos[i].mode;
+ return openssl_algos[i].algo;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static gboolean
+parse_dekinfo (const gchar *dek, int *algo, int *mode, guchar **iv)
+{
+ gboolean success = FALSE;
+ gchar **parts = NULL;
+ gcry_error_t gcry;
+ gsize ivlen, len;
+
+ parts = g_strsplit (dek, ",", 2);
+ if (!parts || !parts[0] || !parts[1])
+ goto done;
+
+ /* Parse the algorithm name */
+ *algo = gck_data_openssl_parse_algo (parts[0], mode);
+ if (!*algo)
+ goto done;
+
+ /* Make sure this is usable */
+ gcry = gcry_cipher_test_algo (*algo);
+ if (gcry)
+ goto done;
+
+ /* Parse the IV */
+ ivlen = len = gcry_cipher_get_algo_blklen (*algo);
+ *iv = g_malloc (ivlen);
+
+ if (!hex_decode (parts[1], strlen (parts[1]), *iv, &len)) {
+ g_free (*iv);
+ goto done;
+ }
+
+ if (ivlen != len) {
+ g_free (*iv);
+ goto done;
+ }
+
+ success = TRUE;
+
+done:
+ g_strfreev (parts);
+ return success;
+}
+
+GckDataResult
+gck_data_openssl_decrypt_block (const gchar *dekinfo, const gchar *password,
+ const guchar *data, gsize n_data,
+ guchar **decrypted, gsize *n_decrypted)
+{
+ gcry_cipher_hd_t ch;
+ guchar *key = NULL;
+ guchar *iv = NULL;
+ int gcry, ivlen;
+ int algo = 0;
+ int mode = 0;
+
+ if (!parse_dekinfo (dekinfo, &algo, &mode, &iv))
+ return GCK_DATA_UNRECOGNIZED;
+
+ ivlen = gcry_cipher_get_algo_blklen (algo);
+
+ /* We assume the iv is at least as long as at 8 byte salt */
+ g_return_val_if_fail (ivlen >= 8, FALSE);
+
+ /* IV is already set from the DEK info */
+ if (!gck_crypto_symkey_generate_simple (algo, GCRY_MD_MD5, password,
+ iv, 8, 1, &key, NULL)) {
+ g_free (iv);
+ return GCK_DATA_FAILURE;
+ }
+
+ /* TODO: Use secure memory */
+ gcry = gcry_cipher_open (&ch, algo, mode, 0);
+ g_return_val_if_fail (!gcry, GCK_DATA_FAILURE);
+
+ gcry = gcry_cipher_setkey (ch, key, gcry_cipher_get_algo_keylen (algo));
+ g_return_val_if_fail (!gcry, GCK_DATA_UNRECOGNIZED);
+ gkr_secure_free (key);
+
+ /* 16 = 128 bits */
+ gcry = gcry_cipher_setiv (ch, iv, ivlen);
+ g_return_val_if_fail (!gcry, GCK_DATA_UNRECOGNIZED);
+ g_free (iv);
+
+ /* Allocate output area */
+ *n_decrypted = n_data;
+ *decrypted = gkr_secure_alloc (n_data);
+
+ gcry = gcry_cipher_decrypt (ch, *decrypted, *n_decrypted, (void*)data, n_data);
+ if (gcry) {
+ gkr_secure_free (*decrypted);
+ g_return_val_if_reached (GCK_DATA_FAILURE);
+ }
+
+ gcry_cipher_close (ch);
+
+ return GCK_DATA_SUCCESS;
+}
+
+gboolean
+gck_data_openssl_encrypt_block (const gchar *dekinfo, const gchar *password,
+ const guchar *data, gsize n_data,
+ guchar **encrypted, gsize *n_encrypted)
+{
+ gsize n_overflow, n_batch, n_padding;
+ gcry_cipher_hd_t ch;
+ guchar *key = NULL;
+ guchar *iv = NULL;
+ guchar *padded = NULL;
+ int gcry, ivlen;
+ int algo = 0;
+ int mode = 0;
+
+ if (!parse_dekinfo (dekinfo, &algo, &mode, &iv))
+ g_return_val_if_reached (FALSE);
+
+ ivlen = gcry_cipher_get_algo_blklen (algo);
+
+ /* We assume the iv is at least as long as at 8 byte salt */
+ g_return_val_if_fail (ivlen >= 8, FALSE);
+
+ /* IV is already set from the DEK info */
+ if (!gck_crypto_symkey_generate_simple (algo, GCRY_MD_MD5, password,
+ iv, 8, 1, &key, NULL))
+ g_return_val_if_reached (FALSE);
+
+ gcry = gcry_cipher_open (&ch, algo, mode, 0);
+ g_return_val_if_fail (!gcry, FALSE);
+
+ gcry = gcry_cipher_setkey (ch, key, gcry_cipher_get_algo_keylen (algo));
+ g_return_val_if_fail (!gcry, FALSE);
+ gkr_secure_free (key);
+
+ /* 16 = 128 bits */
+ gcry = gcry_cipher_setiv (ch, iv, ivlen);
+ g_return_val_if_fail (!gcry, FALSE);
+ g_free (iv);
+
+ /* Allocate output area */
+ n_overflow = (n_data % ivlen);
+ n_padding = n_overflow ? (ivlen - n_overflow) : 0;
+ n_batch = n_data - n_overflow;
+ *n_encrypted = n_data + n_padding;
+ *encrypted = g_malloc0 (*n_encrypted);
+
+ g_assert (*n_encrypted % ivlen == 0);
+ g_assert (*n_encrypted >= n_data);
+ g_assert (*n_encrypted == n_batch + n_overflow + n_padding);
+
+ /* Encrypt everything but the last bit */
+ gcry = gcry_cipher_encrypt (ch, *encrypted, n_batch, (void*)data, n_batch);
+ if (gcry) {
+ g_free (*encrypted);
+ g_return_val_if_reached (FALSE);
+ }
+
+ /* Encrypt the padded block */
+ if (n_overflow) {
+ padded = gkr_secure_alloc (ivlen);
+ memset (padded, 0, ivlen);
+ memcpy (padded, data + n_batch, n_overflow);
+ gcry = gcry_cipher_encrypt (ch, *encrypted + n_batch, ivlen, padded, ivlen);
+ gkr_secure_free (padded);
+ if (gcry) {
+ g_free (*encrypted);
+ g_return_val_if_reached (FALSE);
+ }
+ }
+
+ gcry_cipher_close (ch);
+ return TRUE;
+}
+
+const gchar*
+gck_data_openssl_get_dekinfo (GHashTable *headers)
+{
+ const gchar *val;
+ if (!headers)
+ return NULL;
+ val = g_hash_table_lookup (headers, "Proc-Type");
+ if (!val || strcmp (val, "4,ENCRYPTED") != 0)
+ return NULL;
+ val = g_hash_table_lookup (headers, "DEK-Info");
+ g_return_val_if_fail (val, NULL);
+ return val;
+}
+
+const gchar*
+gck_data_openssl_prep_dekinfo (GHashTable *headers)
+{
+ gsize ivlen, len, n_encoded;
+ gchar buf[256];
+ guchar *iv;
+ const gchar *dekinfo;
+
+ strcpy (buf, "DES-EDE3-CBC,");
+
+ /* Create the iv */
+ ivlen = gcry_cipher_get_algo_blklen (GCRY_CIPHER_3DES);
+ g_return_val_if_fail (ivlen, NULL);
+ iv = g_malloc (ivlen);
+ gcry_create_nonce (iv, ivlen);
+
+ /* And encode it into the string */
+ len = strlen (buf);
+ g_return_val_if_fail (sizeof (buf) - len > ivlen * 2, NULL);
+ n_encoded = (ivlen * 2) + 1;
+ if (!hex_encode (iv, ivlen, buf + len, &n_encoded))
+ g_return_val_if_reached (NULL);
+
+ dekinfo = g_strdup (buf);
+ g_hash_table_insert (headers, g_strdup ("DEK-Info"), (void*)dekinfo);
+ g_hash_table_insert (headers, g_strdup ("Proc-Type"), g_strdup ("4,ENCRYPTED"));
+
+ return dekinfo;
+}
Added: trunk/pkcs11/gck/gck-data-openssl.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-openssl.h Mon Dec 22 20:21:06 2008
@@ -0,0 +1,43 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-data-openssl.h - OpenSSL compatibility functionality
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef GCKDATAOPENSSL_H_
+#define GCKDATAOPENSSL_H_
+
+#include "gck-data-types.h"
+
+int gck_data_openssl_parse_algo (const gchar *name, int *mode);
+
+gboolean gck_data_openssl_encrypt_block (const gchar *dekinfo, const gchar *password,
+ const guchar *data, gsize n_data,
+ guchar **encrypted, gsize *n_encrypted);
+
+GckDataResult gck_data_openssl_decrypt_block (const gchar *dekinfo, const gchar *password,
+ const guchar *data, gsize n_data,
+ guchar **decrypted, gsize *n_decrypted);
+
+const gchar* gck_data_openssl_get_dekinfo (GHashTable *headers);
+
+const gchar* gck_data_openssl_prep_dekinfo (GHashTable *headers);
+
+#endif /* GCKDATAOPENSSL_H_ */
Added: trunk/pkcs11/gck/gck-data-pem.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-pem.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,345 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gkr-pkix-pem.c - PEM base64 encoding helper routines
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gck-data-pem.h"
+
+#include "common/gkr-secure-memory.h"
+
+#include <glib.h>
+
+#include <ctype.h>
+#include <string.h>
+
+/*
+ * PEM looks like:
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,704CFFD62FBA03E9
+ *
+ * 4AV/g0BiTeb07hzo4/Ct47HGhHEshMhBPGJ843QzuAinpZBbg3OxwPsQsLgoPhJL
+ * Bg6Oxyz9M4UN1Xlx6Lyo2lRT908mBP6dl/OItLsVArqAzM+e29KHQVNjV1h7xN9F
+ * u84tOgZftKun+ZkQUOoRvMLLu4yV4CUraks9tgyXquugGba/tbeyj2MYsC8wwSJX
+ * ....
+ * -----END RSA PRIVATE KEY-----
+ */
+
+#define PEM_SUFF "-----"
+#define PEM_SUFF_L 5
+#define PEM_PREF_BEGIN "-----BEGIN "
+#define PEM_PREF_BEGIN_L 11
+#define PEM_PREF_END "-----END "
+#define PEM_PREF_END_L 9
+
+static void
+parse_header_lines (const gchar *hbeg, const gchar *hend, GHashTable **result)
+{
+ gchar **lines, **l;
+ gchar *line, *name, *value;
+ gchar *copy;
+
+ copy = g_strndup (hbeg, hend - hbeg);
+ lines = g_strsplit (copy, "\n", 0);
+ g_free (copy);
+
+ for (l = lines; l && *l; ++l) {
+ line = *l;
+ g_strstrip (line);
+
+ /* Look for the break between name: value */
+ value = strchr (line, ':');
+ if (value == NULL)
+ continue;
+
+ *value = 0;
+ value = g_strdup (value + 1);
+ g_strstrip (value);
+
+ name = g_strdup (line);
+ g_strstrip (name);
+
+ if (!*result)
+ *result = gck_data_pem_headers_new ();
+ g_hash_table_replace (*result, name, value);
+ }
+
+ g_strfreev (lines);
+}
+
+static const gchar*
+pem_find_begin (const gchar *data, gsize n_data, GQuark *type)
+{
+ const gchar *pref, *suff;
+ gchar *stype;
+
+ /* Look for a prefix */
+ pref = g_strstr_len ((gchar*)data, n_data, PEM_PREF_BEGIN);
+ if (!pref)
+ return NULL;
+
+ n_data -= (pref - data) + PEM_PREF_BEGIN_L;
+ data = pref + PEM_PREF_BEGIN_L;
+
+ /* Look for the end of that begin */
+ suff = g_strstr_len ((gchar*)data, n_data, PEM_SUFF);
+ if (!suff)
+ return NULL;
+
+ /* Make sure on the same line */
+ if (memchr (pref, '\n', suff - pref))
+ return NULL;
+
+ if (type) {
+ *type = 0;
+ pref += PEM_PREF_BEGIN_L;
+ g_assert (suff > pref);
+ stype = g_alloca (suff - pref + 1);
+ memcpy (stype, pref, suff - pref);
+ stype[suff - pref] = 0;
+ *type = g_quark_from_string (stype);
+ }
+
+ /* The byte after this ---BEGIN--- */
+ return suff + PEM_SUFF_L;
+}
+
+static const gchar*
+pem_find_end (const gchar *data, gsize n_data, GQuark type)
+{
+ const gchar *stype;
+ const gchar *pref;
+ gsize n_type;
+
+ /* Look for a prefix */
+ pref = g_strstr_len (data, n_data, PEM_PREF_END);
+ if (!pref)
+ return NULL;
+
+ n_data -= (pref - data) + PEM_PREF_END_L;
+ data = pref + PEM_PREF_END_L;
+
+ /* Next comes the type string */
+ stype = g_quark_to_string (type);
+ n_type = strlen (stype);
+ if (strncmp ((gchar*)data, stype, n_type) != 0)
+ return NULL;
+
+ n_data -= n_type;
+ data += n_type;
+
+ /* Next comes the suffix */
+ if (strncmp ((gchar*)data, PEM_SUFF, PEM_SUFF_L) != 0)
+ return NULL;
+
+ /* The beginning of this ---END--- */
+ return pref;
+}
+
+static gboolean
+pem_parse_block (const gchar *data, gsize n_data, guchar **decoded, gsize *n_decoded,
+ GHashTable **headers)
+{
+ const gchar *x, *hbeg, *hend;
+ const gchar *p, *end;
+ gint state = 0;
+ guint save = 0;
+
+ g_assert (data);
+ g_assert (n_data);
+
+ g_assert (decoded);
+ g_assert (n_decoded);
+
+ p = data;
+ end = p + n_data;
+
+ hbeg = hend = NULL;
+
+ /* Try and find a pair of blank lines with only white space between */
+ while (hend == NULL) {
+ x = memchr (p, '\n', end - p);
+ if (!x)
+ break;
+ ++x;
+ while (isspace (*x)) {
+ /* Found a second line, with only spaces between */
+ if (*x == '\n') {
+ hbeg = data;
+ hend = x;
+ break;
+ /* Found a space between two lines */
+ } else {
+ ++x;
+ }
+ }
+
+ /* Try next line */
+ p = x;
+ }
+
+ /* Headers found? */
+ if (hbeg && hend) {
+ data = hend;
+ n_data = end - data;
+ }
+
+ *n_decoded = (n_data * 3) / 4 + 1;
+ if (gkr_secure_check (data))
+ *decoded = gkr_secure_alloc (*n_decoded);
+ else
+ *decoded = g_malloc (*n_decoded);
+ g_return_val_if_fail (*decoded, FALSE);
+
+ *n_decoded = g_base64_decode_step (data, n_data, *decoded, &state, &save);
+ if (!*n_decoded) {
+ gkr_secure_free (*decoded);
+ return FALSE;
+ }
+
+ if (headers && hbeg && hend)
+ parse_header_lines (hbeg, hend, headers);
+
+ return TRUE;
+}
+
+GHashTable*
+gck_data_pem_headers_new (void)
+{
+ return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+}
+
+guint
+gck_data_pem_parse (const guchar *data, gsize n_data,
+ GckDataPemCallback callback, gpointer user_data)
+{
+ const gchar *beg, *end;
+ guint nfound = 0;
+ guchar *decoded = NULL;
+ gsize n_decoded = 0;
+ GHashTable *headers = NULL;
+ GQuark type;
+
+ g_return_val_if_fail (data, 0);
+ g_return_val_if_fail (n_data, 0);
+ g_return_val_if_fail (callback, 0);
+
+ while (n_data > 0) {
+
+ /* This returns the first character after the PEM BEGIN header */
+ beg = pem_find_begin ((const gchar*)data, n_data, &type);
+ if (!beg)
+ break;
+
+ g_assert (type);
+
+ /* This returns the character position before the PEM END header */
+ end = pem_find_end ((const gchar*)beg, n_data - ((const guchar*)beg - data), type);
+ if (!end)
+ break;
+
+ if (beg != end) {
+ if (pem_parse_block (beg, end - beg, &decoded, &n_decoded, &headers)) {
+ (callback) (type, decoded, n_decoded, headers, user_data);
+ ++nfound;
+ gkr_secure_free (decoded);
+ if (headers)
+ g_hash_table_remove_all (headers);
+ }
+ }
+
+ /* Try for another block */
+ end += PEM_SUFF_L;
+ n_data -= (const guchar*)end - data;
+ data = (const guchar*)end;
+ }
+
+ if (headers)
+ g_hash_table_destroy (headers);
+
+ return nfound;
+}
+
+#ifdef UNTESTED_CODE
+
+static void
+append_each_header (gpointer key, gpointer value, gpointer user_data)
+{
+ GString *string = (GString*)user_data;
+
+ g_string_append (string, (gchar*)key);
+ g_string_append (string, ": ");
+ g_string_append (string, (gchar*)value);
+ g_string_append_c (string, '\n');
+}
+
+guchar*
+gck_data_pem_write (const guchar *data, gsize n_data, GQuark type,
+ GHashTable *headers, gsize *n_result)
+{
+ GString *string;
+ gint state, save;
+ gsize length, n_prefix;
+
+ g_return_val_if_fail (data || !n_data, NULL);
+ g_return_val_if_fail (type, NULL);
+ g_return_val_if_fail (n_result, NULL);
+
+ string = g_string_sized_new (4096);
+
+ /* The prefix */
+ g_string_append_len (string, PEM_PREF_BEGIN, PEM_PREF_BEGIN_L);
+ g_string_append (string, g_quark_to_string (type));
+ g_string_append_len (string, PEM_SUFF, PEM_SUFF_L);
+ g_string_append_c (string, '\n');
+
+ /* The headers */
+ if (headers && g_hash_table_size (headers) > 0) {
+ g_hash_table_foreach (headers, append_each_header, string);
+ g_string_append_c (string, '\n');
+ }
+
+ /* Resize string to fit the base64 data. Algorithm from Glib reference */
+ length = n_data * 4 / 3 + n_data * 4 / (3 * 72) + 7;
+ n_prefix = string->len;
+ g_string_set_size (string, n_prefix + length);
+
+ /* The actual base64 data */
+ state = save = 0;
+ length = g_base64_encode_step (data, n_data, TRUE,
+ string->str + string->len, &state, &save);
+ g_string_set_size (string, n_prefix + length);
+
+ /* The suffix */
+ g_string_append_c (string, '\n');
+ g_string_append_len (string, PEM_PREF_END, PEM_PREF_END_L);
+ g_string_append (string, g_quark_to_string (type));
+ g_string_append_len (string, PEM_SUFF, PEM_SUFF_L);
+ g_string_append_c (string, '\n');
+
+ *n_result = string->len;
+ return (guchar*)g_string_free (string, FALSE);
+}
+
+#endif /* UNTESTED_CODE */
Added: trunk/pkcs11/gck/gck-data-pem.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-pem.h Mon Dec 22 20:21:06 2008
@@ -0,0 +1,42 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gkr-pkix-pem.h - PEM base64 helper routines
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef GCK_DATA_PEM_H_
+#define GCK_DATA_PEM_H_
+
+#include <glib.h>
+
+typedef void (*GckDataPemCallback) (GQuark type, const guchar *data, gsize n_data,
+ GHashTable *headers, gpointer user_data);
+
+GHashTable* gck_data_pem_headers_new (void);
+
+guint gck_data_pem_parse (const guchar *data, gsize n_data,
+ GckDataPemCallback callback,
+ gpointer user_data);
+
+guchar* gck_data_pem_write (const guchar *data, gsize n_data,
+ GQuark type, GHashTable *headers,
+ gsize *n_result);
+
+#endif /* GCK_DATA_PEM_H_ */
Added: trunk/pkcs11/gck/gck-data-types.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-data-types.h Mon Dec 22 20:21:06 2008
@@ -0,0 +1,14 @@
+#ifndef GCKDATA_H_
+#define GCKDATA_H_
+
+#include <glib.h>
+
+typedef enum _GckDataResult {
+ GCK_DATA_FAILURE = -2,
+ GCK_DATA_UNRECOGNIZED = 0,
+ GCK_DATA_SUCCESS = 1
+} GckDataResult;
+
+typedef void* (*GckDataAllocator) (void* p, unsigned long len);
+
+#endif /* GCKDATA_H_ */
Added: trunk/pkcs11/gck/gck-file-tracker.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-file-tracker.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,302 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-file-tracker.c - Watch for changes in a directory
+
+ Copyright (C) 2008 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gck-file-tracker.h"
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+
+typedef struct _UpdateDescendants {
+ GckFileTracker *tracker;
+ GHashTable *checks;
+} UpdateDescendants;
+
+struct _GckFileTracker {
+ GObject parent;
+
+ /* Specification */
+ GPatternSpec *include;
+ GPatternSpec *exclude;
+ gchar *directory_path;
+ time_t directory_mtime;
+
+ /* Matched files */
+ GHashTable *files;
+};
+
+enum {
+ FILE_ADDED,
+ FILE_REMOVED,
+ FILE_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GckFileTracker, gck_file_tracker, G_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * HELPERS
+ */
+
+static void
+copy_key_string (gpointer key, gpointer value, gpointer data)
+{
+ GHashTable *dest = (GHashTable*)data;
+ g_hash_table_replace (dest, g_strdup (key), value);
+}
+
+static void
+remove_files (gpointer key, gpointer value, gpointer data)
+{
+ GckFileTracker *self = GCK_FILE_TRACKER (data);
+
+ g_hash_table_remove (self->files, key);
+ g_signal_emit (self, signals[FILE_REMOVED], 0, key);
+}
+
+static gboolean
+update_file (GckFileTracker *self, gboolean force_all, const gchar *path)
+{
+ time_t old_mtime;
+ struct stat sb;
+
+ if (stat (path, &sb) < 0) {
+ if (errno != ENOENT && errno != ENOTDIR && errno != EPERM)
+ g_warning ("couldn't stat file: %s: %s", path, g_strerror (errno));
+ return FALSE;
+ }
+
+ old_mtime = GPOINTER_TO_UINT (g_hash_table_lookup (self->files, path));
+ g_assert (old_mtime);
+
+ /* See if it has actually changed */
+ if (force_all || old_mtime != sb.st_mtime) {
+ g_assert (g_hash_table_lookup (self->files, path));
+ g_hash_table_insert (self->files, g_strdup (path), GUINT_TO_POINTER (sb.st_mtime));
+ g_signal_emit (self, signals[FILE_CHANGED], 0, path);
+ }
+
+ return TRUE;
+}
+
+static void
+update_each_file (gpointer key, gpointer unused, gpointer data)
+{
+ UpdateDescendants *ctx = (UpdateDescendants*)data;
+ if (update_file (ctx->tracker, FALSE, key))
+ g_hash_table_remove (ctx->checks, key);
+}
+
+static void
+update_directory (GckFileTracker *self, gboolean force_all, GHashTable *checks)
+{
+ UpdateDescendants uctx;
+ struct stat sb;
+ GError *err = NULL;
+ const char *filename;
+ gchar *path;
+ gchar *file;
+ GDir *dir;
+ int ret, lasterr;
+
+ g_assert (checks);
+ g_assert (GCK_IS_FILE_TRACKER (self));
+
+ if (!self->directory_path)
+ return;
+
+ if (stat (self->directory_path, &sb) < 0) {
+ if (errno != ENOENT && errno != ENOTDIR && errno != EPERM)
+ g_message ("couldn't stat directory: %s: %s", path, g_strerror (errno));
+ return;
+ }
+
+ /* See if it was updated since last seen or not */
+ if (!force_all && self->directory_mtime == sb.st_mtime) {
+
+ uctx.checks = checks;
+ uctx.tracker = self;
+
+ /* Still need to check for individual file updates */
+ g_hash_table_foreach (self->files, update_each_file, &uctx);
+ return;
+ }
+
+ self->directory_mtime = sb.st_mtime;
+
+ /* Actually list the directory */
+ dir = g_dir_open (self->directory_path, 0, &err);
+ if (dir == NULL) {
+ if (errno != ENOENT && errno != ENOTDIR && errno != EPERM)
+ g_message ("couldn't list keyrings at: %s: %s", path,
+ err && err->message ? err->message : "");
+ g_error_free (err);
+ return;
+ }
+
+ while ((filename = g_dir_read_name (dir)) != NULL) {
+ if (filename[0] == '.')
+ continue;
+ if (self->include && !g_pattern_match_string (self->include, filename))
+ continue;
+ if (self->exclude && g_pattern_match_string (self->exclude, filename))
+ continue;
+
+ file = g_build_filename (self->directory_path, filename, NULL);
+
+ /* If we hadn't yet seen this, then add it */
+ if (!g_hash_table_remove (checks, file)) {
+
+ /* Get the last modified time for this one */
+ ret = g_stat (file, &sb);
+ lasterr = errno;
+
+ /* Couldn't access the file */
+ if (ret < 0) {
+ g_message ("couldn't stat file: %s: %s", file, g_strerror (lasterr));
+
+ } else {
+
+ /* We don't do directories */
+ if (!(sb.st_mode & S_IFDIR)) {
+ g_hash_table_replace (self->files, g_strdup (file), GINT_TO_POINTER (sb.st_mtime));
+ g_signal_emit (self, signals[FILE_ADDED], 0, file);
+ }
+ }
+
+ /* Otherwise we already had it, see if it needs updating */
+ } else {
+ update_file (self, force_all, file);
+ }
+
+ g_free (file);
+ }
+
+ g_dir_close (dir);
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gck_file_tracker_init (GckFileTracker *self)
+{
+ self->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+}
+
+static void
+gck_file_tracker_finalize (GObject *obj)
+{
+ GckFileTracker *self = GCK_FILE_TRACKER (obj);
+
+ if (self->include)
+ g_pattern_spec_free (self->include);
+ if (self->exclude)
+ g_pattern_spec_free (self->exclude);
+ g_free (self->directory_path);
+
+ g_hash_table_destroy (self->files);
+
+ G_OBJECT_CLASS (gck_file_tracker_parent_class)->finalize (obj);
+}
+
+static void
+gck_file_tracker_class_init (GckFileTrackerClass *klass)
+{
+ GObjectClass *gobject_class;
+ gobject_class = (GObjectClass*) klass;
+
+ gck_file_tracker_parent_class = g_type_class_peek_parent (klass);
+ gobject_class->finalize = gck_file_tracker_finalize;
+
+ signals[FILE_ADDED] = g_signal_new ("file-added", GCK_TYPE_FILE_TRACKER,
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckFileTrackerClass, file_added),
+ NULL, NULL, g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ signals[FILE_CHANGED] = g_signal_new ("file-changed", GCK_TYPE_FILE_TRACKER,
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckFileTrackerClass, file_changed),
+ NULL, NULL, g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ signals[FILE_REMOVED] = g_signal_new ("file-removed", GCK_TYPE_FILE_TRACKER,
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckFileTrackerClass, file_removed),
+ NULL, NULL, g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+}
+
+GckFileTracker*
+gck_file_tracker_new (const gchar *directory, const gchar *include, const gchar *exclude)
+{
+ GckFileTracker *self;
+ const gchar *homedir;
+
+ g_return_val_if_fail (directory, NULL);
+
+ self = g_object_new (GCK_TYPE_FILE_TRACKER, NULL);
+
+ /* TODO: Use properties */
+
+ if (directory[0] == '~' && directory[1] == '/') {
+ homedir = g_getenv ("HOME");
+ if (!homedir)
+ homedir = g_get_home_dir ();
+ self->directory_path = g_build_filename (homedir, directory + 2, NULL);
+
+ /* A relative or absolute path */
+ } else {
+ self->directory_path = g_strdup (directory);
+ }
+
+ self->include = include ? g_pattern_spec_new (include) : NULL;
+ self->exclude = exclude ? g_pattern_spec_new (exclude) : NULL;
+
+ return self;
+}
+
+void
+gck_file_tracker_refresh (GckFileTracker *self, gboolean force_all)
+{
+ GHashTable *checks;
+
+ g_return_if_fail (GCK_IS_FILE_TRACKER (self));
+
+ /* Copy into our check set */
+ checks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ g_hash_table_foreach (self->files, copy_key_string, checks);
+
+ /* If only one volume, then just try and access it directly */
+ update_directory (self, force_all, checks);
+
+ /* Find any keyrings whose paths we didn't see */
+ g_hash_table_foreach (checks, remove_files, self);
+ g_hash_table_destroy (checks);
+}
Added: trunk/pkcs11/gck/gck-file-tracker.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-file-tracker.h Mon Dec 22 20:21:06 2008
@@ -0,0 +1,63 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-file-tracker.h - Watch for changes in a directory
+
+ Copyright (C) 2008, Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef __GCK_FILE_TRACKER_H__
+#define __GCK_FILE_TRACKER_H__
+
+#include <glib-object.h>
+
+#include "gck-file-tracker.h"
+
+G_BEGIN_DECLS
+
+#define GCK_TYPE_FILE_TRACKER (gck_file_tracker_get_type ())
+#define GCK_FILE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_FILE_TRACKER, GckFileTracker))
+#define GCK_FILE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_FILE_TRACKER, GObject))
+#define GCK_IS_FILE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_FILE_TRACKER))
+#define GCK_IS_FILE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_FILE_TRACKER))
+#define GCK_FILE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_FILE_TRACKER, GckFileTrackerClass))
+
+typedef struct _GckFileTracker GckFileTracker;
+typedef struct _GckFileTrackerClass GckFileTrackerClass;
+
+struct _GckFileTrackerClass {
+ GObjectClass parent_class;
+
+ void (*file_added) (GckFileTracker *locmgr, const gchar *path);
+ void (*file_changed) (GckFileTracker *locmgr, const gchar *path);
+ void (*file_removed) (GckFileTracker *locmgr, const gchar *path);
+};
+
+GType gck_file_tracker_get_type (void) G_GNUC_CONST;
+
+GckFileTracker* gck_file_tracker_new (const gchar *directory,
+ const gchar *include_pattern,
+ const gchar *exclude_pattern);
+
+void gck_file_tracker_refresh (GckFileTracker *self,
+ gboolean force_all);
+
+G_END_DECLS
+
+#endif /* __GCK_FILE_TRACKER_H__ */
+
Modified: trunk/pkcs11/gck/gck-module-ep.h
==============================================================================
--- trunk/pkcs11/gck/gck-module-ep.h (original)
+++ trunk/pkcs11/gck/gck-module-ep.h Mon Dec 22 20:21:06 2008
@@ -36,6 +36,8 @@
CK_RV rv = CKR_OK;
pid_t pid = getpid ();
+ gck_crypto_initialize (void);
+
g_static_mutex_lock (&pkcs11_module_mutex);
if (pkcs11_module != NULL) {
Modified: trunk/pkcs11/gck/gck-module.c
==============================================================================
--- trunk/pkcs11/gck/gck-module.c (original)
+++ trunk/pkcs11/gck/gck-module.c Mon Dec 22 20:21:06 2008
@@ -216,6 +216,13 @@
*/
static CK_RV
+gck_module_real_refresh_token (GckModule *self)
+{
+ /* Derived classes should do something interesting */
+ return CKR_OK;
+}
+
+static CK_RV
gck_module_real_login_user (GckModule *self, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
{
VirtualSlot *slot;
@@ -360,6 +367,7 @@
klass->slot_info = &default_slot_info;
klass->token_info = &default_token_info;
+ klass->refresh_token = gck_module_real_refresh_token;
klass->login_user = gck_module_real_login_user;
klass->logout_user = gck_module_real_logout_user;
Modified: trunk/pkcs11/gck/gck-module.h
==============================================================================
--- trunk/pkcs11/gck/gck-module.h (original)
+++ trunk/pkcs11/gck/gck-module.h Mon Dec 22 20:21:06 2008
@@ -57,6 +57,8 @@
/* virtual methods */
+ CK_RV (*refresh_token) (GckModule *self);
+
CK_RV (*login_user) (GckModule *self, CK_SLOT_ID slot_id,
CK_UTF8CHAR_PTR pin, CK_ULONG n_pin);
Added: trunk/pkcs11/gck/pk.asn
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/pk.asn Mon Dec 22 20:21:06 2008
@@ -0,0 +1,103 @@
+PK { }
+
+DEFINITIONS EXPLICIT TAGS ::=
+
+BEGIN
+
+-- This file contains parts of PKCS-1 structures and some stuff
+-- required for DSA keys.
+
+RSAPublicKey ::= SEQUENCE {
+ modulus INTEGER, -- n
+ publicExponent INTEGER -- e
+}
+
+--
+-- Representation of RSA private key with information for the
+-- CRT algorithm.
+--
+RSAPrivateKey ::= SEQUENCE {
+ version Version,
+ modulus INTEGER, -- (Usually large) n
+ publicExponent INTEGER, -- (Usually small) e
+ privateExponent INTEGER, -- (Usually large) d
+ prime1 INTEGER, -- (Usually large) p
+ prime2 INTEGER, -- (Usually large) q
+ exponent1 INTEGER, -- (Usually large) d mod (p-1)
+ exponent2 INTEGER, -- (Usually large) d mod (q-1)
+ coefficient INTEGER, -- (Usually large) (inverse of q) mod p
+ otherPrimeInfos OtherPrimeInfos OPTIONAL
+}
+
+Version ::= INTEGER { two-prime(0), multi(1) }
+-- version must be multi if otherPrimeInfos present --
+
+OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
+
+OtherPrimeInfo ::= SEQUENCE {
+ prime INTEGER, -- ri
+ exponent INTEGER, -- di
+ coefficient INTEGER -- ti
+}
+
+-- for signature calculation
+-- added by nmav
+
+AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters ANY DEFINED BY algorithm OPTIONAL
+}
+ -- contains a value of the type
+ -- registered for use with the
+ -- algorithm object identifier value
+
+DigestInfo ::= SEQUENCE {
+ digestAlgorithm DigestAlgorithmIdentifier,
+ digest Digest
+}
+
+DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+
+Digest ::= OCTET STRING
+
+DSAPublicPart ::= INTEGER
+
+DSAPublicKey ::= SEQUENCE {
+ version INTEGER, -- should be zero
+ p INTEGER,
+ q INTEGER,
+ g INTEGER,
+ Y INTEGER -- public
+}
+
+DSAParameters ::= SEQUENCE {
+ p INTEGER,
+ q INTEGER,
+ g INTEGER
+}
+
+DSASignatureValue ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+}
+
+DSAPrivatePart ::= INTEGER
+
+DSAPrivateKey ::= SEQUENCE {
+ version INTEGER, -- should be zero
+ p INTEGER,
+ q INTEGER,
+ g INTEGER,
+ Y INTEGER, -- public
+ priv INTEGER
+}
+
+-- from PKCS#3
+DHParameter ::= SEQUENCE {
+ prime INTEGER, -- p
+ base INTEGER, -- g
+ privateValueLength INTEGER OPTIONAL
+}
+
+
+END
Added: trunk/pkcs11/gck/pkix.asn
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/pkix.asn Mon Dec 22 20:21:06 2008
@@ -0,0 +1,1230 @@
+
+PKIX1 { }
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+-- This contains both PKIX1Implicit88 and RFC2630 ASN.1 modules.
+
+-- ISO arc for standard certificate and CRL extensions
+
+id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29}
+
+
+-- authority key identifier OID and syntax
+
+id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
+
+AuthorityKeyIdentifier ::= SEQUENCE {
+ keyIdentifier [0] KeyIdentifier OPTIONAL,
+ authorityCertIssuer [1] GeneralNames OPTIONAL,
+ authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ -- authorityCertIssuer and authorityCertSerialNumber shall both
+ -- be present or both be absgent
+
+KeyIdentifier ::= OCTET STRING
+
+-- subject key identifier OID and syntax
+
+id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 }
+
+SubjectKeyIdentifier ::= KeyIdentifier
+
+-- key usage extension OID and syntax
+
+id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
+
+KeyUsage ::= BIT STRING {
+ digitalSignature (0),
+ nonRepudiation (1),
+ keyEncipherment (2),
+ dataEncipherment (3),
+ keyAgreement (4),
+ keyCertSign (5),
+ cRLSign (6),
+ encipherOnly (7),
+ decipherOnly (8) }
+
+-- private key usage period extension OID and syntax
+
+id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-ce 16 }
+
+PrivateKeyUsagePeriod ::= SEQUENCE {
+ notBefore [0] GeneralizedTime OPTIONAL,
+ notAfter [1] GeneralizedTime OPTIONAL }
+ -- either notBefore or notAfter shall be present
+
+-- certificate policies extension OID and syntax
+
+id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
+
+CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+
+PolicyInformation ::= SEQUENCE {
+ policyIdentifier CertPolicyId,
+ policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ PolicyQualifierInfo OPTIONAL }
+
+CertPolicyId ::= OBJECT IDENTIFIER
+
+PolicyQualifierInfo ::= SEQUENCE {
+ policyQualifierId PolicyQualifierId,
+ qualifier ANY DEFINED BY policyQualifierId }
+
+-- Implementations that recognize additional policy qualifiers shall
+-- augment the following definition for PolicyQualifierId
+
+PolicyQualifierId ::=
+ OBJECT IDENTIFIER -- ( id-qt-cps | id-qt-unotice )
+
+-- CPS pointer qualifier
+
+CPSuri ::= IA5String
+
+-- user notice qualifier
+
+UserNotice ::= SEQUENCE {
+ noticeRef NoticeReference OPTIONAL,
+ explicitText DisplayText OPTIONAL}
+
+NoticeReference ::= SEQUENCE {
+ organization DisplayText,
+ noticeNumbers SEQUENCE OF INTEGER }
+
+DisplayText ::= CHOICE {
+ visibleString VisibleString (SIZE (1..200)),
+ bmpString BMPString (SIZE (1..200)),
+ utf8String UTF8String (SIZE (1..200)) }
+
+-- policy mapping extension OID and syntax
+
+id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 }
+
+PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ issuerDomainPolicy CertPolicyId,
+ subjectDomainPolicy CertPolicyId }
+
+-- subject alternative name extension OID and syntax
+
+-- Directory string type --
+
+DirectoryString ::= CHOICE {
+ teletexString TeletexString (SIZE (1..MAX)),
+ printableString PrintableString (SIZE (1..MAX)),
+ universalString UniversalString (SIZE (1..MAX)),
+ utf8String UTF8String (SIZE (1..MAX)),
+ bmpString BMPString (SIZE(1..MAX)),
+ -- IA5String is added here to handle old UID encoded as ia5String --
+ -- See tests/userid/ for more information. It shouldn't be here, --
+ -- so if it causes problems, considering dropping it. --
+ ia5String IA5String (SIZE(1..MAX)) }
+
+id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 }
+
+SubjectAltName ::= GeneralNames
+
+GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+
+GeneralName ::= CHOICE {
+ otherName [0] AnotherName,
+ rfc822Name [1] IA5String,
+ dNSName [2] IA5String,
+ x400Address [3] ORAddress,
+-- Changed to work with the libtasn1 parser.
+ directoryName [4] EXPLICIT RDNSequence, --Name,
+ ediPartyName [5] EDIPartyName,
+ uniformResourceIdentifier [6] IA5String,
+ iPAddress [7] OCTET STRING,
+ registeredID [8] OBJECT IDENTIFIER }
+
+-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as
+-- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax
+
+AnotherName ::= SEQUENCE {
+ type-id OBJECT IDENTIFIER,
+ value [0] EXPLICIT ANY DEFINED BY type-id }
+
+EDIPartyName ::= SEQUENCE {
+ nameAssigner [0] DirectoryString OPTIONAL,
+ partyName [1] DirectoryString }
+
+-- issuer alternative name extension OID and syntax
+
+id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 }
+
+IssuerAltName ::= GeneralNames
+
+id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 }
+
+SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+
+-- basic constraints extension OID and syntax
+
+id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 }
+
+BasicConstraints ::= SEQUENCE {
+ cA BOOLEAN DEFAULT FALSE,
+ pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+
+-- name constraints extension OID and syntax
+
+id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 }
+
+NameConstraints ::= SEQUENCE {
+ permittedSubtrees [0] GeneralSubtrees OPTIONAL,
+ excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+
+GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+
+GeneralSubtree ::= SEQUENCE {
+ base GeneralName,
+ minimum [0] BaseDistance DEFAULT 0,
+ maximum [1] BaseDistance OPTIONAL }
+
+BaseDistance ::= INTEGER (0..MAX)
+
+-- policy constraints extension OID and syntax
+
+id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 }
+
+PolicyConstraints ::= SEQUENCE {
+ requireExplicitPolicy [0] SkipCerts OPTIONAL,
+ inhibitPolicyMapping [1] SkipCerts OPTIONAL }
+
+SkipCerts ::= INTEGER (0..MAX)
+
+-- CRL distribution points extension OID and syntax
+
+id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31}
+
+CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+
+DistributionPoint ::= SEQUENCE {
+ distributionPoint [0] EXPLICIT DistributionPointName OPTIONAL,
+ reasons [1] ReasonFlags OPTIONAL,
+ cRLIssuer [2] GeneralNames OPTIONAL
+}
+
+DistributionPointName ::= CHOICE {
+ fullName [0] GeneralNames,
+ nameRelativeToCRLIssuer [1] RelativeDistinguishedName
+}
+
+ReasonFlags ::= BIT STRING {
+ unused (0),
+ keyCompromise (1),
+ cACompromise (2),
+ affiliationChanged (3),
+ superseded (4),
+ cessationOfOperation (5),
+ certificateHold (6),
+ privilegeWithdrawn (7),
+ aACompromise (8) }
+
+-- extended key usage extension OID and syntax
+
+id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}
+
+ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+
+KeyPurposeId ::= OBJECT IDENTIFIER
+
+-- extended key purpose OIDs
+id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
+id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
+id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
+id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
+id-kp-ipsecEndSystem OBJECT IDENTIFIER ::= { id-kp 5 }
+id-kp-ipsecTunnel OBJECT IDENTIFIER ::= { id-kp 6 }
+id-kp-ipsecUser OBJECT IDENTIFIER ::= { id-kp 7 }
+id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
+
+-- authority info access
+
+id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+
+AuthorityInfoAccessSyntax ::=
+ SEQUENCE SIZE (1..MAX) OF AccessDescription
+
+AccessDescription ::= SEQUENCE {
+ accessMethod OBJECT IDENTIFIER,
+ accessLocation GeneralName }
+
+-- CRL number extension OID and syntax
+
+id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
+
+CRLNumber ::= INTEGER (0..MAX)
+
+-- issuing distribution point extension OID and syntax
+
+id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }
+
+IssuingDistributionPoint ::= SEQUENCE {
+ distributionPoint [0] DistributionPointName OPTIONAL,
+ onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
+ onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
+ onlySomeReasons [3] ReasonFlags OPTIONAL,
+ indirectCRL [4] BOOLEAN DEFAULT FALSE }
+
+
+id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 }
+
+-- deltaCRLIndicator ::= BaseCRLNumber
+
+BaseCRLNumber ::= CRLNumber
+
+-- CRL reasons extension OID and syntax
+
+id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }
+
+CRLReason ::= ENUMERATED {
+ unspecified (0),
+ keyCompromise (1),
+ cACompromise (2),
+ affiliationChanged (3),
+ superseded (4),
+ cessationOfOperation (5),
+ certificateHold (6),
+ removeFromCRL (8) }
+
+-- certificate issuer CRL entry extension OID and syntax
+
+id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 }
+
+CertificateIssuer ::= GeneralNames
+
+-- hold instruction extension OID and syntax
+
+id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 }
+
+HoldInstructionCode ::= OBJECT IDENTIFIER
+
+-- ANSI x9 holdinstructions
+
+-- ANSI x9 arc holdinstruction arc
+holdInstruction OBJECT IDENTIFIER ::=
+ {joint-iso-itu-t(2) member-body(2) us(840) x9cm(10040) 2}
+
+-- ANSI X9 holdinstructions referenced by this standard
+id-holdinstruction-none OBJECT IDENTIFIER ::=
+ {holdInstruction 1} -- deprecated
+id-holdinstruction-callissuer OBJECT IDENTIFIER ::=
+ {holdInstruction 2}
+id-holdinstruction-reject OBJECT IDENTIFIER ::=
+ {holdInstruction 3}
+
+-- invalidity date CRL entry extension OID and syntax
+
+id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }
+
+InvalidityDate ::= GeneralizedTime
+
+
+-- --------------------------------------
+-- EXPLICIT
+-- --------------------------------------
+
+-- UNIVERSAL Types defined in '93 and '98 ASN.1
+-- but required by this specification
+
+VisibleString ::= [UNIVERSAL 26] IMPLICIT OCTET STRING
+
+NumericString ::= [UNIVERSAL 18] IMPLICIT OCTET STRING
+
+IA5String ::= [UNIVERSAL 22] IMPLICIT OCTET STRING
+
+TeletexString ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
+
+PrintableString ::= [UNIVERSAL 19] IMPLICIT OCTET STRING
+
+UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING
+ -- UniversalString is defined in ASN.1:1993
+
+BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING
+ -- BMPString is the subtype of UniversalString and models
+ -- the Basic Multilingual Plane of ISO/IEC/ITU 10646-1
+
+UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING
+ -- The content of this type conforms to RFC 2279.
+
+
+-- PKIX specific OIDs
+
+id-pkix OBJECT IDENTIFIER ::=
+ { iso(1) identified-organization(3) dod(6) internet(1)
+ security(5) mechanisms(5) pkix(7) }
+
+-- PKIX arcs
+
+id-pe OBJECT IDENTIFIER ::= { id-pkix 1 }
+ -- arc for private certificate extensions
+id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+ -- arc for policy qualifier types
+id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
+ -- arc for extended key purpose OIDS
+id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+ -- arc for access descriptors
+
+-- policyQualifierIds for Internet policy qualifiers
+
+id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
+ -- OID for CPS qualifier
+id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
+ -- OID for user notice qualifier
+
+-- access descriptor definitions
+
+id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+
+-- attribute data types --
+
+Attribute ::= SEQUENCE {
+ type AttributeType,
+ values SET OF AttributeValue
+ -- at least one value is required --
+}
+
+AttributeType ::= OBJECT IDENTIFIER
+
+AttributeValue ::= ANY DEFINED BY type
+
+AttributeTypeAndValue ::= SEQUENCE {
+ type AttributeType,
+ value AttributeValue }
+
+-- suggested naming attributes: Definition of the following
+-- information object set may be augmented to meet local
+-- requirements. Note that deleting members of the set may
+-- prevent interoperability with conforming implementations.
+-- presented in pairs: the AttributeType followed by the
+-- type definition for the corresponding AttributeValue
+
+-- Arc for standard naming attributes
+id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4}
+
+-- Attributes of type NameDirectoryString
+id-at-initials AttributeType ::= { id-at 43 }
+X520initials ::= DirectoryString
+
+id-at-generationQualifier AttributeType ::= { id-at 44 }
+X520generationQualifier ::= DirectoryString
+
+id-at-surname AttributeType ::= { id-at 4 }
+X520surName ::= DirectoryString
+
+id-at-givenName AttributeType ::= { id-at 42 }
+X520givenName ::= DirectoryString
+
+id-at-name AttributeType ::= { id-at 41 }
+X520name ::= DirectoryString
+
+id-at-commonName AttributeType ::= {id-at 3}
+X520CommonName ::= DirectoryString
+
+id-at-localityName AttributeType ::= {id-at 7}
+X520LocalityName ::= DirectoryString
+
+id-at-stateOrProvinceName AttributeType ::= {id-at 8}
+X520StateOrProvinceName ::= DirectoryString
+
+id-at-organizationName AttributeType ::= {id-at 10}
+X520OrganizationName ::= DirectoryString
+
+id-at-organizationalUnitName AttributeType ::= {id-at 11}
+X520OrganizationalUnitName ::= DirectoryString
+
+id-at-title AttributeType ::= {id-at 12}
+X520Title ::= DirectoryString
+
+id-at-description AttributeType ::= {id-at 13}
+X520Description ::= DirectoryString
+
+id-at-dnQualifier AttributeType ::= {id-at 46}
+X520dnQualifier ::= PrintableString
+
+id-at-countryName AttributeType ::= {id-at 6}
+X520countryName ::= PrintableString (SIZE (2)) -- IS 3166 codes
+
+id-at-serialNumber AttributeType ::= {id-at 5}
+X520serialNumber ::= PrintableString
+
+id-at-telephoneNumber AttributeType ::= {id-at 20}
+X520telephoneNumber ::= PrintableString
+
+id-at-facsimileTelephoneNumber AttributeType ::= {id-at 23}
+X520facsimileTelephoneNumber ::= PrintableString
+
+id-at-pseudonym AttributeType ::= {id-at 65}
+X520pseudonym ::= DirectoryString
+
+id-at-name AttributeType ::= {id-at 41}
+X520name ::= DirectoryString
+
+id-at-streetAddress AttributeType ::= {id-at 9}
+X520streetAddress ::= DirectoryString
+
+id-at-postalAddress AttributeType ::= {id-at 16}
+X520postalAddress ::= PostalAddress
+
+PostalAddress ::= SEQUENCE OF DirectoryString
+
+
+ -- Legacy attributes
+
+pkcs OBJECT IDENTIFIER ::=
+ { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) }
+
+pkcs-9 OBJECT IDENTIFIER ::=
+ { pkcs 9 }
+
+
+emailAddress AttributeType ::= { pkcs-9 1 }
+
+Pkcs9email ::= IA5String (SIZE (1..ub-emailaddress-length))
+
+-- naming data types --
+
+Name ::= CHOICE { -- only one possibility for now --
+ rdnSequence RDNSequence }
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+DistinguishedName ::= RDNSequence
+
+RelativeDistinguishedName ::=
+ SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+
+
+
+-- --------------------------------------------------------
+-- certificate and CRL specific structures begin here
+-- --------------------------------------------------------
+
+Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING }
+
+TBSCertificate ::= SEQUENCE {
+ version [0] EXPLICIT Version DEFAULT v1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier,
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ -- If present, version shall be v2 or v3
+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ -- If present, version shall be v2 or v3
+ extensions [3] EXPLICIT Extensions OPTIONAL
+ -- If present, version shall be v3 --
+}
+
+Version ::= INTEGER { v1(0), v2(1), v3(2) }
+
+CertificateSerialNumber ::= INTEGER
+
+Validity ::= SEQUENCE {
+ notBefore Time,
+ notAfter Time }
+
+Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime }
+
+UniqueIdentifier ::= BIT STRING
+
+SubjectPublicKeyInfo ::= SEQUENCE {
+ algorithm AlgorithmIdentifier,
+ subjectPublicKey BIT STRING }
+
+Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+
+Extension ::= SEQUENCE {
+ extnID OBJECT IDENTIFIER,
+ critical BOOLEAN DEFAULT FALSE,
+ extnValue OCTET STRING }
+
+
+-- ------------------------------------------
+-- CRL structures
+-- ------------------------------------------
+
+CertificateList ::= SEQUENCE {
+ tbsCertList TBSCertList,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING }
+
+TBSCertList ::= SEQUENCE {
+ version Version OPTIONAL,
+ -- if present, shall be v2
+ signature AlgorithmIdentifier,
+ issuer Name,
+ thisUpdate Time,
+ nextUpdate Time OPTIONAL,
+ revokedCertificates SEQUENCE OF SEQUENCE {
+ userCertificate CertificateSerialNumber,
+ revocationDate Time,
+ crlEntryExtensions Extensions OPTIONAL
+ -- if present, shall be v2
+ } OPTIONAL,
+ crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ -- if present, shall be v2 --
+}
+
+-- Version, Time, CertificateSerialNumber, and Extensions were
+-- defined earlier for use in the certificate structure
+
+AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters ANY DEFINED BY algorithm OPTIONAL }
+ -- contains a value of the type
+ -- registered for use with the
+ -- algorithm object identifier value
+
+-- Algorithm OIDs and parameter structures
+
+pkcs-1 OBJECT IDENTIFIER ::= {
+ pkcs 1 }
+
+rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
+
+md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
+
+md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
+
+sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
+
+id-dsa-with-sha1 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) x9-57 (10040) x9algorithm(4) 3 }
+
+Dss-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+}
+
+dhpublicnumber OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1 }
+
+DomainParameters ::= SEQUENCE {
+ p INTEGER, -- odd prime, p=jq +1
+ g INTEGER, -- generator, g
+ q INTEGER, -- factor of p-1
+ j INTEGER OPTIONAL, -- subgroup factor, j>= 2
+ validationParms ValidationParms OPTIONAL }
+
+ValidationParms ::= SEQUENCE {
+ seed BIT STRING,
+ pgenCounter INTEGER }
+
+id-dsa OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 }
+
+Dss-Parms ::= SEQUENCE {
+ p INTEGER,
+ q INTEGER,
+ g INTEGER }
+
+-- x400 address syntax starts here
+-- OR Names
+
+ORAddress ::= SEQUENCE {
+ built-in-standard-attributes BuiltInStandardAttributes,
+ built-in-domain-defined-attributes
+ BuiltInDomainDefinedAttributes OPTIONAL,
+ -- see also teletex-domain-defined-attributes
+ extension-attributes ExtensionAttributes OPTIONAL }
+-- The OR-address is semantically absent from the OR-name if the
+-- built-in-standard-attribute sequence is empty and the
+-- built-in-domain-defined-attributes and extension-attributes are
+-- both omitted.
+
+-- Built-in Standard Attributes
+
+BuiltInStandardAttributes ::= SEQUENCE {
+ country-name CountryName OPTIONAL,
+ administration-domain-name AdministrationDomainName OPTIONAL,
+ network-address [0] EXPLICIT NetworkAddress OPTIONAL,
+ -- see also extended-network-address
+ terminal-identifier [1] EXPLICIT TerminalIdentifier OPTIONAL,
+ private-domain-name [2] EXPLICIT PrivateDomainName OPTIONAL,
+ organization-name [3] EXPLICIT OrganizationName OPTIONAL,
+ -- see also teletex-organization-name
+ numeric-user-identifier [4] EXPLICIT NumericUserIdentifier OPTIONAL,
+ personal-name [5] EXPLICIT PersonalName OPTIONAL,
+ -- see also teletex-personal-name
+ organizational-unit-names [6] EXPLICIT OrganizationalUnitNames OPTIONAL
+ -- see also teletex-organizational-unit-names --
+}
+
+CountryName ::= [APPLICATION 1] CHOICE {
+ x121-dcc-code NumericString
+ (SIZE (ub-country-name-numeric-length)),
+ iso-3166-alpha2-code PrintableString
+ (SIZE (ub-country-name-alpha-length)) }
+
+AdministrationDomainName ::= [APPLICATION 2] EXPLICIT CHOICE {
+ numeric NumericString (SIZE (0..ub-domain-name-length)),
+ printable PrintableString (SIZE (0..ub-domain-name-length)) }
+
+NetworkAddress ::= X121Address -- see also extended-network-address
+
+X121Address ::= NumericString (SIZE (1..ub-x121-address-length))
+
+TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length))
+
+PrivateDomainName ::= CHOICE {
+ numeric NumericString (SIZE (1..ub-domain-name-length)),
+ printable PrintableString (SIZE (1..ub-domain-name-length)) }
+
+OrganizationName ::= PrintableString
+ (SIZE (1..ub-organization-name-length))
+-- see also teletex-organization-name
+
+NumericUserIdentifier ::= NumericString
+ (SIZE (1..ub-numeric-user-id-length))
+
+PersonalName ::= SET {
+ surname [0] PrintableString (SIZE (1..ub-surname-length)),
+ given-name [1] PrintableString
+ (SIZE (1..ub-given-name-length)) OPTIONAL,
+ initials [2] PrintableString (SIZE (1..ub-initials-length)) OPTIONAL,
+ generation-qualifier [3] PrintableString
+ (SIZE (1..ub-generation-qualifier-length)) OPTIONAL }
+-- see also teletex-personal-name
+
+OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
+ OF OrganizationalUnitName
+-- see also teletex-organizational-unit-names
+
+OrganizationalUnitName ::= PrintableString (SIZE
+ (1..ub-organizational-unit-name-length))
+
+-- Built-in Domain-defined Attributes
+
+BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE
+ (1..ub-domain-defined-attributes) OF
+ BuiltInDomainDefinedAttribute
+
+BuiltInDomainDefinedAttribute ::= SEQUENCE {
+ type PrintableString (SIZE
+ (1..ub-domain-defined-attribute-type-length)),
+ value PrintableString (SIZE
+ (1..ub-domain-defined-attribute-value-length))}
+
+-- Extension Attributes
+
+ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF
+ ExtensionAttribute
+
+ExtensionAttribute ::= SEQUENCE {
+ extension-attribute-type [0] EXPLICIT INTEGER (0..ub-extension-attributes),
+ extension-attribute-value [1] EXPLICIT
+ ANY DEFINED BY extension-attribute-type }
+
+-- Extension types and attribute values
+--
+
+common-name INTEGER ::= 1
+
+CommonName ::= PrintableString (SIZE (1..ub-common-name-length))
+
+teletex-common-name INTEGER ::= 2
+
+TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))
+
+teletex-organization-name INTEGER ::= 3
+
+TeletexOrganizationName ::=
+ TeletexString (SIZE (1..ub-organization-name-length))
+
+teletex-personal-name INTEGER ::= 4
+
+TeletexPersonalName ::= SET {
+ surname [0] EXPLICIT TeletexString (SIZE (1..ub-surname-length)),
+ given-name [1] EXPLICIT TeletexString
+ (SIZE (1..ub-given-name-length)) OPTIONAL,
+ initials [2] EXPLICIT TeletexString (SIZE (1..ub-initials-length)) OPTIONAL,
+ generation-qualifier [3] EXPLICIT TeletexString (SIZE
+ (1..ub-generation-qualifier-length)) OPTIONAL }
+
+teletex-organizational-unit-names INTEGER ::= 5
+
+TeletexOrganizationalUnitNames ::= SEQUENCE SIZE
+ (1..ub-organizational-units) OF TeletexOrganizationalUnitName
+
+TeletexOrganizationalUnitName ::= TeletexString
+ (SIZE (1..ub-organizational-unit-name-length))
+
+pds-name INTEGER ::= 7
+
+PDSName ::= PrintableString (SIZE (1..ub-pds-name-length))
+
+physical-delivery-country-name INTEGER ::= 8
+
+PhysicalDeliveryCountryName ::= CHOICE {
+ x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)),
+ iso-3166-alpha2-code PrintableString
+ (SIZE (ub-country-name-alpha-length)) }
+
+postal-code INTEGER ::= 9
+
+PostalCode ::= CHOICE {
+ numeric-code NumericString (SIZE (1..ub-postal-code-length)),
+ printable-code PrintableString (SIZE (1..ub-postal-code-length)) }
+
+physical-delivery-office-name INTEGER ::= 10
+
+PhysicalDeliveryOfficeName ::= PDSParameter
+
+physical-delivery-office-number INTEGER ::= 11
+
+PhysicalDeliveryOfficeNumber ::= PDSParameter
+
+extension-OR-address-components INTEGER ::= 12
+
+ExtensionORAddressComponents ::= PDSParameter
+
+physical-delivery-personal-name INTEGER ::= 13
+
+PhysicalDeliveryPersonalName ::= PDSParameter
+
+physical-delivery-organization-name INTEGER ::= 14
+
+PhysicalDeliveryOrganizationName ::= PDSParameter
+
+extension-physical-delivery-address-components INTEGER ::= 15
+
+ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter
+
+unformatted-postal-address INTEGER ::= 16
+
+UnformattedPostalAddress ::= SET {
+ printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines) OF
+ PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL,
+ teletex-string TeletexString
+ (SIZE (1..ub-unformatted-address-length)) OPTIONAL }
+
+street-address INTEGER ::= 17
+
+StreetAddress ::= PDSParameter
+
+post-office-box-address INTEGER ::= 18
+
+PostOfficeBoxAddress ::= PDSParameter
+
+poste-restante-address INTEGER ::= 19
+
+PosteRestanteAddress ::= PDSParameter
+
+unique-postal-name INTEGER ::= 20
+
+UniquePostalName ::= PDSParameter
+
+local-postal-attributes INTEGER ::= 21
+
+LocalPostalAttributes ::= PDSParameter
+
+PDSParameter ::= SET {
+ printable-string PrintableString
+ (SIZE(1..ub-pds-parameter-length)) OPTIONAL,
+ teletex-string TeletexString
+ (SIZE(1..ub-pds-parameter-length)) OPTIONAL }
+
+extended-network-address INTEGER ::= 22
+
+ExtendedNetworkAddress ::= CHOICE {
+ e163-4-address SEQUENCE {
+ number [0] EXPLICIT NumericString (SIZE (1..ub-e163-4-number-length)),
+ sub-address [1] EXPLICIT NumericString
+ (SIZE (1..ub-e163-4-sub-address-length)) OPTIONAL },
+ psap-address [0] EXPLICIT PresentationAddress }
+
+PresentationAddress ::= SEQUENCE {
+ pSelector [0] EXPLICIT OCTET STRING OPTIONAL,
+ sSelector [1] EXPLICIT OCTET STRING OPTIONAL,
+ tSelector [2] EXPLICIT OCTET STRING OPTIONAL,
+ nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING }
+
+terminal-type INTEGER ::= 23
+
+TerminalType ::= INTEGER {
+ telex (3),
+ teletex (4),
+ g3-facsimile (5),
+ g4-facsimile (6),
+ ia5-terminal (7),
+ videotex (8) } -- (0..ub-integer-options)
+
+-- Extension Domain-defined Attributes
+
+teletex-domain-defined-attributes INTEGER ::= 6
+
+TeletexDomainDefinedAttributes ::= SEQUENCE SIZE
+ (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute
+
+TeletexDomainDefinedAttribute ::= SEQUENCE {
+ type TeletexString
+ (SIZE (1..ub-domain-defined-attribute-type-length)),
+ value TeletexString
+ (SIZE (1..ub-domain-defined-attribute-value-length)) }
+
+-- specifications of Upper Bounds shall be regarded as mandatory
+-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
+-- Upper Bounds
+
+-- Upper Bounds
+ub-name INTEGER ::= 32768
+ub-common-name INTEGER ::= 64
+ub-locality-name INTEGER ::= 128
+ub-state-name INTEGER ::= 128
+ub-organization-name INTEGER ::= 64
+ub-organizational-unit-name INTEGER ::= 64
+ub-title INTEGER ::= 64
+ub-match INTEGER ::= 128
+
+ub-emailaddress-length INTEGER ::= 128
+
+ub-common-name-length INTEGER ::= 64
+ub-country-name-alpha-length INTEGER ::= 2
+ub-country-name-numeric-length INTEGER ::= 3
+ub-domain-defined-attributes INTEGER ::= 4
+ub-domain-defined-attribute-type-length INTEGER ::= 8
+ub-domain-defined-attribute-value-length INTEGER ::= 128
+ub-domain-name-length INTEGER ::= 16
+ub-extension-attributes INTEGER ::= 256
+ub-e163-4-number-length INTEGER ::= 15
+ub-e163-4-sub-address-length INTEGER ::= 40
+ub-generation-qualifier-length INTEGER ::= 3
+ub-given-name-length INTEGER ::= 16
+ub-initials-length INTEGER ::= 5
+ub-integer-options INTEGER ::= 256
+ub-numeric-user-id-length INTEGER ::= 32
+ub-organization-name-length INTEGER ::= 64
+ub-organizational-unit-name-length INTEGER ::= 32
+ub-organizational-units INTEGER ::= 4
+ub-pds-name-length INTEGER ::= 16
+ub-pds-parameter-length INTEGER ::= 30
+ub-pds-physical-address-lines INTEGER ::= 6
+ub-postal-code-length INTEGER ::= 16
+ub-surname-length INTEGER ::= 40
+ub-terminal-id-length INTEGER ::= 24
+ub-unformatted-address-length INTEGER ::= 180
+ub-x121-address-length INTEGER ::= 16
+
+-- Note - upper bounds on string types, such as TeletexString, are
+-- measured in characters. Excepting PrintableString or IA5String, a
+-- significantly greater number of octets will be required to hold
+-- such a value. As a minimum, 16 octets, or twice the specified upper
+-- bound, whichever is the larger, should be allowed for TeletexString.
+-- For UTF8String or UniversalString at least four times the upper
+-- bound should be allowed.
+
+
+
+-- END of PKIX1Implicit88
+
+
+-- BEGIN of RFC2630
+
+-- Cryptographic Message Syntax
+
+pkcs-7-ContentInfo ::= SEQUENCE {
+ contentType pkcs-7-ContentType,
+ content [0] EXPLICIT ANY DEFINED BY contentType }
+
+pkcs-7-DigestInfo ::= SEQUENCE {
+ digestAlgorithm pkcs-7-DigestAlgorithmIdentifier,
+ digest pkcs-7-Digest
+}
+
+pkcs-7-Digest ::= OCTET STRING
+
+pkcs-7-ContentType ::= OBJECT IDENTIFIER
+
+pkcs-7-SignedData ::= SEQUENCE {
+ version pkcs-7-CMSVersion,
+ digestAlgorithms pkcs-7-DigestAlgorithmIdentifiers,
+ encapContentInfo pkcs-7-EncapsulatedContentInfo,
+ certificates [0] IMPLICIT pkcs-7-CertificateSet OPTIONAL,
+ crls [1] IMPLICIT pkcs-7-CertificateRevocationLists OPTIONAL,
+ signerInfos pkcs-7-SignerInfos
+}
+
+pkcs-7-CMSVersion ::= INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) }
+
+pkcs-7-DigestAlgorithmIdentifiers ::= SET OF pkcs-7-DigestAlgorithmIdentifier
+
+pkcs-7-DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+
+pkcs-7-EncapsulatedContentInfo ::= SEQUENCE {
+ eContentType pkcs-7-ContentType,
+ eContent [0] EXPLICIT OCTET STRING OPTIONAL }
+
+-- We don't use CertificateList here since we only want
+-- to read the raw data.
+pkcs-7-CertificateRevocationLists ::= SET OF ANY
+
+pkcs-7-CertificateChoices ::= CHOICE {
+-- Although the paper uses Certificate type, we
+-- don't use it since, we don't need to parse it.
+-- We only need to read and store it.
+ certificate ANY
+}
+
+pkcs-7-CertificateSet ::= SET OF pkcs-7-CertificateChoices
+
+pkcs-7-SignerInfos ::= SET OF ANY -- this is not correct but we don't use it
+ -- anyway
+
+
+-- BEGIN of RFC2986
+
+-- Certificate requests
+pkcs-10-CertificationRequestInfo ::= SEQUENCE {
+ version INTEGER { v1(0) },
+ subject Name,
+ subjectPKInfo SubjectPublicKeyInfo,
+ attributes [0] Attributes
+}
+
+Attributes ::= SET OF Attribute
+
+pkcs-10-CertificationRequest ::= SEQUENCE {
+ certificationRequestInfo pkcs-10-CertificationRequestInfo,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING
+}
+
+-- stuff from PKCS#9
+
+pkcs-9-ub-challengePassword INTEGER ::= 255
+
+pkcs-9-certTypes OBJECT IDENTIFIER ::= {pkcs-9 22}
+pkcs-9-crlTypes OBJECT IDENTIFIER ::= {pkcs-9 23}
+
+pkcs-9-at-challengePassword OBJECT IDENTIFIER ::= {pkcs-9 7}
+
+pkcs-9-challengePassword ::= CHOICE {
+ printableString PrintableString (SIZE (1..pkcs-9-ub-challengePassword)),
+ utf8String UTF8String (SIZE (1..pkcs-9-ub-challengePassword)) }
+
+pkcs-9-at-localKeyId OBJECT IDENTIFIER ::= {pkcs-9 21}
+
+pkcs-9-localKeyId ::= OCTET STRING
+
+pkcs-9-at-friendlyName OBJECT IDENTIFIER ::= {pkcs-9 20}
+
+pkcs-9-friendlyName ::= BMPString (SIZE (1..255))
+
+-- PKCS #8 stuff
+
+-- Private-key information syntax
+
+pkcs-8-PrivateKeyInfo ::= SEQUENCE {
+ version pkcs-8-Version,
+ privateKeyAlgorithm AlgorithmIdentifier,
+ privateKey pkcs-8-PrivateKey,
+ attributes [0] Attributes OPTIONAL }
+
+pkcs-8-Version ::= INTEGER {v1(0)}
+
+pkcs-8-PrivateKey ::= OCTET STRING
+
+pkcs-8-Attributes ::= SET OF Attribute
+
+-- Encrypted private-key information syntax
+
+pkcs-8-EncryptedPrivateKeyInfo ::= SEQUENCE {
+ encryptionAlgorithm AlgorithmIdentifier,
+ encryptedData pkcs-8-EncryptedData
+}
+
+pkcs-8-EncryptedData ::= OCTET STRING
+
+-- PKCS #5 stuff
+
+pkcs-5 OBJECT IDENTIFIER ::=
+ { pkcs 5 }
+
+pkcs-5-encryptionAlgorithm OBJECT IDENTIFIER ::=
+ { iso(1) member-body(2) us(840) rsadsi(113549) 3 }
+
+pkcs-5-des-EDE3-CBC OBJECT IDENTIFIER ::= {pkcs-5-encryptionAlgorithm 7}
+
+pkcs-5-des-EDE3-CBC-params ::= OCTET STRING (SIZE(8))
+
+pkcs-5-des-CBC-params ::= OCTET STRING (SIZE(8))
+
+pkcs-5-rc2-CBC-params ::= SEQUENCE {
+ rc2ParameterVersion INTEGER OPTIONAL,
+ iv OCTET STRING (SIZE(8))
+}
+
+pkcs-5-PBE-params ::= SEQUENCE {
+ salt OCTET STRING (SIZE(8)),
+ iterationCount INTEGER
+}
+
+pkcs-5-id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13}
+
+pkcs-5-PBES2-params ::= SEQUENCE {
+ keyDerivationFunc AlgorithmIdentifier,
+ encryptionScheme AlgorithmIdentifier }
+
+-- PBKDF2
+
+pkcs-5-id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12}
+
+-- pkcs-5-id-hmacWithSHA1 OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) rsadsi(113549) 2 7}
+
+-- pkcs-5-algid-hmacWithSHA1 AlgorithmIdentifier ::=
+-- {algorithm pkcs-5-id-hmacWithSHA1, parameters NULL : NULL}
+
+pkcs-5-PBKDF2-params ::= SEQUENCE {
+ salt CHOICE {
+ specified OCTET STRING,
+ otherSource AlgorithmIdentifier
+ },
+ iterationCount INTEGER (1..MAX),
+ keyLength INTEGER (1..MAX) OPTIONAL,
+ prf AlgorithmIdentifier OPTIONAL -- DEFAULT pkcs-5-id-hmacWithSHA1
+}
+
+-- PKCS #12 stuff
+
+pkcs-12 OBJECT IDENTIFIER ::= {pkcs 12}
+
+pkcs-12-PFX ::= SEQUENCE {
+ version INTEGER {v3(3)},
+ authSafe pkcs-7-ContentInfo,
+ macData pkcs-12-MacData OPTIONAL
+}
+
+pkcs-12-PbeParams ::= SEQUENCE {
+ salt OCTET STRING,
+ iterations INTEGER
+}
+
+pkcs-12-MacData ::= SEQUENCE {
+ mac pkcs-7-DigestInfo,
+ macSalt OCTET STRING,
+ iterations INTEGER DEFAULT 1
+-- Note: The default is for historical reasons and its use is
+-- deprecated. A higher value, like 1024 is recommended.
+}
+
+pkcs-12-AuthenticatedSafe ::= SEQUENCE OF pkcs-7-ContentInfo
+ -- Data if unencrypted
+ -- EncryptedData if password-encrypted
+ -- EnvelopedData if public key-encrypted
+
+pkcs-12-SafeContents ::= SEQUENCE OF pkcs-12-SafeBag
+
+pkcs-12-SafeBag ::= SEQUENCE {
+ bagId OBJECT IDENTIFIER,
+ bagValue [0] EXPLICIT ANY DEFINED BY badId,
+ bagAttributes SET OF pkcs-12-PKCS12Attribute OPTIONAL
+}
+
+-- Bag types
+
+
+pkcs-12-bagtypes OBJECT IDENTIFIER ::= {pkcs-12 10 1}
+
+pkcs-12-keyBag OBJECT IDENTIFIER ::= {pkcs-12-bagtypes 1}
+pkcs-12-pkcs8ShroudedKeyBag OBJECT IDENTIFIER ::= {pkcs-12-bagtypes 2}
+pkcs-12-certBag OBJECT IDENTIFIER ::= {pkcs-12-bagtypes 3}
+pkcs-12-crlBag OBJECT IDENTIFIER ::= {pkcs-12-bagtypes 4}
+
+pkcs-12-KeyBag ::= pkcs-8-PrivateKeyInfo
+
+-- Shrouded KeyBag
+
+pkcs-12-PKCS8ShroudedKeyBag ::= pkcs-8-EncryptedPrivateKeyInfo
+
+-- CertBag
+
+pkcs-12-CertBag ::= SEQUENCE {
+ certId OBJECT IDENTIFIER,
+ certValue [0] EXPLICIT ANY DEFINED BY certId
+}
+
+-- x509Certificate BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {pkcs-9-certTypes 1}}
+-- DER-encoded X.509 certificate stored in OCTET STRING
+
+pkcs-12-CRLBag ::= SEQUENCE {
+ crlId OBJECT IDENTIFIER,
+ crlValue [0] EXPLICIT ANY DEFINED BY crlId
+}
+
+-- x509CRL BAG-TYPE ::=
+-- {OCTET STRING IDENTIFIED BY {pkcs-9-crlTypes 1}}
+-- DER-encoded X.509 CRL stored in OCTET STRING
+
+pkcs-12-PKCS12Attribute ::= Attribute
+
+-- PKCS #7 stuff (needed in PKCS 12)
+
+pkcs-7-data OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ us(840) rsadsi(113549) pkcs(1) pkcs7(7) 1 }
+
+pkcs-7-encryptedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ us(840) rsadsi(113549) pkcs(1) pkcs7(7) 6 }
+
+pkcs-7-Data ::= OCTET STRING
+
+pkcs-7-EncryptedData ::= SEQUENCE {
+ version pkcs-7-CMSVersion,
+ encryptedContentInfo pkcs-7-EncryptedContentInfo,
+ unprotectedAttrs [1] IMPLICIT pkcs-7-UnprotectedAttributes OPTIONAL }
+
+pkcs-7-EncryptedContentInfo ::= SEQUENCE {
+ contentType pkcs-7-ContentType,
+ contentEncryptionAlgorithm pkcs-7-ContentEncryptionAlgorithmIdentifier,
+ encryptedContent [0] IMPLICIT pkcs-7-EncryptedContent OPTIONAL }
+
+pkcs-7-ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+
+pkcs-7-EncryptedContent ::= OCTET STRING
+
+pkcs-7-UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute
+
+-- LDAP stuff
+-- may not be correct
+
+id-at-ldap-DC AttributeType ::= { 0 9 2342 19200300 100 1 25 }
+
+ldap-DC ::= IA5String
+
+id-at-ldap-UID AttributeType ::= { 0 9 2342 19200300 100 1 1 }
+
+ldap-UID ::= DirectoryString
+
+-- rfc3039
+
+id-pda OBJECT IDENTIFIER ::= { id-pkix 9 }
+
+id-pda-dateOfBirth AttributeType ::= { id-pda 1 }
+DateOfBirth ::= GeneralizedTime
+
+id-pda-placeOfBirth AttributeType ::= { id-pda 2 }
+PlaceOfBirth ::= DirectoryString
+
+id-pda-gender AttributeType ::= { id-pda 3 }
+Gender ::= PrintableString (SIZE(1))
+ -- "M", "F", "m" or "f"
+
+id-pda-countryOfCitizenship AttributeType ::= { id-pda 4 }
+CountryOfCitizenship ::= PrintableString (SIZE (2))
+ -- ISO 3166 Country Code
+
+id-pda-countryOfResidence AttributeType ::= { id-pda 5 }
+CountryOfResidence ::= PrintableString (SIZE (2))
+ -- ISO 3166 Country Code
+
+END
Modified: trunk/pkcs11/gck/temporary-test.c
==============================================================================
--- trunk/pkcs11/gck/temporary-test.c (original)
+++ trunk/pkcs11/gck/temporary-test.c Mon Dec 22 20:21:06 2008
@@ -1,6 +1,30 @@
#include "gck-crypto.h"
+
#include <stdlib.h>
+#include <pthread.h>
+
+#include "common/gkr-secure-memory.h"
+
+static pthread_mutex_t memory_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void
+gkr_memory_lock (void)
+{
+ pthread_mutex_lock (&memory_mutex);
+}
+
+void
+gkr_memory_unlock (void)
+{
+ pthread_mutex_unlock (&memory_mutex);
+}
+
+void*
+gkr_memory_fallback (void *p, unsigned long sz)
+{
+ return realloc (p, sz);
+}
int
main(int argc, char* argv[])
Added: trunk/pkcs11/gck/tests/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/tests/Makefile.am Mon Dec 22 20:21:06 2008
@@ -0,0 +1,26 @@
+
+BUILT_SOURCES = \
+ asn1-def-test.h
+
+asn1-def-test.h: test.asn
+ asn1Parser -o asn1-def-test.h test.asn
+
+UNIT_AUTO = \
+ unit-test-crypto.c \
+ unit-test-data-asn1.c \
+ unit-test-data-der.c \
+ unit-test-data-openssl.c \
+ unit-test-file-tracker.c \
+ $(BUILT_SOURCES)
+
+UNIT_PROMPT =
+
+UNIT_LIBS = \
+ $(top_builddir)/pkcs11/gck/libgck.la \
+ $(top_builddir)/common/libgkr-module-common.la
+
+EXTRA_DIST = \
+ test.asn \
+ test-data
+
+include $(top_srcdir)/tests/gtest.make
Added: trunk/pkcs11/gck/tests/test-data/pem-rsa-enc.key
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/tests/test-data/pem-rsa-enc.key Mon Dec 22 20:21:06 2008
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,24522D4CE5F5CD7B
+
+2H/8j0HYUya7LWEUxpgjp/LVcCX7yZB7SoREdoJdcqJEBUMWVxU/2OfVB8EZupmy
+7YHcnn5v1JwwtmAXAtqM9JGlvNWaRr1m4zDrhJn1fY3tu8YGtMR49IOZmOUBK+X+
+IxWAwaFDqLntuGZZnAmRJtgFVYVABEs5yM9zgoCGDaU4WMK3caD7Jnw8jH5m0nqQ
+XiQ1y1dHxFJmAgG0b5h2z7zjQTmmXd3IhXqSqsE/9ryruCCYa0Z7aAN5oAmO89I9
+gOyy3J4h76mTNFfF5btV4Jllwd4LkgGOmm69UxAyUTGzwYJ5gxgB3xFzGBwpVlcu
+72PrQCrjZqZ6rj6cTPGUYzcyMtEw3Xd6mFhApqJpVRZwNWUAMMJwHl2oWwKcIxfV
+y+OftRX6kc+cunrxCkl9aKuHDoJPEq+/Uh+AEXqir+942Vull0WPyuWUjaPKR1xJ
+poYsNfHRWq+klKCggQQL6jwuVbDLhbaXfgaNBQO1XMracgfmnO1PQPw8JSQ5iOkm
+Ybt2oHAEnrEWxZGn1PfRq6Z8HAbBlQpfmG7SMJZdQjlndKA6GR+tN5krKfpj6uak
+0eklm0Nb0YcDzJ3qqHXxIimK3Kh/WRZ1hVTnX4mS9u3HNQMo5Ov6z8OQN+Q45ffi
+ZDFkVwUTEJ+iwmCG7XnxX0v8Bv5LZmAnPu95KQTp4Ds0AZ6Sp+RqxvhnCO25cgWj
++N5jHGzsDk9/Jw7rAHz8pnl3sziNBWdAk5ASPA28HCQQo5peWnWajM3Pk98+/wHY
+blTh7gw77gTake6hpiegnhNUXwGm6BXEqmyu7mPW0z5XFRb9W7bpog==
+-----END RSA PRIVATE KEY-----
Added: trunk/pkcs11/gck/tests/test.asn
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/tests/test.asn Mon Dec 22 20:21:06 2008
@@ -0,0 +1,18 @@
+TEST { }
+
+DEFINITIONS EXPLICIT TAGS ::=
+
+BEGIN
+
+TestIntegers ::= SEQUENCE {
+ uint1 INTEGER,
+ uint2 INTEGER,
+ uint3 INTEGER,
+ mpi INTEGER
+}
+
+TestData ::= SEQUENCE {
+ data OCTET STRING
+}
+
+END
Added: trunk/pkcs11/gck/tests/unit-test-crypto.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/tests/unit-test-crypto.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,297 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-crypto.c: Test crypto stuff
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+
+#include "gck/gck-crypto.h"
+
+#include <gcrypt.h>
+
+DEFINE_SETUP(crypto_setup)
+{
+ gck_crypto_initialize ();
+}
+
+const static struct {
+ const gchar *password;
+ int cipher_algo;
+ int hash_algo;
+ int iterations;
+ const gchar *salt;
+
+ const gchar *result_simple;
+ const gchar *result_pkcs12;
+ const gchar *result_pbkdf2;
+ const gchar *result_pbe;
+} all_generation_tests[] = {
+
+ { /* 24 byte output */
+ "booo", GCRY_CIPHER_3DES, GCRY_MD_MD5, 1,
+ "\x70\x4C\xFF\xD6\x2F\xBA\x03\xE9",
+ "\x84\x12\xBB\x34\x94\x8C\x40\xAD\x97\x57\x96\x74\x5B\x6A\xFB\xF8\xD6\x61\x33\x51\xEA\x8C\xCF\xD8",
+ NULL,
+ NULL,
+ NULL
+ },
+
+ { /* 5 byte output */
+ "booo", GCRY_CIPHER_RFC2268_40, GCRY_MD_SHA1, 2048,
+ "\x8A\x58\xC2\xE8\x7C\x1D\x80\x11",
+ NULL,
+ "\xD6\xA6\xF0\x76\x66",
+ NULL,
+ NULL
+ },
+
+ { /* Null Password, 5 byte output */
+ NULL, GCRY_CIPHER_RFC2268_40, GCRY_MD_SHA1, 2000,
+ "\x04\xE0\x1C\x3E\xF8\xF2\xE9\xFD",
+ NULL,
+ "\x98\x7F\x20\x97\x1E",
+ NULL,
+ NULL
+ },
+
+ { /* 24 byte output */
+ "booo", GCRY_CIPHER_3DES, GCRY_MD_SHA1, 2048,
+ "\xBD\xEE\x0B\xC6\xCF\x43\xAC\x25",
+ NULL,
+ "\x3F\x38\x1B\x0E\x87\xEB\x19\xBE\xD1\x39\xDC\x5B\xC2\xD2\xB3\x3C\x35\xA8\xB8\xF9\xEE\x66\x48\x94",
+ "\x20\x25\x90\xD8\xD6\x98\x3E\x71\x10\x17\x1F\x51\x49\x87\x27\xCA\x97\x27\xD1\xC9\x72\xF8\x11\xBB",
+ NULL
+ },
+
+ { /* Empty password, 24 byte output */
+ "", GCRY_CIPHER_3DES, GCRY_MD_SHA1, 2048,
+ "\xF7\xCF\xD9\xCF\x1F\xF3\xAD\xF6",
+ NULL,
+ NULL,
+ "\x53\xE3\x35\x9E\x5D\xC1\x85\x1A\x71\x3A\x67\x4E\x80\x56\x13\xD6\x4E\x3E\x89\x43\xB7\x1D\x5F\x7F",
+ NULL
+ },
+
+ { /* Empty password, 24 byte output */
+ "", GCRY_CIPHER_3DES, GCRY_MD_SHA1, 2048,
+ "\xD9\xB3\x2E\xC7\xBA\x1A\x8E\x15",
+ NULL,
+ "\x39\x70\x75\x7C\xF5\xE2\x13\x0B\x5D\xC2\x9D\x96\x8B\x71\xC7\xFC\x5B\x97\x1F\x79\x9F\x06\xFC\xA2",
+ NULL,
+ NULL
+ },
+
+ { /* 8 byte output */
+ "booo", GCRY_CIPHER_DES, GCRY_MD_MD5, 2048,
+ "\x93\x4C\x3D\x29\xA2\x42\xB0\xF5",
+ NULL,
+ NULL,
+ NULL,
+ "\x8C\x67\x19\x7F\xB9\x23\xE2\x8D"
+ }
+};
+
+#define N_GENERATION_TESTS (sizeof (all_generation_tests) / sizeof (all_generation_tests[0]))
+
+DEFINE_TEST(generate_key_simple)
+{
+ int i;
+ gboolean ret;
+ guchar *key;
+
+ for (i = 0; i < N_GENERATION_TESTS; ++i) {
+
+ if (!all_generation_tests[i].result_simple)
+ continue;
+
+ ret = gck_crypto_symkey_generate_simple (all_generation_tests[i].cipher_algo,
+ all_generation_tests[i].hash_algo,
+ all_generation_tests[i].password,
+ (guchar*)all_generation_tests[i].salt, 8,
+ all_generation_tests[i].iterations,
+ &key, NULL);
+ g_assert (ret && "key generation failed");
+
+ ret = (memcmp (key, all_generation_tests[i].result_simple,
+ gcry_cipher_get_algo_keylen (all_generation_tests[i].cipher_algo)) == 0);
+
+ g_assert (ret && "invalid simple key generated");
+ }
+}
+
+DEFINE_TEST(generate_key_pkcs12)
+{
+ int i;
+ gboolean ret;
+ guchar *key;
+
+ for (i = 0; i < N_GENERATION_TESTS; ++i) {
+
+ if (!all_generation_tests[i].result_pkcs12)
+ continue;
+
+ ret = gck_crypto_symkey_generate_pkcs12 (all_generation_tests[i].cipher_algo,
+ all_generation_tests[i].hash_algo,
+ all_generation_tests[i].password,
+ (guchar*)all_generation_tests[i].salt, 8,
+ all_generation_tests[i].iterations,
+ &key, NULL);
+ g_assert ("failed to generate pkcs12 key" && ret);
+
+ ret = (memcmp (key, all_generation_tests[i].result_pkcs12,
+ gcry_cipher_get_algo_keylen (all_generation_tests[i].cipher_algo)) == 0);
+
+ g_assert ("invalid pkcs12 key generated" && ret);
+ }
+}
+
+DEFINE_TEST(generate_key_pbkdf2)
+{
+ int i;
+ gboolean ret;
+ guchar *key;
+
+ for (i = 0; i < N_GENERATION_TESTS; ++i) {
+
+ if (!all_generation_tests[i].result_pbkdf2)
+ continue;
+
+ ret = gck_crypto_symkey_generate_pbkdf2 (all_generation_tests[i].cipher_algo,
+ all_generation_tests[i].hash_algo,
+ all_generation_tests[i].password,
+ (guchar*)all_generation_tests[i].salt, 8,
+ all_generation_tests[i].iterations,
+ &key, NULL);
+ g_assert ("failed to generate pbkdf2 key" && ret);
+
+ ret = (memcmp (key, all_generation_tests[i].result_pbkdf2,
+ gcry_cipher_get_algo_keylen (all_generation_tests[i].cipher_algo)) == 0);
+
+ g_assert ("invalid pbkdf2 key generated" && ret);
+ }
+}
+
+DEFINE_TEST(generate_key_pbe)
+{
+ int i;
+ gboolean ret;
+ guchar *key;
+
+ for (i = 0; i < N_GENERATION_TESTS; ++i) {
+
+ if (!all_generation_tests[i].result_pbe)
+ continue;
+
+ ret = gck_crypto_symkey_generate_pbe (all_generation_tests[i].cipher_algo,
+ all_generation_tests[i].hash_algo,
+ all_generation_tests[i].password,
+ (guchar*)all_generation_tests[i].salt, 8,
+ all_generation_tests[i].iterations,
+ &key, NULL);
+ g_assert ("failed to generate pbe key" && ret);
+
+ ret = (memcmp (key, all_generation_tests[i].result_pbe,
+ gcry_cipher_get_algo_keylen (all_generation_tests[i].cipher_algo)) == 0);
+
+ g_assert ("invalid pbe key generated" && ret);
+
+ }
+}
+
+#if 0
+#define TEST_KEY \
+"(private-key (rsa " \
+"(n #00B78758D55EBFFAB61D07D0DC49B5309A6F1DA2AE51C275DFC2370959BB81AC0C39093B1C618E396161A0DECEB8768D0FFB14F197B96C3DA14190EE0F20D51315#)" \
+"(e #010001#)" \
+"(d #108BCAC5FDD35812981E6EC5957D98E2AB76E4064C47B861D27C2CC322C50792313C852B4164A035B42D261F1A09F9FFE8F477F9F78FF2EABBDA6BA875C671D7#)" \
+"(p #00C357F11B19A18C66573D25D1E466D9AB8BCDDCDFE0B2E80BD46712C4BEC18EB7#)" \
+"(q #00F0843B90A60EF7034CA4BE80414ED9497CABCC685143B388013FF989CBB0E093#)" \
+"(u #12F2555F52EB56329A991CF0404B51C68AC921AD370A797860F550415FF987BD#)" \
+"))"
+
+gcry_sexp_t thekey = NULL;
+
+void unit_test_parse_key (CuTest *cu)
+{
+ gcry_sexp_t sexp = NULL;
+ gcry_error_t gcry;
+ gcry_mpi_t mpi = NULL;
+ gboolean ret;
+ gboolean is_priv = FALSE;
+ int algorithm = 0;
+
+ gcry = gcry_sexp_new (&sexp, TEST_KEY, strlen (TEST_KEY), 1);
+ g_return_if_fail (gcry == 0);
+
+ /* Get the private key out */
+ thekey = gkr_crypto_sexp_get_child (sexp, "private-key", NULL);
+ CuAssert (cu, "couldn't extract private key", sexp != NULL);
+
+ ret = gkr_crypto_skey_parse (thekey, &algorithm, &is_priv, &sexp);
+ CuAssert (cu, "couldn't parse rsa key", ret);
+ CuAssert (cu, "parsed bad algorithm", algorithm == GCRY_PK_RSA);
+ CuAssert (cu, "not a private-key", is_priv == TRUE);
+ CuAssert (cu, "didn't get numbers", sexp != NULL);
+
+ ret = gkr_crypto_sexp_extract_mpi (sexp, &mpi, "p", NULL);
+ CuAssert (cu, "couldn't extract mpi from key", ret);
+ CuAssert (cu, "no mpi returned from extract", mpi != NULL);
+}
+
+void unit_test_make_keyid (CuTest *cu)
+{
+ guchar hash[20];
+ gkrid id;
+ const guchar *p;
+ gsize n;
+
+ p = gcry_pk_get_keygrip (thekey, hash);
+ g_return_if_fail (p == hash);
+
+ id = gkr_crypto_skey_make_id (thekey);
+ CuAssert (cu, "null returned as key id", id != NULL);
+
+ p = gkr_id_get_raw (id, &n);
+ CuAssert (cu, "key id is of wrong length", n == sizeof (hash));
+ CuAssert (cu, "key grip doesn't match key id", memcmp (hash, p, n) == 0);
+}
+
+void unit_test_key_to_public (CuTest *cu)
+{
+ gcry_sexp_t pubkey = NULL;
+ gboolean ret;
+ gkrid u1, u2;
+
+ ret = gkr_crypto_skey_private_to_public (thekey, &pubkey);
+ CuAssert (cu, "couldn't make public key", ret);
+ CuAssert (cu, "returned null public key", pubkey != NULL);
+
+ u1 = gkr_crypto_skey_make_id (thekey);
+ u2 = gkr_crypto_skey_make_id (pubkey);
+ CuAssert (cu, "public and private keys are not equivalent",
+ gkr_id_equals (u1, u2));
+}
+
+#endif
Added: trunk/pkcs11/gck/tests/unit-test-data-asn1.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/tests/unit-test-data-asn1.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,251 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-pkix-parser.c: Test PKIX parser
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+
+#include "gck/gck-data-asn1.h"
+
+#include <glib.h>
+#include <gcrypt.h>
+#include <libtasn1.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define extern
+#include "asn1-def-test.h"
+#undef extern
+
+ASN1_TYPE asn1_test = NULL;
+
+DEFINE_SETUP(asn1_tree)
+{
+ int res = asn1_array2tree (test_asn1_tab, &asn1_test, NULL);
+ g_assert (res == ASN1_SUCCESS);
+}
+
+DEFINE_TEARDOWN(asn1_tree)
+{
+ asn1_delete_structure (&asn1_test);
+}
+
+DEFINE_TEST(asn1_types)
+{
+ ASN1_TYPE asn;
+
+ asn = gck_data_asn1_get_pk_asn1type ();
+ g_assert ("pk asn type is null" && asn != NULL);
+
+ asn = gck_data_asn1_get_pkix_asn1type ();
+ g_assert ("pkix asn type is null" && asn != NULL);
+}
+
+DEFINE_TEST(asn1_integers)
+{
+ ASN1_TYPE asn;
+ gcry_mpi_t mpi, mpt;
+ guchar *data;
+ gsize n_data;
+ gboolean ret;
+ guint val;
+ int res;
+
+ res = asn1_create_element (asn1_test, "TEST.TestIntegers", &asn);
+ g_assert ("asn test structure is null" && asn != NULL);
+
+ ret = gck_data_asn1_write_uint (asn, "uint1", 35);
+ g_assert ("couldn't write integer" && ret);
+
+ ret = gck_data_asn1_write_uint (asn, "uint2", 23456);
+ g_assert ("couldn't write integer" && ret);
+
+ ret = gck_data_asn1_write_uint (asn, "uint3", 209384022);
+ g_assert ("couldn't write integer" && ret);
+
+ /* Make a random number */
+ mpi = gcry_mpi_new (512);
+ g_return_if_fail (mpi);
+ gcry_mpi_randomize (mpi, 512, GCRY_WEAK_RANDOM);
+
+ /* Write the mpi out */
+ ret = gck_data_asn1_write_mpi (asn, "mpi", mpi);
+
+ /* Now encode the whole caboodle */
+ data = gck_data_asn1_encode (asn, "", &n_data, NULL);
+ g_assert ("encoding asn1 didn't work" && data != NULL);
+
+ asn1_delete_structure (&asn);
+
+ /* Now decode it all nicely */
+ res = asn1_create_element (asn1_test, "TEST.TestIntegers", &asn);
+ g_return_if_fail (res == ASN1_SUCCESS);
+
+ res = asn1_der_decoding (&asn, data, n_data, NULL);
+ g_assert ("decoding asn didn't work" && res == ASN1_SUCCESS);
+
+ /* And get out the values */
+ ret = gck_data_asn1_read_uint (asn, "uint1", &val);
+ g_assert ("couldn't read integer from asn1" && ret);
+ g_assert_cmpuint (val, ==, 35);
+
+ ret = gck_data_asn1_read_uint (asn, "uint2", &val);
+ g_assert ("couldn't read integer from asn1" && ret);
+ g_assert_cmpuint (val, ==, 23456);
+
+ ret = gck_data_asn1_read_uint (asn, "uint3", &val);
+ g_assert ("couldn't read integer from asn1" && ret);
+ g_assert_cmpuint (val, ==, 209384022);
+
+ ret = gck_data_asn1_read_mpi (asn, "mpi", &mpt);
+ g_assert ("couldn't read mpi from asn1" && ret);
+ g_assert ("mpi returned is null" && mpt != NULL);
+ g_assert ("mpi is wrong number" && gcry_mpi_cmp (mpi, mpt) == 0);
+}
+
+DEFINE_TEST(write_value)
+{
+ ASN1_TYPE asn = NULL;
+ guchar *data;
+ gsize n_data;
+ int res;
+
+ res = asn1_create_element (asn1_test, "TEST.TestData", &asn);
+ g_assert ("asn test structure is null" && asn != NULL);
+
+ if (!gck_data_asn1_write_value (asn, "data", (const guchar*)"SOME DATA", 9))
+ g_assert_not_reached ();
+
+ data = gck_data_asn1_read_value (asn, "data", &n_data, NULL);
+ g_assert (data != NULL);
+ g_assert_cmpuint (n_data, ==, 9);
+ g_assert (memcmp (data, "SOME DATA", 9) == 0);
+ g_free (data);
+
+ asn1_delete_structure (&asn);
+}
+
+DEFINE_TEST(element_length_content)
+{
+ ASN1_TYPE asn = NULL;
+ guchar buffer[1024];
+ const guchar *content;
+ gsize n_content;
+ gint length;
+ int res;
+
+ res = asn1_create_element (asn1_test, "TEST.TestData", &asn);
+ g_assert ("asn test structure is null" && asn != NULL);
+
+ res = asn1_write_value (asn, "data", "SOME DATA", 9);
+ g_assert (res == ASN1_SUCCESS);
+
+ length = 1024;
+ res = asn1_der_coding (asn, "", buffer, &length, NULL);
+ g_assert (res == ASN1_SUCCESS);
+
+ /* Now the real test */
+ length = gck_data_asn1_element_length (buffer, 1024);
+ g_assert_cmpint (length, ==, 13);
+
+ content = gck_data_asn1_element_content (buffer, length, &n_content);
+ g_assert (content);
+ g_assert_cmpuint (n_content, ==, 11);
+
+ content = gck_data_asn1_element_content (content, n_content, &n_content);
+ g_assert (content);
+ g_assert_cmpuint (n_content, ==, 9);
+ g_assert (memcmp (content, "SOME DATA", 9) == 0);
+}
+
+typedef struct _TimeTestData {
+ gchar *value;
+ time_t ref;
+} TimeTestData;
+
+static const TimeTestData generalized_time_test_data[] = {
+ { "20070725130528Z", 1185368728 },
+ { "20070725130528.2134Z", 1185368728 },
+ { "20070725140528-0100", 1185368728 },
+ { "20070725040528+0900", 1185368728 },
+ { "20070725013528+1130", 1185368728 },
+ { "20070725Z", 1185321600 },
+ { "20070725+0000", 1185321600 },
+ { NULL, 0 }
+};
+
+static const TimeTestData utc_time_test_data[] = {
+ /* Test the Y2K style wrap arounds */
+ { "070725130528Z", 1185368728 }, /* The year 2007 */
+ { "020725130528Z", 1027602328 }, /* The year 2002 */
+ { "970725130528Z", 869835928 }, /* The year 1997 */
+ { "370725130528Z", 2132139928 }, /* The year 2037 */
+
+ /* Test the time zones and other formats */
+ { "070725130528.2134Z", 1185368728 },
+ { "070725140528-0100", 1185368728 },
+ { "070725040528+0900", 1185368728 },
+ { "070725013528+1130", 1185368728 },
+ { "070725Z", 1185321600 },
+ { "070725+0000", 1185321600 },
+
+ { NULL, 0 }
+};
+
+DEFINE_TEST(general_time)
+{
+ time_t when;
+ const TimeTestData *data;
+
+ for (data = generalized_time_test_data; data->value; ++data) {
+ when = gck_data_asn1_parse_general_time (data->value);
+ if (data->ref != when) {
+ printf ("%s", data->value);
+ printf ("%s != ", ctime (&when));
+ printf ("%s\n", ctime (&data->ref));
+ fflush (stdout);
+ }
+
+ g_assert ("decoded time doesn't match reference" && data->ref == when);
+ }
+}
+
+DEFINE_TEST(utc_time)
+{
+ time_t when;
+ const TimeTestData *data;
+
+ for (data = utc_time_test_data; data->value; ++data) {
+ when = gck_data_asn1_parse_utc_time (data->value);
+ if (data->ref != when) {
+ printf ("%s", data->value);
+ printf ("%s != ", ctime (&when));
+ printf ("%s\n", ctime (&data->ref));
+ fflush (stdout);
+ }
+
+ g_assert ("decoded time doesn't match reference" && data->ref == when);
+ }
+}
Added: trunk/pkcs11/gck/tests/unit-test-data-der.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/tests/unit-test-data-der.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,190 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-pkix-parser.c: Test PKIX parser
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+
+#include "gck/gck-crypto.h"
+#include "gck/gck-data-der.h"
+
+#include <glib.h>
+#include <gcrypt.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+const gchar *rsapub = "(public-key (rsa" \
+" (n #00AE4B381CF43F7DC24CF90827325E2FB2EB57EDDE29562DF391C8942AA8E6423410E2D3FE26381F9DE0395E74BF2D17621AE46992C72CF895F6FA5FBE98054FBF#)" \
+" (e #010001#)))";
+
+const gchar *rsaprv = "(private-key (rsa" \
+" (n #00B78758D55EBFFAB61D07D0DC49B5309A6F1DA2AE51C275DFC2370959BB81AC0C39093B1C618E396161A0DECEB8768D0FFB14F197B96C3DA14190EE0F20D51315#)" \
+" (e #010001#)" \
+" (d #108BCAC5FDD35812981E6EC5957D98E2AB76E4064C47B861D27C2CC322C50792313C852B4164A035B42D261F1A09F9FFE8F477F9F78FF2EABBDA6BA875C671D7#)" \
+" (p #00C357F11B19A18C66573D25D1E466D9AB8BCDDCDFE0B2E80BD46712C4BEC18EB7#)" \
+" (q #00F0843B90A60EF7034CA4BE80414ED9497CABCC685143B388013FF989CBB0E093#)" \
+" (u #12F2555F52EB56329A991CF0404B51C68AC921AD370A797860F550415FF987BD#)))";
+
+const gchar *dsapub = "(public-key (dsa" \
+" (p #0090EC0B60735839C754EAF8F64BB03FC35398D69772BFAE540079DEA2D3A61FAFFB27630A038A01A3D0CD62A10745A574A27ECB462F4F0885B79C61BBE954A60A29668AD54BBA5C07A72FD8B1105249670B339DF2C59E64A47064EFCF0B7236C5C72CD55CEB32917430BEC9A003D4E484FBAA84D79571B38D6B5AC95BB73E3F7B#)" \
+" (q #00FA214A1385C21BFEBAADAB240A2430C607D56271#)" \
+" (g #2DE05751F5DAEE97F3D43C54595A3E94A080728F0C66C98AEBED5762F6AB155802D8359EAD1DE1EC36A459FBEEEA48E59B9E6A8CB4F5295936B3CC881A5D957C7339175E2CFFE0F30D3711E430DB6648C2EB474AA10A4A3297450531FF2C7C6951220C9D446B6B6B0F00262E1EBEB3CC861476AA518CC555C9ABF9E5F39023FC#)" \
+" (y #54734451DB79D4EEDF0BBCEBD43BB6CBB7B8584603B957080075DD318EB5B0266D4B20DC5EFF376BDFC4EA2983B1F7F02A39ED4C619ED68712729FFF3B7C696ADD1B6D748F56A4B4BEC5C4385E528423A3B88AE65E6D5500F97839E7A486255982189C3B4FA8D94338C76F0E5CAFC9A30A1ED728BB9F2091D594E3250A09EA00#)))";
+
+const gchar *dsaprv = "(private-key (dsa" \
+" (p #0090EC0B60735839C754EAF8F64BB03FC35398D69772BFAE540079DEA2D3A61FAFFB27630A038A01A3D0CD62A10745A574A27ECB462F4F0885B79C61BBE954A60A29668AD54BBA5C07A72FD8B1105249670B339DF2C59E64A47064EFCF0B7236C5C72CD55CEB32917430BEC9A003D4E484FBAA84D79571B38D6B5AC95BB73E3F7B#)" \
+" (q #00FA214A1385C21BFEBAADAB240A2430C607D56271#)" \
+" (g #2DE05751F5DAEE97F3D43C54595A3E94A080728F0C66C98AEBED5762F6AB155802D8359EAD1DE1EC36A459FBEEEA48E59B9E6A8CB4F5295936B3CC881A5D957C7339175E2CFFE0F30D3711E430DB6648C2EB474AA10A4A3297450531FF2C7C6951220C9D446B6B6B0F00262E1EBEB3CC861476AA518CC555C9ABF9E5F39023FC#)" \
+" (y #54734451DB79D4EEDF0BBCEBD43BB6CBB7B8584603B957080075DD318EB5B0266D4B20DC5EFF376BDFC4EA2983B1F7F02A39ED4C619ED68712729FFF3B7C696ADD1B6D748F56A4B4BEC5C4385E528423A3B88AE65E6D5500F97839E7A486255982189C3B4FA8D94338C76F0E5CAFC9A30A1ED728BB9F2091D594E3250A09EA00#)" \
+" (x #00876F84F709D51108DFB0CBFA1F1C569C09C413EC#)))";
+
+static gboolean
+compare_keys (gcry_sexp_t key, gcry_sexp_t sexp)
+{
+ guchar hash1[20], hash2[20];
+ guchar *p;
+
+ /* Now compare them */
+ p = gcry_pk_get_keygrip (key, hash1);
+ g_assert ("couldn't get key id for private key" && p == hash1);
+ p = gcry_pk_get_keygrip (key, hash2);
+ g_assert ("couldn't get key id for parsed private key" && p == hash2);
+
+ return memcmp (hash1, hash2, 20) == 0;
+}
+
+static void
+test_der_public (gcry_sexp_t key)
+{
+ guchar *data;
+ gsize n_data;
+ GckDataResult ret;
+ gcry_sexp_t sexp;
+
+ /* Encode it */
+ data = gck_data_der_write_public_key (key, &n_data);
+ g_assert ("couldn't encode public key" && data != NULL);
+ g_assert ("encoding is empty" && n_data > 0);
+
+ /* Now parse it */
+ ret = gck_data_der_read_public_key (data, n_data, &sexp);
+ g_assert ("couldn't decode public key" && ret == GCK_DATA_SUCCESS);
+ g_assert ("parsed key is empty" && sexp != NULL);
+
+ /* Now compare them */
+ g_assert ("key parsed differently" && compare_keys (key, sexp));
+}
+
+DEFINE_TEST(der_rsa_public)
+{
+ gcry_sexp_t key;
+ gcry_error_t gcry;
+
+ gcry = gcry_sexp_sscan (&key, NULL, rsapub, strlen (rsapub));
+ g_return_if_fail (gcry == 0);
+
+ test_der_public (key);
+}
+
+DEFINE_TEST(der_dsa_public)
+{
+ gcry_sexp_t key;
+ gcry_error_t gcry;
+
+ gcry = gcry_sexp_sscan (&key, NULL, dsapub, strlen (dsapub));
+ g_return_if_fail (gcry == 0);
+
+ test_der_public (key);
+}
+
+static void
+test_der_private (gcry_sexp_t key)
+{
+ guchar *data;
+ gsize n_data;
+ GckDataResult ret;
+ gcry_sexp_t sexp;
+
+ /* Encode it */
+ data = gck_data_der_write_private_key (key, &n_data);
+ g_assert ("couldn't encode private key" && data != NULL);
+ g_assert ("encoding is empty" && n_data > 0);
+
+ /* Now parse it */
+ ret = gck_data_der_read_private_key (data, n_data, &sexp);
+ g_assert ("couldn't decode private key" && ret == GCK_DATA_SUCCESS);
+ g_assert ("parsed key is empty" && sexp != NULL);
+
+ /* Now compare them */
+ g_assert ("key parsed differently" && compare_keys (key, sexp));
+}
+
+DEFINE_TEST(der_rsa_private)
+{
+ gcry_sexp_t key;
+ gcry_error_t gcry;
+
+ gcry = gcry_sexp_sscan (&key, NULL, rsaprv, strlen (rsaprv));
+ g_return_if_fail (gcry == 0);
+
+ test_der_private (key);
+}
+
+DEFINE_TEST(der_dsa_private)
+{
+ gcry_sexp_t key;
+ gcry_error_t gcry;
+
+ gcry = gcry_sexp_sscan (&key, NULL, dsaprv, strlen (dsaprv));
+ g_return_if_fail (gcry == 0);
+
+ test_der_private (key);
+}
+
+DEFINE_TEST(der_dsa_private_parts)
+{
+ guchar *params, *key;
+ gsize n_params, n_key;
+ gcry_sexp_t skey, pkey;
+ gcry_error_t gcry;
+ GckDataResult result;
+
+ gcry = gcry_sexp_sscan (&skey, NULL, dsaprv, strlen (dsaprv));
+ g_return_if_fail (gcry == 0);
+
+ /* Encode the the dsa key by parts */
+ params = gck_data_der_write_private_key_dsa_params (skey, &n_params);
+ g_assert ("didn't encode dsa params" && params != NULL);
+ key = gck_data_der_write_private_key_dsa_part (skey, &n_key);
+ g_assert ("didn't encode dsa key" && key != NULL);
+
+ /* Parse the dsa key by parts */
+ result = gck_data_der_read_private_key_dsa_parts (key, n_key, params, n_params, &pkey);
+ g_assert ("couldn't parse dsa parts" && result == GCK_DATA_SUCCESS);
+ g_assert ("parsing dsa parts resulted in null key" && pkey != NULL);
+
+ /* Now compare them */
+ g_assert ("key parsed differently" && compare_keys (skey, pkey));
+}
Added: trunk/pkcs11/gck/tests/unit-test-data-openssl.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/tests/unit-test-data-openssl.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,153 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-pkix-openssl.c: Test PKIX openssl
+
+ Copyright (C) 2008 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+
+#include "common/gkr-secure-memory.h"
+
+#include "gck/gck-crypto.h"
+#include "gck/gck-data-pem.h"
+#include "gck/gck-data-openssl.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static void
+read_file (const gchar *filename, guchar **contents, gsize *len)
+{
+ gchar *path;
+ gboolean ret;
+
+ path = g_build_filename (g_get_current_dir (), "test-data", filename, NULL);
+ ret = g_file_get_contents (path, (gchar**)contents, len, NULL);
+ g_assert ("couldn't read in file" && ret);
+
+ g_free (path);
+}
+
+guchar *refenc = NULL;
+guchar *refdata = NULL;
+gsize n_refenc = 0;
+gsize n_refdata = 0;
+GHashTable *refheaders = NULL;
+
+static void
+copy_each_key_value (gpointer key, gpointer value, gpointer user_data)
+{
+ g_hash_table_insert ((GHashTable*)user_data, g_strdup ((gchar*)key), g_strdup ((gchar*)value));
+}
+
+static void
+parse_reference (GQuark type, const guchar *data, gsize n_data,
+ GHashTable *headers, gpointer user_data)
+{
+ GckDataResult res;
+ const gchar *dekinfo;
+
+ g_assert ("no data in PEM callback" && data != NULL);
+ g_assert ("no data in PEM callback" && n_data > 0);
+ refenc = g_memdup (data, n_data);
+ n_refenc = n_data;
+
+ g_assert ("no headers present in file" && headers != NULL);
+ refheaders = gck_data_pem_headers_new ();
+ g_hash_table_foreach (headers, copy_each_key_value, refheaders);
+ dekinfo = gck_data_openssl_get_dekinfo (headers);
+ g_assert ("no dekinfo in headers" && dekinfo != NULL);
+
+ res = gck_data_openssl_decrypt_block (dekinfo, "booo", data, n_data, &refdata, &n_refdata);
+ g_assert ("couldn't openssl decrypt block" && res == GCK_DATA_SUCCESS);
+ g_assert ("no data returned from openssl decrypt" && refdata != NULL);
+ g_assert ("invalid amount of data returned from openssl decrypt" && n_refdata == n_data);
+}
+
+DEFINE_TEST(parse_reference)
+{
+ guchar *input;
+ gsize n_input;
+ guint num;
+
+ read_file ("pem-rsa-enc.key", &input, &n_input);
+
+ num = gck_data_pem_parse (input, n_input, parse_reference, NULL);
+ g_assert ("couldn't PEM block in reference data" && num == 1);
+
+ g_assert ("parse_reference() wasn't called" && refdata != NULL);
+}
+
+DEFINE_TEST(write_reference)
+{
+ const gchar *dekinfo;
+ guchar *encrypted;
+ gsize n_encrypted;
+ gboolean ret;
+
+ dekinfo = gck_data_openssl_get_dekinfo (refheaders);
+ g_assert ("no dekinfo in headers" && dekinfo != NULL);
+
+ ret = gck_data_openssl_encrypt_block (dekinfo, "booo", refdata, n_refdata, &encrypted, &n_encrypted);
+ g_assert ("couldn't openssl encrypt block" && ret == TRUE);
+ g_assert ("no data returned from openssl encrypt" && encrypted != NULL);
+ g_assert ("invalid amount of data returned from openssl encrypt" && n_refdata <= n_encrypted);
+
+ g_assert ("data length doesn't match input length" && n_encrypted == n_refenc);
+ g_assert ("data doesn't match input" && memcmp (encrypted, refenc, n_encrypted) == 0);
+}
+
+/* 29 bytes (prime number, so block length has bad chance of matching */
+const static guchar *TEST_DATA = (guchar*)"ABCDEFGHIJKLMNOPQRSTUVWXYZ123";
+const gsize TEST_DATA_L = 29;
+
+DEFINE_TEST(openssl_roundtrip)
+{
+ const gchar *dekinfo;
+ GckDataResult res;
+ gboolean ret;
+ guchar *encrypted, *decrypted;
+ gsize n_encrypted, n_decrypted;
+ int i;
+
+ dekinfo = gck_data_openssl_prep_dekinfo (refheaders);
+
+ ret = gck_data_openssl_encrypt_block (dekinfo, "password", TEST_DATA, TEST_DATA_L, &encrypted, &n_encrypted);
+ g_assert ("couldn't openssl encrypt block" && ret == TRUE);
+ g_assert ("no data returned from openssl encrypt" && encrypted != NULL);
+ g_assert ("invalid amount of data returned from openssl encrypt" && TEST_DATA_L <= n_encrypted);
+
+ res = gck_data_openssl_decrypt_block (dekinfo, "password", encrypted, n_encrypted, &decrypted, &n_decrypted);
+ g_assert ("couldn't openssl decrypt block" && res == GCK_DATA_SUCCESS);
+ g_assert ("no data returned from openssl decrypt" && decrypted != NULL);
+
+ /* Check that the data was decrypted properly */
+ g_assert ("decrypted data doesn't match length" && n_decrypted >= TEST_DATA_L);
+ g_assert ("decrypted data doesn't match" && memcmp (TEST_DATA, decrypted, TEST_DATA_L) == 0);
+
+ /* Check that the remainder is all zeros */
+ for (i = TEST_DATA_L; i < n_decrypted; ++i)
+ g_assert ("non null byte in padding" && decrypted[i] == 0);
+}
Added: trunk/pkcs11/gck/tests/unit-test-file-tracker.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/tests/unit-test-file-tracker.c Mon Dec 22 20:21:06 2008
@@ -0,0 +1,221 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-location.c: Test location functionality
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "run-auto-test.h"
+
+#include "gck/gck-file-tracker.h"
+
+#include <glib/gstdio.h>
+
+#define DATA "test-data"
+#define SUBDIR "test-subdir"
+#define WILDCARD "*.woo?"
+
+static GckFileTracker *the_tracker = NULL;
+static gchar *test_dir = NULL;
+static gchar *test_file = NULL;
+
+static guint n_files_added = 0;
+static gchar* last_file_added = 0;
+
+static guint n_files_changed = 0;
+static gchar* last_file_changed = 0;
+
+static guint n_files_removed = 0;
+static gchar* last_file_removed = 0;
+
+static void
+file_added (GckFileTracker *tracker, const gchar *path, gpointer unused)
+{
+ g_assert ("should be a non-null path" && path != NULL);
+
+ ++n_files_added;
+ g_free (last_file_added);
+ last_file_added = g_strdup (path);
+}
+
+static void
+file_changed (GckFileTracker *tracker, const gchar *path, gpointer unused)
+{
+ g_assert ("should be a non-null path" && path != NULL);
+
+ ++n_files_changed;
+ g_free (last_file_changed);
+ last_file_changed = g_strdup (path);
+}
+
+static void
+file_removed (GckFileTracker *tracker, const gchar *path, gpointer unused)
+{
+ g_assert ("should be a non-null path" && path != NULL);
+
+ ++n_files_removed;
+ g_free (last_file_removed);
+ last_file_removed = g_strdup (path);
+}
+
+static void
+file_reset_stats (void)
+{
+ g_free (last_file_removed);
+ g_free (last_file_added);
+ g_free (last_file_changed);
+ last_file_removed = last_file_added = last_file_changed = NULL;
+ n_files_added = n_files_changed = n_files_removed = 0;
+}
+
+DEFINE_SETUP(tracker)
+{
+ /* Make a test directory */
+ test_dir = g_build_filename ("/tmp", SUBDIR, NULL);
+
+ the_tracker = gck_file_tracker_new (test_dir, WILDCARD, NULL);
+ g_signal_connect (the_tracker, "file-added", G_CALLBACK (file_added), NULL);
+ g_signal_connect (the_tracker, "file-removed", G_CALLBACK (file_removed), NULL);
+ g_signal_connect (the_tracker, "file-changed", G_CALLBACK (file_changed), NULL);
+
+ /* Mtime must change so wait between tests */
+ sleep (1);
+
+ test_file = g_build_filename (test_dir, "my-file.woof", NULL);
+ g_unlink (test_file);
+}
+
+DEFINE_TEARDOWN(tracker)
+{
+ file_reset_stats ();
+ g_object_unref (the_tracker);
+ g_free (test_dir);
+ g_free (test_file);
+}
+
+DEFINE_TEST(file_watch)
+{
+ /* A watch for an non-existant directory, should have no responses */
+ gck_file_tracker_refresh (the_tracker, FALSE);
+
+ g_assert_cmpint (0, ==, n_files_added);
+ g_assert_cmpint (0, ==, n_files_changed);
+ g_assert_cmpint (0, ==, n_files_removed);
+
+ g_mkdir_with_parents (test_dir, 0700);
+
+ /* Should still have no responses even though it exists */
+ gck_file_tracker_refresh (the_tracker, FALSE);
+
+ g_assert_cmpint (0, ==, n_files_added);
+ g_assert_cmpint (0, ==, n_files_changed);
+ g_assert_cmpint (0, ==, n_files_removed);
+}
+
+DEFINE_TEST(watch_file)
+{
+ gboolean ret;
+
+ /* Make sure things are clean */
+ gck_file_tracker_refresh (the_tracker, FALSE);
+
+ n_files_added = n_files_changed = n_files_removed = 0;
+ last_file_added = last_file_changed = last_file_removed = 0;
+
+ ret = g_file_set_contents (test_file, DATA, strlen (DATA), NULL);
+ g_assert (ret);
+
+ /* Now make sure that file is located */
+ gck_file_tracker_refresh (the_tracker, FALSE);
+
+ g_assert_cmpint (1, ==, n_files_added);
+ g_assert_cmpint (0, ==, n_files_changed);
+ g_assert_cmpint (0, ==, n_files_removed);
+
+ /* The added one should match our file */
+ g_assert_cmpstr (last_file_added, ==, test_file);
+
+ file_reset_stats ();
+ sleep (1);
+
+ /* Shouldn't find the file again */
+ gck_file_tracker_refresh (the_tracker, FALSE);
+ g_assert_cmpint (0, ==, n_files_added);
+ g_assert_cmpint (0, ==, n_files_changed);
+ g_assert_cmpint (0, ==, n_files_removed);
+
+ /* But we should find the file if forced to */
+ gck_file_tracker_refresh (the_tracker, TRUE);
+ g_assert_cmpint (0, ==, n_files_added);
+ g_assert_cmpint (1, ==, n_files_changed);
+ g_assert_cmpint (0, ==, n_files_removed);
+ g_assert_cmpstr (last_file_changed, ==, test_file);
+
+ file_reset_stats ();
+
+ ret = g_file_set_contents (test_file, DATA, strlen (DATA), NULL);
+ g_assert (ret);
+
+ /* File was updated */
+ gck_file_tracker_refresh (the_tracker, FALSE);
+ g_assert_cmpint (0, ==, n_files_added);
+ g_assert_cmpint (1, ==, n_files_changed);
+ g_assert_cmpint (0, ==, n_files_removed);
+ g_assert_cmpstr (last_file_changed, ==, test_file);
+
+ file_reset_stats ();
+ g_unlink (test_file);
+
+ /* Now file should be removed */
+ gck_file_tracker_refresh (the_tracker, FALSE);
+
+ g_assert_cmpint (0, ==, n_files_added);
+ g_assert_cmpint (0, ==, n_files_changed);
+ g_assert_cmpint (1, ==, n_files_removed);
+ g_assert_cmpstr (last_file_removed, ==, test_file);
+}
+
+DEFINE_TEST(nomatch)
+{
+ gchar *file = g_build_filename (test_dir, "my-file.toot", NULL);
+ gboolean ret;
+
+ /* Mtime must change so wait between tests */
+ sleep (1);
+
+ ret = g_file_set_contents (file, DATA, strlen (DATA), NULL);
+ g_assert (ret);
+
+ file_reset_stats ();
+
+ /* Now make sure that file is not located */
+ gck_file_tracker_refresh (the_tracker, FALSE);
+
+ g_assert_cmpint (0, ==, n_files_added);
+ g_assert_cmpint (0, ==, n_files_changed);
+ g_assert_cmpint (0, ==, n_files_removed);
+
+ g_unlink (file);
+ g_free (file);
+}
Modified: trunk/tests/gtest-helpers.c
==============================================================================
--- trunk/tests/gtest-helpers.c (original)
+++ trunk/tests/gtest-helpers.c Mon Dec 22 20:21:06 2008
@@ -52,10 +52,6 @@
return g_realloc (p, sz);
}
-#ifndef EXTERNAL_TEST
-#include "common/gkr-async.h"
-#endif
-
static GMainLoop *mainloop = NULL;
static gboolean
@@ -133,12 +129,6 @@
gtk_init (&argc, &argv);
mainloop = g_main_loop_new (NULL, FALSE);
-#ifndef EXTERNAL_TEST
-
- gkr_async_workers_init (mainloop);
-
-#endif
-
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
g_log_set_always_fatal (fatal_mask);
Modified: trunk/tests/gtest.make
==============================================================================
--- trunk/tests/gtest.make (original)
+++ trunk/tests/gtest.make Mon Dec 22 20:21:06 2008
@@ -8,8 +8,9 @@
INCLUDES= \
-I$(top_srcdir) \
- -I$(top_srcdir)/daemon \
-I$(top_builddir) \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
$(GTK_CFLAGS) \
$(GLIB_CFLAGS)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]