* Benefits are less copies of sensitive data in memory.
* More insightful parsing and API.
libegg-entry-buffer.la
BUILT_SOURCES = \
- asn1-def-pk.h asn1-def-pkix.h
+ asn1-def-pk.c asn1-def-pkix.c
INCLUDES = \
-I$(top_srcdir)
$(GLIB_CFLAGS)
libegg_la_SOURCES = \
- egg-asn1.c egg-asn1.h \
egg-asn1x.c egg-asn1x.h \
egg-buffer.c egg-buffer.h \
egg-cleanup.c egg-cleanup.h \
egg-secure-memory.c egg-secure-memory.h \
egg-spawn.c egg-spawn.h \
egg-symkey.c egg-symkey.h \
+ egg-asn1-defs.h \
$(BUILT_SOURCES)
-asn1-def-pk.h: pk.asn
- $(ASN1PARSER) -o asn1-def-pk.h $(srcdir)/pk.asn
+asn1-def-pk.c: pk.asn
+ $(ASN1PARSER) -o asn1-def-pk.c $(srcdir)/pk.asn
-asn1-def-pkix.h: pkix.asn
- $(ASN1PARSER) -o asn1-def-pkix.h $(srcdir)/pkix.asn
+asn1-def-pkix.c: pkix.asn
+ $(ASN1PARSER) -o asn1-def-pkix.c $(srcdir)/pkix.asn
EXTRA_DIST = \
pkix.asn \
# COMMON STUFF COMPILED INTO SMALLER COMPONENTS
libegg_asn1x_la_SOURCES = \
- egg-asn1x.c egg-asn1x.h
+ egg-asn1x.c egg-asn1x.h \
+ $(BUILT_SOURCES)
libegg_asn1x_la_CFLAGS = \
$(LIBTASN1_CFLAGS) \
--- /dev/null
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* egg-asn1-defs.h - ASN.1 definitions
+
+ Copyright (C) 2010 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 EGG_ASN1_DEFS_H_
+#define EGG_ASN1_DEFS_H_
+
+#include <libtasn1.h>
+
+extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
+extern const ASN1_ARRAY_TYPE pk_asn1_tab[];
+
+#endif /*EGG_ASN1_DEFS_H_*/
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* egg-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 "egg-asn1.h"
-#include "egg-oid.h"
-
-#include <libtasn1.h>
-
-#include <string.h>
-
-#include <glib/gi18n-lib.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 volatile 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
-egg_asn1_get_pk_asn1type (void)
-{
- init_asn1_trees ();
- return asn1_pk;
-}
-
-ASN1_TYPE
-egg_asn1_get_pkix_asn1type (void)
-{
- init_asn1_trees ();
- return asn1_pkix;
-}
-
-ASN1_TYPE
-egg_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 = egg_asn1_get_pkix_asn1type ();
- else if (strncmp (type, "PK.", 3) == 0)
- base = egg_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*
-egg_asn1_encode (ASN1_TYPE asn, const gchar* part, gsize *n_data, EggAllocator 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 = (EggAllocator)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
-egg_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;
-}
-
-const guchar*
-egg_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*
-egg_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 = egg_asn1_read_element (asn, data, n_data, part, &n_raw);
- if (!raw)
- return NULL;
-
- return egg_asn1_element_content (raw, n_raw, n_content);
-}
-
-const guchar*
-egg_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*
-egg_asn1_read_value (ASN1_TYPE asn, const gchar *part, gsize *len, EggAllocator 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 = (EggAllocator)g_realloc;
-
- 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, l + 1);
-
- res = asn1_read_value (asn, part, buf, &l);
- if (res != ASN1_SUCCESS) {
- (allocator) (buf, 0);
- buf = NULL;
- } else {
- *len = l;
- }
-
- return buf;
-}
-
-gboolean
-egg_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;
-}
-
-static gboolean
-ascii_length_equals (const gchar *str, gconstpointer data, gsize n_data)
-{
- g_assert (str);
- if (!data)
- return FALSE;
- if (strlen (str) != n_data)
- return FALSE;
- return strncmp (str, data, n_data) == 0;
-}
-
-static gboolean
-ascii_length_case_equals (const gchar *str, gconstpointer data, gsize n_data)
-{
- g_assert (str);
- if (!data)
- return FALSE;
- if (strlen (str) != n_data)
- return FALSE;
- return g_ascii_strncasecmp (str, data, n_data) == 0;
-}
-
-gboolean
-egg_asn1_read_boolean (ASN1_TYPE asn, const gchar *part, gboolean *val)
-{
- gchar buffer[32];
- int n_buffer = sizeof (buffer);
- int res;
-
- memset (buffer, 0, sizeof (buffer));
-
- res = asn1_read_value (asn, part, buffer, &n_buffer);
- if (res != ASN1_SUCCESS || !n_buffer)
- return FALSE;
-
- if (ascii_length_case_equals ("TRUE", buffer, n_buffer - 1))
- *val = TRUE;
- else
- *val = FALSE;
-
- return TRUE;
-}
-
-gboolean
-egg_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
-egg_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;
-}
-
-GQuark
-egg_asn1_read_oid (ASN1_TYPE asn, const gchar *part)
-{
- GQuark quark;
- guchar *buf;
- gpointer end;
- gsize n_buf;
-
- buf = egg_asn1_read_value (asn, part, &n_buf, NULL);
- if (!buf || !n_buf)
- return 0;
-
- /* Make sure the string is actually that long */
- end = memchr (buf, 0, n_buf - 1);
- if (end != NULL)
- return 0;
-
- quark = g_quark_from_string ((gchar*)buf);
- g_free (buf);
- return quark;
-}
-
-gboolean
-egg_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 egg_asn1_write_value (asn, part, (const guchar*)oid, strlen (oid));
-}
-
-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
-
-static gboolean
-parse_utc_time (const gchar *time, gsize n_time,
- struct tm* when, gint *offset)
-{
- const char *p, *e;
- int year;
-
- g_assert (when);
- g_assert (time);
- g_assert (offset);
-
- if (n_time != strlen (time))
- return FALSE;
-
- /* YYMMDDhhmmss.ffff Z | +0000 */
- if (n_time < 6 || n_time >= 28)
- return FALSE;
-
- /* Reset everything to default legal values */
- memset (when, 0, sizeof (*when));
- *offset = 0;
- 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 FALSE;
-
- /* Make sure all that got parsed */
- if (p != e)
- return FALSE;
-
- /* 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)
- *offset = 0 - off;
- else
- *offset = off;
- }
-
- /* Make sure everything got parsed */
- if (p != e)
- return FALSE;
-
- return TRUE;
-}
-
-static time_t
-when_to_time (struct tm *when, gint offset)
-{
- time_t result;
-
- g_assert (when);
-
- /* 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 */
-
- /* Convert to seconds since epoch */
- result = timegm (when);
- if (result >= 0)
- result += offset;
-
- return result;
-}
-
-glong
-egg_asn1_time_parse_utc (const gchar *time, gssize n_time)
-{
- struct tm when;
- gint offset;
-
- g_return_val_if_fail (time, -1);
-
- if (n_time == -1)
- n_time = strlen (time);
-
- if (!parse_utc_time (time, n_time, &when, &offset))
- return -1;
-
- return when_to_time (&when, offset);
-}
-
-static gboolean
-parse_general_time (const gchar *time, gsize n_time,
- struct tm* when, gint *offset)
-{
- const char *p, *e;
-
- g_assert (time);
- g_assert (when);
- g_assert (offset);
-
- if (strlen (time) != n_time)
- return FALSE;
-
- /* YYYYMMDDhhmmss.ffff Z | +0000 */
- if (n_time < 8 || n_time >= 30)
- return FALSE;
-
- /* Reset everything to default legal values */
- memset (when, 0, sizeof (*when));
- *offset = 0;
- 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 FALSE;
-
- /* Make sure all that got parsed */
- if (p != e)
- return FALSE;
-
- /* 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)
- *offset = 0 - off;
- else
- *offset = off;
- }
-
- /* Make sure everything got parsed */
- if (p != e)
- return FALSE;
-
- return TRUE;
-}
-
-glong
-egg_asn1_time_parse_general (const gchar *time, gssize n_time)
-{
- struct tm when;
- gint offset;
-
- g_return_val_if_fail (time, -1);
-
- if (n_time == -1)
- n_time = strlen (time);
-
- if (!parse_general_time (time, n_time, &when, &offset))
- return -1;
-
- return when_to_time (&when, offset);
-}
-
-static gboolean
-read_asn1_time (ASN1_TYPE asn, const gchar *part, struct tm *when, gint *offset)
-{
- gchar ttime[256];
- gchar *name;
- int len, res;
-
- g_assert (asn);
- g_assert (part);
- g_assert (when);
- g_assert (offset);
-
- len = sizeof (ttime);
- res = asn1_read_value (asn, part, ttime, &len);
- if (res != ASN1_SUCCESS)
- return FALSE;
- --len; /* libtasn1 returns the null terminator in this count */
-
- /* CHOICE */
- if (ascii_length_equals ("generalTime", ttime, len)) {
- 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;
- return parse_general_time (ttime, len - 1, when, offset);
-
- /* UTCTIME */
- } else if (ascii_length_equals ("utcTime", ttime, len)) {
- 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;
- return parse_utc_time (ttime, len - 1, when, offset);
- }
-
- return FALSE;
-}
-
-gboolean
-egg_asn1_read_time (ASN1_TYPE asn, const gchar *part, time_t *val)
-{
- struct tm when;
- gint offset;
-
- g_return_val_if_fail (asn, FALSE);
- g_return_val_if_fail (part, FALSE);
- g_return_val_if_fail (val, FALSE);
-
- if (!read_asn1_time (asn, part, &when, &offset))
- return FALSE;
-
- *val = when_to_time (&when, offset);
- return TRUE;
-}
-
-gboolean
-egg_asn1_read_date (ASN1_TYPE asn, const gchar *part, GDate *date)
-{
- struct tm when;
- gint offset;
-
- g_return_val_if_fail (asn, FALSE);
- g_return_val_if_fail (part, FALSE);
- g_return_val_if_fail (date, FALSE);
-
- if (!read_asn1_time (asn, part, &when, &offset))
- return FALSE;
-
- g_date_set_dmy (date, when.tm_mday, when.tm_mon + 1, when.tm_year + 1900);
- return g_date_valid (date);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* egg-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 EGG_ASN1_H_
-#define EGG_ASN1_H_
-
-#include <glib.h>
-
-#include <libtasn1.h>
-
-#ifndef HAVE_EGG_ALLOCATOR
-typedef void* (*EggAllocator) (void* p, gsize);
-#define HAVE_EGG_ALLOCATOR
-#endif
-
-ASN1_TYPE egg_asn1_get_pk_asn1type (void);
-
-ASN1_TYPE egg_asn1_get_pkix_asn1type (void);
-
-ASN1_TYPE egg_asn1_decode (const gchar *type, const guchar *data,
- gsize n_data);
-
-guchar* egg_asn1_encode (ASN1_TYPE asn, const gchar* part,
- gsize *len, EggAllocator alloc);
-
-guchar* egg_asn1_read_value (ASN1_TYPE asn, const gchar *part,
- gsize *len, EggAllocator alloc);
-
-gboolean egg_asn1_write_value (ASN1_TYPE asn, const gchar *part,
- const guchar* value, gsize len);
-
-GQuark egg_asn1_read_oid (ASN1_TYPE asn, const gchar *part);
-
-gboolean egg_asn1_write_oid (ASN1_TYPE asn, const gchar *part, GQuark val);
-
-gboolean egg_asn1_read_boolean (ASN1_TYPE asn, const gchar *part, gboolean *val);
-
-gboolean egg_asn1_read_uint (ASN1_TYPE asn, const gchar *part, guint *val);
-
-gboolean egg_asn1_read_time (ASN1_TYPE asn, const gchar *part, time_t *val);
-
-gboolean egg_asn1_read_date (ASN1_TYPE asn, const gchar *part, GDate *date);
-
-const guchar* egg_asn1_read_content (ASN1_TYPE asn, const guchar *data, gsize n_data,
- const gchar *part, gsize *n_content);
-
-const guchar* egg_asn1_read_element (ASN1_TYPE asn, const guchar *data, gsize n_data,
- const gchar *part, gsize *n_element);
-
-gboolean egg_asn1_write_uint (ASN1_TYPE asn, const gchar *part, guint val);
-
-gint egg_asn1_element_length (const guchar *data, gsize n_data);
-
-const guchar* egg_asn1_element_content (const guchar *data, gsize n_data, gsize *n_content);
-
-glong egg_asn1_time_parse_utc (const gchar* value, gssize n_value);
-
-glong egg_asn1_time_parse_general (const gchar* value, gssize n_value);
-
-#endif /*EGG_ASN1_H_*/
typedef struct _Atlv Atlv;
typedef struct _Anode Anode;
typedef struct _Abuf Abuf;
+typedef struct _Abits Abits;
struct _Aenc {
EggAsn1xEncoder encoder;
- gpointer user_data;
- GDestroyNotify destroy;
+ gpointer data;
};
struct _Atlv {
GList *opts;
Atlv *tlv;
Aenc *enc;
+ gpointer user_data;
+ GDestroyNotify destroy;
gchar* failure;
};
gpointer user_data;
};
+struct _Abits {
+ guint n_bits;
+ guchar *bits;
+ GDestroyNotify destroy;
+};
+
/* Forward Declarations */
static gboolean anode_decode_anything (GNode*, Atlv*);
static gboolean anode_decode_anything_for_flags (GNode *, Atlv*, gint);
}
static gulong
-anode_def_value_as_ulong (ASN1_ARRAY_TYPE *def)
+anode_def_value_as_ulong (const ASN1_ARRAY_TYPE *def)
{
gchar *end = NULL;
gulong lval;
{
Anode *an = node->data;
if (an->enc) {
- if (an->enc->destroy)
- (an->enc->destroy) (an->enc->user_data);
g_slice_free (Aenc, an->enc);
an->enc = NULL;
}
}
static void
-anode_set_enc_data (GNode *node, EggAsn1xEncoder encoder,
- gpointer user_data, GDestroyNotify destroy)
+anode_set_enc_data (GNode *node, EggAsn1xEncoder encoder, gpointer enc_data)
{
Anode *an = node->data;
g_assert (!an->enc);
an->enc = g_slice_new0 (Aenc);
an->enc->encoder = encoder;
- an->enc->user_data = user_data;
- an->enc->destroy = destroy;
+ an->enc->data = enc_data;
+}
+
+static void
+anode_set_user_data (GNode *node, gpointer user_data, GDestroyNotify destroy)
+{
+ Anode *an;
+ g_assert (node && node->data);
+ an = node->data;
+ if (an->destroy)
+ (an->destroy) (an->user_data);
+ an->user_data = user_data;
+ an->destroy = destroy;
}
static Aenc*
g_free (an->failure);
an->failure = g_strdup_printf ("%s: %s", prefix, failure);
- return FALSE; /* So this can be changed */
+ return FALSE; /* So this can be chained */
}
static const gchar*
Anode *an = node->data;
anode_clr_tlv_data (node);
anode_clr_enc_data (node);
+ anode_set_user_data (node, NULL, NULL);
g_free (an->failure);
an->failure = NULL;
}
}
static void
+abits_destroy (gpointer data)
+{
+ Abits *ab = data;
+ g_assert (ab);
+ if (ab->destroy)
+ (ab->destroy) (ab->bits);
+ g_slice_free (Abits, ab);
+}
+
+static void
anode_destroy (GNode *node)
{
if (!G_NODE_IS_ROOT (node))
return anode_calc_tag_for_flags (node, anode_def_flags (node));
}
+static gboolean
+anode_calc_explicit_for_flags (GNode *node, gint flags)
+{
+ const ASN1_ARRAY_TYPE *opt;
+ if ((flags & FLAG_TAG) != FLAG_TAG)
+ return FALSE;
+ opt = anode_opt_lookup (node, TYPE_TAG, NULL);
+ g_return_val_if_fail (opt, FALSE);
+ if ((opt->type & FLAG_IMPLICIT) == FLAG_IMPLICIT)
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+anode_calc_explicit (GNode *node)
+{
+ return anode_calc_explicit_for_flags (node, anode_def_flags (node));
+}
+
/* -------------------------------------------------------------------------
* DECODE
*/
end = tlv->end;
/* An explicit, wrapped tag */
- if (flags & FLAG_TAG && !(flags & FLAG_IMPLICIT)) {
+ if (anode_calc_explicit_for_flags (node, flags)) {
if ((tlv->cls & ASN1_CLASS_CONTEXT_SPECIFIC) == 0)
return anode_failure (node, "missing context specific tag");
if (!anode_decode_tlv_for_contents (tlv, TRUE, &ctlv))
/* Other structured types */
} else {
- if ((tlv->cls & ASN1_CLASS_CONTEXT_SPECIFIC) != 0)
- return anode_failure (node, "invalid context specific tag");
switch (anode_def_type (node)) {
case TYPE_ANY:
if (!anode_decode_struct_any (node, tlv))
tag = tlv->tag;
/* Tag does not match, what do we do? */
- if (tlv->off == 0 || tag != tlv->tag) {
- if (flags & FLAG_OPTION || flags & FLAG_DEFAULT) {
- tlv->len = 0;
- tlv->end = tlv->buf;
- tlv->off = 0;
- return TRUE;
- } else {
- return FALSE;
- }
- }
+ if (tlv->off == 0 || tag != tlv->tag)
+ return FALSE;
/* Structured value */
if (tlv->cls & ASN1_CLASS_STRUCTURED)
static gboolean
anode_decode_anything (GNode *node, Atlv *tlv)
{
- return anode_decode_anything_for_flags (node, tlv, anode_def_flags (node));
+ gint flags = anode_def_flags (node);
+
+ if (!anode_decode_anything_for_flags (node, tlv, flags)) {
+ if (flags & FLAG_OPTION || flags & FLAG_DEFAULT) {
+ tlv->len = 0;
+ tlv->end = tlv->buf;
+ tlv->off = 0;
+ anode_clr_tlv_data (node);
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ return TRUE;
}
gboolean
/* Build up the class */
flags = anode_def_flags (node);
if (flags & FLAG_TAG) {
- explicit = !(flags & FLAG_IMPLICIT);
+ explicit = anode_calc_explicit_for_flags (node, flags);
if (explicit)
flags &= ~FLAG_TAG;
else
}
/* Not completely filled in */
- tlv.buf = tlv.end = 0;
+ tlv.buf = tlv.end = NULL;
anode_clear (node);
anode_set_tlv_data (node, &tlv);
- anode_set_enc_data (node, encoder, user_data, destroy);
+ anode_set_enc_data (node, encoder, user_data);
+ anode_set_user_data (node, user_data, destroy);
}
static gboolean
/* Encode any explicit tag */
flags = anode_def_flags (node);
- if (flags & FLAG_TAG && !(flags & FLAG_IMPLICIT)) {
+ if (anode_calc_explicit_for_flags (node, flags)) {
tag = anode_calc_tag (node);
g_return_val_if_fail (tag != G_MAXULONG, FALSE);
cls = (ASN1_CLASS_STRUCTURED | ASN1_CLASS_CONTEXT_SPECIFIC);
tlv->end = data + n_data;
/* Encode in the data */
- if (!(enc->encoder) (enc->user_data, data + tlv->off, tlv->len))
+ if (!(enc->encoder) (enc->data, data + tlv->off, tlv->len))
return FALSE;
return TRUE;
Atlv *tlv;
GNode *child;
+ g_assert (allocator);
+
/* We have to sort any SET OF :( */
if (anode_def_type (node) != TYPE_SET_OF)
return FALSE;
if (ctlv) {
enc = anode_get_enc_data (child);
g_return_val_if_fail (enc, FALSE);
- if (!(enc->encoder) (enc->user_data, data, n_data))
+ if (!(enc->encoder) (enc->data, data, n_data))
return FALSE;
/* Child's buffer matches ours */
}
static gboolean
+anode_encoder_bit_string (gpointer user_data, guchar *data, gsize n_data)
+{
+ Abits *ab = user_data;
+ guchar empty, mask;
+ gsize len;
+
+ empty = ab->n_bits % 8;
+ if (empty > 0)
+ empty = 8 - empty;
+ len = (ab->n_bits / 8) + (empty ? 1 : 0);
+ g_assert (n_data == len + 1);
+
+ /* Fill in the amount of empty */
+ data[0] = empty;
+ data += 1;
+
+ /* Fill in the actual data */
+ memcpy (data, ab->bits, len);
+
+ /* Set the extra bits to zero */
+ if (len && empty) {
+ mask = 0xFF >> (8 - empty);
+ data[len - 1] &= ~mask;
+ }
+
+ return TRUE;
+}
+
+static gboolean
anode_encode_prepare_simple (GNode *node)
{
Aenc *enc;
Atlv *tlv;
- enc = anode_get_enc_data (node);
tlv = anode_get_tlv_data (node);
- if (enc != NULL || tlv == NULL)
+ if (tlv == NULL)
return FALSE;
/* Transfer the tlv data over to enc */
- anode_set_enc_data (node, anode_encoder_simple,
- (guchar*)tlv->buf + tlv->off, NULL);
+ enc = anode_get_enc_data (node);
+ if (enc == NULL)
+ anode_set_enc_data (node, anode_encoder_simple, (guchar*)tlv->buf + tlv->off);
+
tlv->buf = tlv->end = NULL;
return TRUE;
}
g_return_val_if_fail (tlv, had);
anode_clr_tlv_data (node);
anode_set_tlv_data (node, tlv);
- anode_set_enc_data (node, anode_encoder_choice, node, NULL);
+ anode_set_enc_data (node, anode_encoder_choice, node);
}
/* Other container types */
if (!allocator)
allocator = g_realloc;
- anode_encode_prepare (asn);
+ if (!anode_encode_prepare (asn))
+ return NULL;
/* We must sort all the nasty SET OF nodes */
g_node_traverse (asn, G_POST_ORDER, G_TRAVERSE_ALL, -1,
val = p[0] - pval * 40;
if (result)
- g_string_append_printf (result, "%u.%u.", pval, val);
+ g_string_append_printf (result, "%u.%u", pval, val);
/* TODO: Validate first byte? */
for (k = 1, lead = 1, val = 0, pval = 0; k < tlv->len; ++k) {
pval = val;
if (!(p[k] & 0x80)) {
if (result)
- g_string_append_printf (result, "%u.", val);
+ g_string_append_printf (result, ".%u", val);
pval = val = 0;
lead = 1;
}
static gboolean
anode_write_oid (const gchar *oid, guchar *data, gsize *n_data)
{
- const gchar *p;
+ const gchar *p, *next;
gint num, num1;
guchar bit7;
gboolean had;
p = oid;
at = 0;
- for (i = 0; oid[0]; ++i, oid = p) {
+ for (i = 0; oid[0]; ++i, oid = next) {
p = strchr (oid, '.');
if (p == NULL)
- p = oid + strlen (oid);
+ next = p = oid + strlen (oid);
+ else
+ next = p + 1;
if (p == oid)
return FALSE;
num = atoin (oid, p - oid);
index = va_arg (va, gint);
if (index == 0)
return node;
- node = g_node_nth_child (node, index);
+
+ /* Only consider nodes that have data */
+ node = g_node_nth_child (node, 0);
+ while (node) {
+ if (egg_asn1x_have (node)) {
+ --index;
+ if (index == 0)
+ break;
+ }
+ node = g_node_next_sibling (node);
+ }
+
if (node == NULL)
return NULL;
}
}
+const gchar*
+egg_asn1x_name (GNode *node)
+{
+ g_return_val_if_fail (node, NULL);
+ return anode_def_name (node);
+}
+
+guint
+egg_asn1x_count (GNode *node)
+{
+ gint type;
+
+ g_return_val_if_fail (node, 0);
+
+ type = anode_def_type (node);
+ if (type != TYPE_SEQUENCE_OF && type != TYPE_SET_OF) {
+ g_warning ("node passed to egg_asn1x_count was not a sequence of or set of");
+ return 0;
+ }
+
+ return g_node_n_children (node);
+}
+
+gboolean
+egg_asn1x_have (GNode *node)
+{
+ Atlv *tlv;
+
+ g_return_val_if_fail (node, FALSE);
+
+ /* TODO: Handle default values */
+
+ tlv = anode_get_tlv_data (node);
+ return tlv != NULL && tlv->buf != NULL;
+}
+
gboolean
egg_asn1x_get_boolean (GNode *node, gboolean *value)
{
+ ASN1_ARRAY_TYPE *opt;
Atlv *tlv;
g_return_val_if_fail (node, FALSE);
g_return_val_if_fail (anode_def_type (node) == TYPE_BOOLEAN, FALSE);
tlv = anode_get_tlv_data (node);
- if (tlv == NULL)
- return FALSE;
+ if (tlv == NULL || tlv->buf == NULL) {
+
+ if ((anode_def_flags (node) & FLAG_DEFAULT) == 0)
+ return FALSE;
+
+ /* Try to get a default */
+ opt = anode_opt_lookup (node, TYPE_DEFAULT, NULL);
+ g_return_val_if_fail (opt, FALSE);
+
+ /* Parse out the default value */
+ if ((opt->type & FLAG_TRUE) == FLAG_TRUE)
+ *value = TRUE;
+ else if ((opt->type & FLAG_FALSE) == FLAG_FALSE)
+ *value = FALSE;
+ else
+ g_return_val_if_reached (FALSE);
+ return TRUE;
+ }
return anode_read_boolean (node, tlv, value);
}
g_return_val_if_fail (node, FALSE);
g_return_val_if_fail (anode_def_type (node) == TYPE_BOOLEAN, FALSE);
+ /* TODO: Handle default values */
+
n_data = 1;
data = g_malloc0 (1);
if (!anode_write_boolean (value, data, &n_data))
gboolean
egg_asn1x_get_integer_as_ulong (GNode *node, gulong *value)
{
+ const ASN1_ARRAY_TYPE *opt;
+ const gchar *defval;
Atlv *tlv;
+ gchar *end;
g_return_val_if_fail (node, FALSE);
g_return_val_if_fail (value, FALSE);
g_return_val_if_fail (anode_def_type (node) == TYPE_INTEGER, FALSE);
tlv = anode_get_tlv_data (node);
- if (tlv == NULL)
+ if (tlv == NULL || tlv->buf == NULL) {
+
+ if ((anode_def_flags (node) & FLAG_DEFAULT) == 0)
+ return FALSE;
+
+ /* Try to get a default */
+ opt = anode_opt_lookup (node, TYPE_DEFAULT, NULL);
+ g_return_val_if_fail (opt, FALSE);
+ g_return_val_if_fail (opt->value, FALSE);
+ defval = opt->value;
+
+ opt = anode_opt_lookup (node, TYPE_CONSTANT, defval);
+ if (opt != NULL) {
+ g_return_val_if_fail (opt->value, FALSE);
+ defval = opt->value;
+ }
+
+ /* Parse out the default value */
+ *value = strtoul (defval, &end, 10);
+ g_return_val_if_fail (end && !end[0], FALSE);
+ return TRUE;
+ }
+
+ if (tlv == NULL || tlv->buf == NULL)
return FALSE;
+ /* TODO: Default integer values */
+
return anode_read_integer_as_ulong(node, tlv, value);
}
gsize n_data;
g_return_val_if_fail (node, FALSE);
- g_return_val_if_fail (anode_def_type (node) == TYPE_BOOLEAN, FALSE);
+ g_return_val_if_fail (anode_def_type (node) == TYPE_INTEGER, FALSE);
+
+ /* TODO: Handle default values */
n_data = 8;
data = g_malloc0 (8);
return TRUE;
}
+gpointer
+egg_asn1x_get_integer_as_raw (GNode *node, EggAllocator allocator, gsize *n_data)
+{
+ Atlv *tlv;
+ gpointer data;
+
+ g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (n_data, FALSE);
+ g_return_val_if_fail (anode_def_type (node) == TYPE_INTEGER, FALSE);
+
+ if (!allocator)
+ allocator = g_realloc;
+
+ tlv = anode_get_tlv_data (node);
+ if (tlv == NULL || tlv->buf == NULL)
+ return NULL;
+
+ data = (allocator) (NULL, tlv->len);
+ if (data == NULL)
+ return NULL;
+
+ memcpy (data, tlv->buf + tlv->off, tlv->len);
+ *n_data = tlv->len;
+ return data;
+}
+
+gboolean
+egg_asn1x_set_integer_as_raw (GNode *node, gpointer data, gsize n_data, GDestroyNotify destroy)
+{
+ gboolean sign;
+ guchar *p;
+
+ g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (data, FALSE);
+ g_return_val_if_fail (n_data > 0, FALSE);
+ g_return_val_if_fail (anode_def_type (node) == TYPE_INTEGER, FALSE);
+
+ /* Make sure the integer is properly encoded in twos complement*/
+ p = (guchar*)data;
+ sign = !!(p[0] & 0x80);
+ if (sign) {
+ g_warning ("integer in egg_asn1x_set_integer_as_raw is not two's complement");
+ return FALSE;
+ }
+
+ anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, data, destroy);
+ return TRUE;
+}
+
+gconstpointer
+egg_asn1x_get_raw_element (GNode *node, gsize *n_element)
+{
+ Atlv *tlv;
+
+ g_return_val_if_fail (node, NULL);
+ g_return_val_if_fail (n_element, NULL);
+
+ tlv = anode_get_tlv_data (node);
+ if (tlv == NULL || tlv->buf == NULL)
+ return NULL;
+
+ if (anode_calc_explicit (node)) {
+ *n_element = (tlv->len + tlv->off) - tlv->oft;
+ return tlv->buf + tlv->oft;
+ } else {
+ *n_element = tlv->len + tlv->off;
+ return tlv->buf;
+ }
+}
+
+gboolean
+egg_asn1x_set_raw_element (GNode *node, gpointer data,
+ gsize n_data, GDestroyNotify destroy)
+{
+ Atlv tlv;
+
+ g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (data, FALSE);
+ g_return_val_if_fail (n_data, FALSE);
+
+ anode_clear (node);
+ memset (&tlv, 0, sizeof (tlv));
+
+ /* TODO: This needs implementation */
+ if (anode_calc_explicit (node)) {
+ g_warning ("egg_asn1x_set_raw_element does not yet work with explicit tagging");
+ return FALSE;
+ }
+
+ /* Decode the beginning TLV */
+ if (!anode_decode_tlv_for_data (data, (const guchar*)data + n_data, &tlv))
+ return FALSE;
+
+ /* Decode the data into place properly */
+ if (!anode_decode_anything (node, &tlv))
+ return FALSE;
+
+ /* There was extra data */
+ if (tlv.end - tlv.buf != n_data)
+ return FALSE;
+
+ /* Should have been set above */
+ g_assert (anode_get_tlv_data (node) != NULL);
+
+ /* We set this so the data is properly destroyed */
+ anode_set_user_data (node, data, destroy);
+ return TRUE;
+}
+
gconstpointer
egg_asn1x_get_raw_value (GNode *node, gsize *n_content)
{
g_return_val_if_fail (n_content, NULL);
tlv = anode_get_tlv_data (node);
- if (tlv == NULL)
- return FALSE;
+ if (tlv == NULL || tlv->buf == NULL)
+ return NULL;
g_return_val_if_fail (!(tlv->cls & ASN1_CLASS_STRUCTURED), NULL);
*n_content = tlv->len;
g_return_val_if_fail (node, NULL);
g_return_val_if_fail (n_string, NULL);
+ if (!allocator)
+ allocator = g_realloc;
+
type = anode_def_type (node);
g_return_val_if_fail (type == TYPE_OCTET_STRING || type == TYPE_GENERALSTRING, NULL);
tlv = anode_get_tlv_data (node);
- if (tlv == NULL)
+ if (tlv == NULL || tlv->buf == NULL)
return NULL;
if (!anode_read_string (node, tlv, NULL, &length))
return egg_asn1x_set_string_as_raw (node, (guchar*)data, n_data, destroy);
}
+guchar*
+egg_asn1x_get_bits_as_raw (GNode *node, EggAllocator allocator, guint *n_bits)
+{
+ Atlv *tlv;
+ gpointer bits;
+ guchar padded;
+
+ g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (n_bits, FALSE);
+ g_return_val_if_fail (anode_def_type (node) == TYPE_BIT_STRING, FALSE);
+
+ if (!allocator)
+ allocator = g_realloc;
+
+ tlv = anode_get_tlv_data (node);
+ if (tlv == NULL || tlv->buf == NULL)
+ return NULL;
+
+ padded = *(tlv->buf + tlv->off);
+ g_return_val_if_fail (padded < 8, NULL);
+ g_return_val_if_fail (tlv->len > 1, NULL);
+
+ bits = (allocator) (NULL, tlv->len);
+ if (bits == NULL)
+ return NULL;
+
+ memcpy (bits, tlv->buf + tlv->off + 1, tlv->len - 1);
+ *n_bits = ((tlv->len - 1) * 8) - padded;
+ return bits;
+}
+
+gboolean
+egg_asn1x_set_bits_as_raw (GNode *node, guchar *bits, guint n_bits, GDestroyNotify destroy)
+{
+ gint type;
+ gsize length;
+ Abits *ab;
+
+ g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (bits, FALSE);
+
+ type = anode_def_type (node);
+ g_return_val_if_fail (type == TYPE_BIT_STRING, FALSE);
+
+ length = (n_bits / 8);
+ if (n_bits % 8)
+ length += 1;
+
+ ab = g_slice_new0 (Abits);
+ ab->bits = bits;
+ ab->n_bits = n_bits;
+ ab->destroy = destroy;
+
+ anode_encode_tlv_and_enc (node, length + 1, anode_encoder_bit_string, ab, abits_destroy);
+ return TRUE;
+}
+
+gboolean
+egg_asn1x_get_bits_as_ulong (GNode *node, gulong *bits, guint *n_bits)
+{
+ Atlv *tlv;
+ guint i, length;
+ guchar empty;
+ const guchar *p;
+ gulong value;
+
+ g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (bits, FALSE);
+ g_return_val_if_fail (n_bits, FALSE);
+ g_return_val_if_fail (anode_def_type (node) == TYPE_BIT_STRING, FALSE);
+
+ tlv = anode_get_tlv_data (node);
+ if (tlv == NULL || tlv->buf == NULL)
+ return FALSE;
+
+ empty = *(tlv->buf + tlv->off);
+ g_return_val_if_fail (empty < 8, FALSE);
+ g_return_val_if_fail (tlv->len > 1, FALSE);
+
+ length = ((tlv->len - 1) * 8) - empty;
+ if (length > sizeof (gulong) * 8)
+ return FALSE;
+
+ value = 0;
+ p = tlv->buf + tlv->off + 1;
+
+ for (i = 0; i < tlv->len - 1; ++i)
+ value = value << 8 | p[i];
+
+ *bits = value >> empty;
+ *n_bits = length;
+ return TRUE;
+}
+
+gboolean
+egg_asn1x_set_bits_as_ulong (GNode *node, gulong bits, guint n_bits)
+{
+ guchar *data;
+ gulong value;
+ gint type;
+ gsize i, length;
+ guchar empty;
+ Abits *ab;
+
+ g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (bits, FALSE);
+ g_return_val_if_fail (n_bits <= sizeof (gulong) * 8, FALSE);
+
+ type = anode_def_type (node);
+ g_return_val_if_fail (type == TYPE_BIT_STRING, FALSE);
+
+ empty = n_bits % 8;
+ if (empty > 0)
+ empty = 8 - empty;
+ length = (n_bits / 8) + (empty ? 1 : 0);
+
+ data = g_malloc0 (sizeof (gulong));
+ value = bits << empty;
+
+ for (i = 0; i < length; ++i)
+ data[(length - i) - 1] = (value >> i * 8) & 0xFF;
+
+ ab = g_slice_new0 (Abits);
+ ab->bits = data;
+ ab->n_bits = n_bits;
+ ab->destroy = g_free;
+
+ anode_encode_tlv_and_enc (node, length + 1, anode_encoder_bit_string, ab, abits_destroy);
+ return TRUE;
+}
+
glong
egg_asn1x_get_time_as_long (GNode *node)
{
Atlv *tlv;
glong time;
+ gint type;
g_return_val_if_fail (node, -1);
- g_return_val_if_fail (anode_def_type (node) == TYPE_TIME, -1);
+ type = anode_def_type (node);
+
+ /* Time is often represented as a choice, so work than in here */
+ if (type == TYPE_CHOICE) {
+ node = egg_asn1x_get_choice (node);
+ if (node == NULL)
+ return -1;
+ g_return_val_if_fail (anode_def_type (node) == TYPE_TIME, -1);
+ return egg_asn1x_get_time_as_long (node);
+ }
+
+ g_return_val_if_fail (type == TYPE_TIME, -1);
tlv = anode_get_tlv_data (node);
- if (tlv == NULL)
+ if (tlv == NULL || tlv->buf == NULL)
return -1;
if (!anode_read_time (node, tlv, &time))
return time;
}
+gboolean
+egg_asn1x_get_time_as_date (GNode *node, GDate *date)
+{
+ GTimeVal tv;
+
+ g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (date, FALSE);
+
+ tv.tv_sec = egg_asn1x_get_time_as_long (node);
+ if (tv.tv_sec < 0)
+ return FALSE;
+ tv.tv_usec = 0;
+
+ g_date_set_time_val (date, &tv);
+ return TRUE;
+}
+
gchar*
egg_asn1x_get_oid_as_string (GNode *node)
{
g_return_val_if_fail (anode_def_type (node) == TYPE_OBJECT_ID, NULL);
tlv = anode_get_tlv_data (node);
- if (tlv == NULL)
+ if (tlv == NULL || tlv->buf == NULL)
return NULL;
if (!anode_read_object_id (node, tlv, &oid))
return egg_asn1x_set_oid_as_string (node, str);
}
+GNode*
+egg_asn1x_get_choice (GNode *node)
+{
+ GNode *child;
+
+ g_return_val_if_fail (node, NULL);
+
+ /* One and only one of the children must be set */
+ for (child = node->children; child; child = child->next) {
+ if (anode_get_tlv_data (child))
+ return child;
+ }
+
+ return NULL;
+}
+
/* -----------------------------------------------------------------------------------
* VALIDATION
*/
if (anode_def_flags (node) & FLAG_SIZE) {
size = anode_opt_lookup (node, TYPE_SIZE, NULL);
- if (size == NULL) {
- egg_asn1x_dump (g_node_get_root (node));
- }
g_return_val_if_fail (size, FALSE);
if (!anode_parse_size (node, size->value, &value1))
g_return_val_if_reached (FALSE);
g_assert (tlv);
/* At least two bytes in length */
- if (tlv->len < 2)
+ if (tlv->len < 1)
return anode_failure (node, "invalid length bit string");
/* First byte is the number of free bits at end */
empty = tlv->buf[tlv->off];
return anode_failure (node, "bit string has invalid header");
/* Free bits at end must be zero */
mask = 0xFF >> (8 - empty);
- if (tlv->buf[tlv->off + tlv->len - 1] & mask)
+ if (tlv->len > 1 && tlv->buf[tlv->off + tlv->len - 1] & mask)
return anode_failure (node, "bit string has invalid trailing bits");
return TRUE;
}
/* All the children must validate properly */
for (child = node->children; child; child = child->next) {
- if (!anode_validate_anything (child))
- return FALSE;
-
tlv = anode_get_tlv_data (child);
if (tlv) {
+ if (!anode_validate_anything (child))
+ return FALSE;
+
/* Tag must have same tag as top */
if (count == 0)
tag = anode_calc_tag (child);
if (!tlv) {
if (anode_def_flags (node) & FLAG_OPTION)
return TRUE;
+ if (anode_def_flags (node) & FLAG_DEFAULT)
+ return TRUE;
return anode_failure (node, "missing value");
}
}
static const ASN1_ARRAY_TYPE*
-lookup_def (const ASN1_ARRAY_TYPE *defs, const gchar *identifier, gint type)
+adef_next_sibling (const ASN1_ARRAY_TYPE *def)
+{
+ int depth = 0;
+
+ g_assert (def);
+ g_assert (def->value || def->type || def->name);
+
+ if ((def->type & FLAG_RIGHT) == 0)
+ return NULL;
+
+ /* Skip past any children */
+ if ((def->type & FLAG_DOWN) == FLAG_DOWN) {
+ depth += 1;
+ while (depth > 0) {
+ ++def;
+ if ((def->type & FLAG_DOWN) == FLAG_DOWN)
+ depth += 1;
+ if ((def->type & FLAG_RIGHT) == 0)
+ depth -= 1;
+ }
+ }
+
+ ++def;
+ g_return_val_if_fail (def->value || def->type || def->name, NULL);
+ return def;
+}
+
+static const ASN1_ARRAY_TYPE*
+adef_first_child (const ASN1_ARRAY_TYPE *def)
{
- /* Find the one we're interested in */
- while (defs && (defs->value || defs->type || defs->name)) {
- if ((defs->type & 0xFF) == type &&
- defs->name && g_str_equal (identifier, defs->name))
- return defs;
- ++defs;
+ g_assert (def);
+ g_assert (def->value || def->type || def->name);
+
+ if ((def->type & FLAG_DOWN) == 0)
+ return NULL;
+
+ ++def;
+ g_return_val_if_fail (def->value || def->type || def->name, NULL);
+ return def;
+}
+
+static const ASN1_ARRAY_TYPE*
+lookup_def_of_type (const ASN1_ARRAY_TYPE *defs, const gchar *name, gint type)
+{
+ const ASN1_ARRAY_TYPE *def;
+
+ g_assert (defs);
+ g_assert (defs->value || defs->type || defs->name);
+
+ for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
+ if ((def->type & 0xFF) == type && def->name && g_str_equal (name, def->name))
+ return def;
}
return NULL;
identifier = anode_def_name (node);
if (identifier && !g_str_equal (identifier, "MAX") &&
g_ascii_isalpha (identifier[0])) {
- def = lookup_def (defs, identifier, TYPE_INTEGER);
+ def = lookup_def_of_type (defs, identifier, TYPE_INTEGER);
g_return_val_if_fail (def, TRUE);
anode_opt_add (node, def);
}
return FALSE;
}
+static const ASN1_ARRAY_TYPE*
+match_oid_in_definition (const ASN1_ARRAY_TYPE *def, GHashTable *names,
+ const gchar *match, const gchar **problem)
+{
+ const ASN1_ARRAY_TYPE *result = NULL;
+ const ASN1_ARRAY_TYPE *odef;
+ const gchar *value;
+ GString *oid = NULL;
+
+ g_assert (match);
+ g_assert (problem);
+ g_assert (names);
+
+ for (odef = adef_first_child (def); odef; odef = adef_next_sibling (odef)) {
+ if ((odef->type & 0xFF) != TYPE_CONSTANT)
+ continue;
+
+ g_return_val_if_fail (odef->value, NULL);
+ if (strspn (odef->value, "01234567890") == strlen (odef->value)) {
+ value = odef->value;
+
+ } else {
+ value = g_hash_table_lookup (names, odef->value);
+
+ /* A name resolution problem */
+ if (!value) {
+ if (oid)
+ g_string_free (oid, TRUE);
+ *problem = odef->value;
+ return NULL;
+ }
+ }
+
+ if (oid) {
+ g_string_append_c (oid, '.');
+ g_string_append (oid, value);
+ } else {
+ oid = g_string_new (value);
+ }
+ }
+
+ if (oid != NULL) {
+ if (g_str_equal (oid->str, match))
+ result = adef_next_sibling (def);
+ g_assert (def->name);
+ g_hash_table_insert (names, (gchar*)def->name, g_string_free (oid, FALSE));
+ }
+
+ return result;
+}
+
+static const ASN1_ARRAY_TYPE*
+match_oid_in_definitions (const ASN1_ARRAY_TYPE *defs, const gchar *match)
+{
+ const ASN1_ARRAY_TYPE *def;
+ const ASN1_ARRAY_TYPE *result;
+ GHashTable *names;
+ gboolean progress;
+ const gchar *problem;
+
+ names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+ for (;;) {
+ progress = FALSE;
+ problem = NULL;
+
+ for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
+
+ /* Only work with object ids, and ones with names */
+ if ((def->type & 0xFF) != TYPE_OBJECT_ID || !def->name)
+ continue;
+
+ /* If we've already seen this one, skip */
+ if (g_hash_table_lookup (names, def->name))
+ continue;
+
+ progress = TRUE;
+ result = match_oid_in_definition (def, names, match, &problem);
+ if (result != NULL)
+ break;
+ }
+
+ if (!problem || result) {
+ break;
+ } else if (problem && !progress) {
+ g_warning ("couldn't find oid definition in ASN.1 for: %s", problem);
+ g_return_val_if_reached (NULL);
+ }
+ }
+
+ g_hash_table_destroy (names);
+ return result;
+}
+
GNode*
-egg_asn1x_create (const ASN1_ARRAY_TYPE *defs, const gchar *identifier)
+egg_asn1x_create (const ASN1_ARRAY_TYPE *defs, const gchar *type)
{
const ASN1_ARRAY_TYPE *def;
GNode *root, *parent, *node;
int flags;
g_return_val_if_fail (defs, NULL);
- g_return_val_if_fail (identifier, NULL);
+ g_return_val_if_fail (type, NULL);
- def = defs;
+ /* An OID */
+ if (strspn (type, "0123456789.") == strlen (type)) {
+ def = match_oid_in_definitions (defs, type);
- /* Find the one we're interested in */
- while (def && (def->value || def->type || def->name)) {
- if (def->name && g_str_equal (identifier, def->name))
- break;
- ++def;
+ /* An Identifier */
+ } else {
+ for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
+ if (def->name && g_str_equal (type, def->name))
+ break;
+ }
}
- if (!def->name || !def->type)
+ if (def == NULL || !def->name || !def->type)
return NULL;
/* The node for this item */
return root;
}
+GNode*
+egg_asn1x_create_quark (const ASN1_ARRAY_TYPE *defs, GQuark type)
+{
+ g_return_val_if_fail (type, NULL);
+ return egg_asn1x_create (defs, g_quark_to_string (type));
+}
+
+GNode*
+egg_asn1x_create_and_decode (const ASN1_ARRAY_TYPE *defs, const gchar *identifier,
+ gconstpointer data, gsize n_data)
+{
+ GNode *asn;
+
+ g_return_val_if_fail (defs, NULL);
+ g_return_val_if_fail (identifier, NULL);
+
+ asn = egg_asn1x_create (defs, identifier);
+ g_return_val_if_fail (asn, NULL);
+
+ if (!egg_asn1x_decode (asn, data, n_data)) {
+ egg_asn1x_destroy (asn);
+ return NULL;
+ }
+
+ return asn;
+}
+
/* -----------------------------------------------------------------------------------
* DUMPING and MESSAGES
*/
guint i, depth;
GString *output;
gchar *string;
+ Atlv *tlv;
Anode *an;
GList *l;
for (i = 0; i < depth - 1; ++i)
g_printerr (" ");
+ tlv = anode_get_tlv_data (node);
output = g_string_new ("");
dump_append_type (output, anode_def_type (node));
dump_append_flags (output, anode_def_flags (node));
string = g_utf8_casefold (output->str, output->len - 1);
g_string_free (output, TRUE);
- g_printerr ("+ %s: %s [%s]\n", anode_def_name (node), anode_def_value (node), string);
+ g_printerr ("+ %s: %s [%s]%s\n", anode_def_name (node), anode_def_value (node),
+ string, tlv && tlv->buf ? " *" : "");
g_free (string);
/* Print out all the options */
void
egg_asn1x_destroy (gpointer data)
{
- if (data)
- anode_destroy (data);
+ GNode *node = data;
+
+ if (node != NULL) {
+ g_return_if_fail (G_NODE_IS_ROOT (node));
+ anode_destroy (node);
+ }
+}
+
+/* --------------------------------------------------------------------------------
+ * TIME PARSING
+ */
+
+glong
+egg_asn1x_parse_time_general (const gchar *time, gssize n_time)
+{
+ gboolean ret;
+ glong value;
+ struct tm when;
+ gint offset = 0;
+
+ g_return_val_if_fail (time, -1);
+
+ if (n_time < 0)
+ n_time = strlen (time);
+
+ ret = parse_general_time (time, n_time, &when, &offset);
+ if (!ret)
+ return -1;
+
+ /* In order to work with 32 bit time_t. */
+ if (sizeof (time_t) <= 4 && when.tm_year >= 2038) {
+ value = (time_t)2145914603; /* 2037-12-31 23:23:23 */
+
+ /* Convert to seconds since epoch */
+ } else {
+ value = timegm (&when);
+ g_return_val_if_fail (*time >= 0, FALSE);
+ value += offset;
+ }
+
+ return value;
+}
+
+glong
+egg_asn1x_parse_time_utc (const gchar *time, gssize n_time)
+{
+ gboolean ret;
+ glong value;
+ struct tm when;
+ gint offset = 0;
+
+ g_return_val_if_fail (time, -1);
+
+ if (n_time < 0)
+ n_time = strlen (time);
+
+ ret = parse_utc_time (time, n_time, &when, &offset);
+ if (!ret)
+ return -1;
+
+ /* In order to work with 32 bit time_t. */
+ if (sizeof (time_t) <= 4 && when.tm_year >= 2038) {
+ value = (time_t)2145914603; /* 2037-12-31 23:23:23 */
+
+ /* Convert to seconds since epoch */
+ } else {
+ value = timegm (&when);
+ g_return_val_if_fail (*time >= 0, FALSE);
+ value += offset;
+ }
+
+ return value;
+}
+
+/* --------------------------------------------------------------------------------
+ * BASIC RAW ELEMENT INFO
+ */
+
+gssize
+egg_asn1x_element_length (gconstpointer 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 ((const guchar*)data + cb, n_data - cb, &cb);
+ counter += cb;
+ if (len >= 0) {
+ len += counter;
+ if (n_data >= len)
+ return len;
+ }
+ }
+
+ return -1;
+}
+
+gconstpointer
+egg_asn1x_element_content (gconstpointer 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 ((const guchar*)data + cb, n_data - cb, &cb);
+ if (len < 0)
+ return NULL;
+ counter += cb;
+
+ *n_content = len;
+ return (const guchar*)data + counter;
}
#include <glib.h>
-#include <libtasn1.h>
-
-
#ifndef HAVE_EGG_ALLOCATOR
typedef void* (*EggAllocator) (void* p, gsize);
#define HAVE_EGG_ALLOCATOR
typedef gboolean (*EggAsn1xEncoder) (gpointer data, guchar *buf, gsize n_buf);
-GNode* egg_asn1x_create (const ASN1_ARRAY_TYPE *defs,
+struct static_struct_asn;
+
+GNode* egg_asn1x_create (const struct static_struct_asn *defs,
const gchar *type);
+GNode* egg_asn1x_create_quark (const struct static_struct_asn *defs,
+ GQuark type);
+
+GNode* egg_asn1x_create_and_decode (const struct static_struct_asn *defs,
+ const gchar *type,
+ gconstpointer data,
+ gsize n_data);
+
void egg_asn1x_dump (GNode *asn);
void egg_asn1x_clear (GNode *asn);
GNode* egg_asn1x_node (GNode *asn,
...) G_GNUC_NULL_TERMINATED;
+const gchar* egg_asn1x_name (GNode *asn);
+
+guint egg_asn1x_count (GNode *node);
+
+gboolean egg_asn1x_have (GNode *node);
+
+GNode* egg_asn1x_get_choice (GNode *node);
+
gboolean egg_asn1x_get_boolean (GNode *node,
gboolean *value);
gboolean egg_asn1x_set_integer_as_ulong (GNode *node,
gulong value);
+gpointer egg_asn1x_get_integer_as_raw (GNode *node,
+ EggAllocator allocator,
+ gsize *n_data);
+
+gboolean egg_asn1x_set_integer_as_raw (GNode *node,
+ gpointer data,
+ gsize n_data,
+ GDestroyNotify destroy);
+
gconstpointer egg_asn1x_get_raw_value (GNode *node,
gsize *n_content);
gpointer user_data,
GDestroyNotify destroy);
+gconstpointer egg_asn1x_get_raw_element (GNode *node,
+ gsize *n_data);
+
+gboolean egg_asn1x_set_raw_element (GNode *node,
+ gpointer user_data,
+ gsize n_data,
+ GDestroyNotify destroy);
+
guchar* egg_asn1x_get_string_as_raw (GNode *node,
EggAllocator allocator,
gsize *n_string);
gsize n_data,
GDestroyNotify destroy);
+guchar* egg_asn1x_get_bits_as_raw (GNode *node,
+ EggAllocator allocator,
+ guint *n_bits);
+
+gboolean egg_asn1x_set_bits_as_raw (GNode *node,
+ guchar *data,
+ guint n_bits,
+ GDestroyNotify destroy);
+
+gboolean egg_asn1x_get_bits_as_ulong (GNode *node,
+ gulong *value,
+ guint *n_bits);
+
+gboolean egg_asn1x_set_bits_as_ulong (GNode *node,
+ gulong value,
+ guint n_bits);
+
gchar* egg_asn1x_get_string_as_utf8 (GNode *node,
EggAllocator allocator);
glong egg_asn1x_get_time_as_long (GNode *node);
-glong egg_asn1x_set_time_as_long (GNode *node);
+gboolean egg_asn1x_set_time_as_long (GNode *node,
+ glong time);
+
+gboolean egg_asn1x_get_time_as_date (GNode *node,
+ GDate *date);
+
+gboolean egg_asn1x_set_time_as_date (GNode *node,
+ GDate *date);
GQuark egg_asn1x_get_oid_as_quark (GNode *node);
void egg_asn1x_destroy (gpointer asn);
+glong egg_asn1x_parse_time_general (const gchar *time,
+ gssize n_time);
+
+glong egg_asn1x_parse_time_utc (const gchar *time,
+ gssize n_time);
+
+gssize egg_asn1x_element_length (gconstpointer data,
+ gsize n_data);
+
+gconstpointer egg_asn1x_element_content (gconstpointer data,
+ gsize n_data,
+ gsize *n_content);
+
#endif /*EGG_ASN1X_H_*/
#include "config.h"
-#include "egg-asn1.h"
+#include "egg-asn1-defs.h"
+#include "egg-asn1x.h"
#include "egg-dn.h"
#include "egg-oid.h"
-#include <libtasn1.h>
-
#include <string.h>
static const char HEXC[] = "0123456789ABCDEF";
-static gboolean
-ascii_length_equals (const gchar *str, gconstpointer data, gsize n_data)
-{
- g_assert (str);
- if (!data)
- return FALSE;
- if (strlen (str) != n_data)
- return FALSE;
- return strncmp (str, data, n_data) == 0;
-}
-
static gchar*
dn_print_hex_value (const guchar *data, gsize len)
{
static gchar*
dn_print_oid_value_parsed (GQuark oid, guint flags, const guchar *data, gsize len)
{
- const gchar *asn_name;
- ASN1_TYPE asn1;
- gchar *part;
- gchar *value;
+ GNode *asn1, *node;
+ gconstpointer value;
gsize n_value;
+ gchar *result;
g_assert (data);
g_assert (len);
- asn_name = asn1_find_structure_from_oid (egg_asn1_get_pkix_asn1type (),
- g_quark_to_string (oid));
- g_return_val_if_fail (asn_name, NULL);
-
- part = g_strdup_printf ("PKIX1.%s", asn_name);
- asn1 = egg_asn1_decode (part, data, len);
- g_free (part);
+ asn1 = egg_asn1x_create_quark (pkix_asn1_tab, oid);
+ g_return_val_if_fail (asn1, NULL);
- if (!asn1) {
- g_message ("couldn't decode value for OID: %s", g_quark_to_string (oid));
+ if (!egg_asn1x_decode (asn1, data, len)) {
+ g_message ("couldn't decode value for OID: %s: %s",
+ g_quark_to_string (oid), egg_asn1x_message (asn1));
+ egg_asn1x_destroy (asn1);
return NULL;
}
- value = (gchar*)egg_asn1_read_value (asn1, "", &n_value, NULL);
-
/*
* If it's a choice element, then we have to read depending
* on what's there.
*/
- if (value && (flags & EGG_OID_IS_CHOICE)) {
- if (ascii_length_equals ("printableString", value, n_value - 1) ||
- ascii_length_equals ("ia5String", value, n_value - 1 ) ||
- ascii_length_equals ("utf8String", value, n_value - 1) ||
- ascii_length_equals ("teletexString", value, n_value - 1)) {
- part = value;
- value = (gchar*)egg_asn1_read_value (asn1, part, &n_value, NULL);
- g_free (part);
- } else {
- g_free (value);
- return NULL;
- }
- }
+ if (flags & EGG_OID_IS_CHOICE)
+ node = egg_asn1x_get_choice (asn1);
+ else
+ node = asn1;
- if (!value) {
- g_message ("couldn't read value for OID: %s", g_quark_to_string (oid));
- return NULL;
- }
+ value = egg_asn1x_get_raw_value (node, &n_value);
/*
* Now we make sure it's UTF-8.
*/
- if (!g_utf8_validate (value, n_value, NULL)) {
- gchar *hex = dn_print_hex_value ((guchar*)value, n_value);
- g_free (value);
- value = hex;
+
+ if (!value) {
+ g_message ("couldn't read value for OID: %s", g_quark_to_string (oid));
+ result = NULL;
+
+ } else if (!g_utf8_validate (value, n_value, NULL)) {
+ result = dn_print_hex_value ((guchar*)value, n_value);
+
+ } else {
+ result = g_strndup (value, n_value);
}
- return value;
+ egg_asn1x_destroy (asn1);
+
+ return result;
}
static gchar*
}
static gchar*
-dn_parse_rdn (ASN1_TYPE asn, const gchar *part)
+dn_parse_rdn (GNode *asn)
{
const gchar *name;
guint flags;
GQuark oid;
- gchar *path;
- guchar *value;
+ gconstpointer value;
gsize n_value;
gchar *display;
gchar *result;
g_assert (asn);
- g_assert (part);
- path = g_strdup_printf ("%s.type", part);
- oid = egg_asn1_read_oid (asn, path);
- g_free (path);
-
- if (!oid)
- return NULL;
-
- path = g_strdup_printf ("%s.value", part);
- value = egg_asn1_read_value (asn, path, &n_value, NULL);
- g_free (path);
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "type", NULL));
+ g_return_val_if_fail (oid, NULL);
flags = egg_oid_get_flags (oid);
name = egg_oid_get_name (oid);
+ value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "value", NULL), &n_value);
g_return_val_if_fail (value, NULL);
- display = dn_print_oid_value (oid, flags, value, n_value);
+ display = dn_print_oid_value (oid, flags, value, n_value);
result = g_strconcat ((flags & EGG_OID_PRINTABLE) ? name : g_quark_to_string (oid),
- "=", display, NULL);
+ "=", display, NULL);
g_free (display);
return result;
}
gchar*
-egg_dn_read (ASN1_TYPE asn, const gchar *part)
+egg_dn_read (GNode* asn)
{
gboolean done = FALSE;
GString *result;
- gchar *path;
+ GNode *node;
gchar *rdn;
gint i, j;
g_return_val_if_fail (asn, NULL);
- g_return_val_if_fail (part, NULL);
result = g_string_sized_new (64);
/* Each type=value pair of an RDN */
for (j = 1; TRUE; ++j) {
- path = g_strdup_printf ("%s%s?%u.?%u", part ? part : "",
- part ? "." : "", i, j);
- rdn = dn_parse_rdn (asn, path);
- g_free (path);
-
- if (!rdn) {
+ node = egg_asn1x_node (asn, i, j, NULL);
+ if (!node) {
done = j == 1;
break;
}
+ rdn = dn_parse_rdn (node);
+ g_return_val_if_fail (rdn, NULL);
+
/* Account for multi valued RDNs */
if (j > 1)
g_string_append (result, "+");
}
gchar*
-egg_dn_read_part (ASN1_TYPE asn, const gchar *part, const gchar *match)
+egg_dn_read_part (GNode *asn, const gchar *match)
{
gboolean done = FALSE;
const gchar *name;
- guchar *value;
+ gconstpointer value;
gsize n_value;
- gchar *path;
+ GNode *node;
GQuark oid;
gint i, j;
g_return_val_if_fail (asn, NULL);
- g_return_val_if_fail (part, NULL);
g_return_val_if_fail (match, NULL);
/* Each (possibly multi valued) RDN */
/* Each type=value pair of an RDN */
for (j = 1; TRUE; ++j) {
- path = g_strdup_printf ("%s%s?%u.?%u.type",
- part ? part : "",
- part ? "." : "", i, j);
- oid = egg_asn1_read_oid (asn, path);
- g_free (path);
-
- if (!oid) {
+ node = egg_asn1x_node (asn, i, j, "type", NULL);
+ if (!node) {
done = j == 1;
break;
}
+ oid = egg_asn1x_get_oid_as_quark (node);
+ g_return_val_if_fail (oid, NULL);
+
/* Does it match either the OID or the displayable? */
if (g_ascii_strcasecmp (g_quark_to_string (oid), match) != 0) {
name = egg_oid_get_name (oid);
continue;
}
- path = g_strdup_printf ("%s%s?%u.?%u.value",
- part ? part : "",
- part ? "." : "", i, j);
- value = egg_asn1_read_value (asn, path, &n_value, NULL);
- g_free (path);
+ node = egg_asn1x_node (asn, i, j, "value", NULL);
+ g_return_val_if_fail (node, NULL);
+ value = egg_asn1x_get_raw_element (node, &n_value);
g_return_val_if_fail (value, NULL);
+
return dn_print_oid_value (oid, egg_oid_get_flags (oid), value, n_value);
}
}
}
gboolean
-egg_dn_parse (ASN1_TYPE asn, const gchar *part,
- EggDnCallback callback, gpointer user_data)
+egg_dn_parse (GNode *asn, EggDnCallback callback, gpointer user_data)
{
gboolean done = FALSE;
- gchar *path;
- guchar *value;
+ GNode *node;
+ gconstpointer value;
gsize n_value;
GQuark oid;
guint i, j;
for (j = 1; TRUE; ++j) {
/* Dig out the type */
- path = g_strdup_printf ("%s%s?%u.?%u.type",
- part ? part : "",
- part ? "." : "", i, j);
- oid = egg_asn1_read_oid (asn, path);
- g_free (path);
-
- if (!oid) {
+ node = egg_asn1x_node (asn, i, j, "type", NULL);
+ if (!node) {
done = j == 1;
break;
}
- /* Print the value as nicely as we can */
- path = g_strdup_printf ("%s%s?%u.?%u.value",
- part ? part : "",
- part ? "." : "", i, j);
- value = egg_asn1_read_value (asn, path, &n_value, NULL);
- g_free (path);
+ oid = egg_asn1x_get_oid_as_quark (node);
+ g_return_val_if_fail (oid, FALSE);
- if (!value) {
+ /* Dig out the value */
+ node = egg_asn1x_node (asn, i, j, "value", NULL);
+ if (!node) {
done = j == 1;
break;
}
+ value = egg_asn1x_get_raw_element (node, &n_value);
+
if (callback)
(callback) (i, oid, value, n_value, user_data);
-
- g_free (value);
}
}
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* egg-asn1.h - ASN.1 helper routines
+/* egg-dn.h - ASN.1 helper routines
- Copyright (C) 2007 Stefan Walter
+ Copyright (C) 2010 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
#include <glib.h>
-#include <libtasn1.h>
+gchar* egg_dn_read (GNode *node);
-gchar* egg_dn_read (ASN1_TYPE asn, const gchar *part);
+gchar* egg_dn_read_part (GNode *node,
+ const gchar *match);
-gchar* egg_dn_read_part (ASN1_TYPE asn, const gchar *part, const gchar *match);
+typedef void (*EggDnCallback) (guint index,
+ GQuark oid,
+ const guchar *value,
+ gsize n_value,
+ gpointer user_data);
-typedef void (*EggDnCallback) (guint index, GQuark oid, const guchar *value,
- gsize n_value, gpointer user_data);
+gboolean egg_dn_parse (GNode *node,
+ EggDnCallback callback,
+ gpointer user_data);
-gboolean egg_dn_parse (ASN1_TYPE asn, const gchar *part,
- EggDnCallback callback, gpointer user_data);
+gchar* egg_dn_print_value (GQuark oid,
+ const guchar *value,
+ gsize n_value);
-gchar* egg_dn_print_value (GQuark oid, const guchar *value, gsize n_value);
-
-#endif /*EGG_DN_H_*/
+#endif /* EGG_DN_H_ */
#include "config.h"
-#include "egg-asn1.h"
+#include "egg-asn1-defs.h"
+#include "egg-asn1x.h"
#include "egg-secure-memory.h"
#include "egg-symkey.h"
const gchar *password, gsize n_password, const guchar *data,
gsize n_data, gcry_cipher_hd_t *cih)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
gcry_error_t gcry;
- const guchar *salt;
+ gconstpointer salt;
gsize n_salt;
gsize n_block, n_key;
- guint iterations;
+ gulong iterations;
guchar *key = NULL;
guchar *iv = NULL;
gboolean ret;
gcry_md_test_algo (hash_algo) != 0)
goto done;
- asn = egg_asn1_decode ("PKIX1.pkcs-5-PBE-params", data, n_data);
- if (!asn)
+ asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-5-PBE-params");
+ g_return_val_if_fail (asn, FALSE);
+
+ if (!egg_asn1x_decode (asn, data, n_data))
goto done;
- salt = egg_asn1_read_content (asn, data, n_data, "salt", &n_salt);
+ salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", NULL), &n_salt);
if (!salt)
goto done;
- if (!egg_asn1_read_uint (asn, "iterationCount", &iterations))
+ if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterationCount", NULL), &iterations))
iterations = 1;
n_key = gcry_cipher_get_algo_keylen (cipher_algo);
done:
g_free (iv);
egg_secure_free (key);
-
- if (asn)
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (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;
+ GNode *asn = NULL;
gcry_error_t gcry;
const guchar *iv;
gsize n_iv;
- guint version;
+ gulong version;
+ gboolean ret = FALSE;
g_assert (data);
- asn = egg_asn1_decode ("PKIX1.pkcs-5-rc2-CBC-params", data, n_data);
- if (!asn)
- return FALSE;
+ asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-5-rc2-CBC-params");
+ g_return_val_if_fail (asn, FALSE);
- if (!egg_asn1_read_uint (asn, "rc2ParameterVersion", &version))
- return FALSE;
+ if (!egg_asn1x_decode (asn, data, n_data))
+ goto done;
- iv = egg_asn1_read_content (asn, data, n_data, "iv", &n_iv);
- asn1_delete_structure (&asn);
+ if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "rc2ParameterVersion", NULL), &version))
+ goto done;
+ iv = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "iv", NULL), &n_iv);
if (!iv)
- return FALSE;
+ goto done;
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 FALSE;
+ goto done;
}
- return TRUE;
+ ret = TRUE;
+
+done:
+ egg_asn1x_destroy (asn);
+ return ret;
}
static gboolean
setup_pkcs5_des_params (const guchar *data, guchar n_data, gcry_cipher_hd_t cih)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
gcry_error_t gcry;
- const guchar *iv;
+ gconstpointer iv;
gsize n_iv;
g_assert (data);
- asn = egg_asn1_decode ("PKIX1.pkcs-5-des-EDE3-CBC-params", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-des-EDE3-CBC-params", data, n_data);
if (!asn)
- asn = egg_asn1_decode ("PKIX1.pkcs-5-des-CBC-params", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-des-CBC-params", data, n_data);
if (!asn)
return FALSE;
- iv = egg_asn1_read_content (asn, data, n_data, "", &n_iv);
- asn1_delete_structure (&asn);
+ iv = egg_asn1x_get_raw_value (asn, &n_iv);
+ egg_asn1x_destroy (asn);
if (!iv)
return FALSE;
setup_pkcs5_pbkdf2_params (const gchar *password, gsize n_password, const guchar *data,
gsize n_data, int cipher_algo, gcry_cipher_hd_t cih)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
gboolean ret;
gcry_error_t gcry;
guchar *key = NULL;
const guchar *salt;
gsize n_salt, n_key;
- guint iterations;
+ gulong iterations;
g_assert (cipher_algo);
g_assert (data);
ret = FALSE;
- asn = egg_asn1_decode ("PKIX1.pkcs-5-PBKDF2-params", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-PBKDF2-params", data, n_data);
if (!asn)
goto done;
- if (!egg_asn1_read_uint (asn, "iterationCount", &iterations))
+ if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterationCount", NULL), &iterations))
iterations = 1;
- salt = egg_asn1_read_content (asn, data, n_data, "salt.specified", &n_salt);
+ salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", "specified", NULL), &n_salt);
if (!salt)
goto done;
done:
egg_secure_free (key);
- if (asn)
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
return ret;
}
read_cipher_pkcs5_pbes2 (const gchar *password, gsize n_password, const guchar *data,
gsize n_data, gcry_cipher_hd_t *cih)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
gboolean r, ret;
GQuark key_deriv_algo, enc_oid;
gcry_error_t gcry;
int algo, mode;
- int beg, end;
+ gconstpointer params;
+ gsize n_params;
g_return_val_if_fail (cih != NULL, FALSE);
g_return_val_if_fail (data != NULL && n_data != 0, FALSE);
*cih = NULL;
ret = FALSE;
- asn = egg_asn1_decode ("PKIX1.pkcs-5-PBES2-params", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-PBES2-params", data, n_data);
if (!asn)
goto done;
algo = mode = 0;
/* Read in all the encryption type */
- enc_oid = egg_asn1_read_oid (asn, "encryptionScheme.algorithm");
+ enc_oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptionScheme", "algorithm", NULL));
if (!enc_oid)
goto done;
if (enc_oid == OID_DES_EDE3_CBC)
}
/* Read out the parameters */
- if (asn1_der_decoding_startEnd (asn, data, n_data, "encryptionScheme.parameters",
- &beg, &end) != ASN1_SUCCESS)
+ params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionScheme", "parameters", NULL), &n_params);
+ if (!params)
goto done;
switch (algo) {
case GCRY_CIPHER_3DES:
case GCRY_CIPHER_DES:
- r = setup_pkcs5_des_params (data + beg, end - beg + 1, *cih);
+ r = setup_pkcs5_des_params (params, n_params, *cih);
break;
case GCRY_CIPHER_RFC2268_128:
- r = setup_pkcs5_rc2_params (data + beg, end - beg + 1, *cih);
+ r = setup_pkcs5_rc2_params (params, n_params, *cih);
break;
default:
/* Should have been caught on the oid check above */
goto done;
/* Read out the key creation paramaters */
- key_deriv_algo = egg_asn1_read_oid (asn, "keyDerivationFunc.algorithm");
+ key_deriv_algo = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "keyDerivationFunc", "algorithm", NULL));
if (!key_deriv_algo)
goto done;
if (key_deriv_algo != OID_PBKDF2) {
goto done;
}
- if (asn1_der_decoding_startEnd (asn, data, n_data, "keyDerivationFunc.parameters",
- &beg, &end) != ASN1_SUCCESS)
+ params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "keyDerivationFunc", "parameters", NULL), &n_params);
+ if (!params)
goto done;
- ret = setup_pkcs5_pbkdf2_params (password, n_password, data + beg, end - beg + 1, algo, *cih);
+ ret = setup_pkcs5_pbkdf2_params (password, n_password, params, n_params, algo, *cih);
done:
if (ret != TRUE && *cih) {
*cih = NULL;
}
- if (asn)
- asn1_delete_structure (&asn);
-
+ egg_asn1x_destroy (asn);
return ret;
}
gsize n_password, const guchar *data, gsize n_data,
gcry_cipher_hd_t *cih)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
gcry_error_t gcry;
gboolean ret;
const guchar *salt;
gsize n_salt;
gsize n_block, n_key;
- guint iterations;
+ gulong iterations;
guchar *key = NULL;
guchar *iv = NULL;
if (gcry_cipher_algo_info (cipher_algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0)
goto done;
- asn = egg_asn1_decode ("PKIX1.pkcs-12-PbeParams", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-PbeParams", data, n_data);
if (!asn)
goto done;
- salt = egg_asn1_read_content (asn, data, n_data, "salt", &n_salt);
+ salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", NULL), &n_salt);
if (!salt)
goto done;
- if (!egg_asn1_read_uint (asn, "iterations", &iterations))
+ if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterations", NULL), &iterations))
goto done;
n_block = gcry_cipher_get_algo_blklen (cipher_algo);
g_free (iv);
egg_secure_free (key);
-
- if (asn)
- asn1_delete_structure (&asn);
-
+ egg_asn1x_destroy (asn);
return ret;
}
-asn1-def-test.h: test.asn
- $(ASN1PARSER) -o asn1-def-test.h $(srcdir)/test.asn
-
-asn1-def-tests.h: tests.asn
- $(ASN1PARSER) -o asn1-def-tests.h $(srcdir)/tests.asn
+asn1-def-test.c: test.asn
+ $(ASN1PARSER) -o asn1-def-test.c $(srcdir)/test.asn
# Test files should be listed in order they need to run
TESTING_FILES = \
unit-test-openssl.c \
unit-test-dh.c \
unit-test-spawn.c \
- asn1-def-test.h \
- asn1-def-tests.h
+ asn1-def-test.c
UNIT_PROMPT =
EXTRA_DIST = \
test.asn \
- tests.asn \
test-data
include $(top_srcdir)/testing/testing.make
BUILT_SOURCES += \
- asn1-def-test.h
+ asn1-def-test.c
# ------------------------------------------------------------------------------
#include "egg/egg-asn1x.h"
#include <glib.h>
+#include <libtasn1.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include "asn1-def-tests.h"
+extern const ASN1_ARRAY_TYPE test_asn1_tab[];
const gchar I33[] = "\x02\x01\x2A";
const gchar BFALSE[] = "\x01\x01\x00";
const gchar SIMPLICIT[] = "\x85\x08""implicit";
const gchar SEXPLICIT[] = "\xE5\x0A\x04\x08""explicit";
const gchar TGENERALIZED[] = "\x18\x0F""20070725130528Z";
+const gchar BITS_TEST[] = "\x03\x04\x06\x6e\x5d\xc0";
+const gchar BITS_BAD[] = "\x03\x04\x06\x6e\x5d\xc1";
+const gchar BITS_ZERO[] = "\x03\x01\x00";
#define XL(x) G_N_ELEMENTS (x) - 1
GNode *asn;
gboolean value;
- asn = egg_asn1x_create (tests_asn1_tab, "TestBoolean");
+ asn = egg_asn1x_create (test_asn1_tab, "TestBoolean");
g_assert (asn);
/* Shouldn't succeed */
GNode *asn;
gulong value;
- asn = egg_asn1x_create (tests_asn1_tab, "TestInteger");
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
g_assert (asn);
/* Shouldn't succeed */
GNode *asn;
gchar *value;
- asn = egg_asn1x_create (tests_asn1_tab, "TestOctetString");
+ asn = egg_asn1x_create (test_asn1_tab, "TestOctetString");
g_assert (asn);
/* Shouldn't succeed */
GNode *asn;
glong value;
- asn = egg_asn1x_create (tests_asn1_tab, "TestGeneralized");
+ asn = egg_asn1x_create (test_asn1_tab, "TestGeneralized");
g_assert (asn);
/* Shouldn't succeed */
GNode *asn;
gchar *value;
- asn = egg_asn1x_create (tests_asn1_tab, "TestImplicit");
+ asn = egg_asn1x_create (test_asn1_tab, "TestImplicit");
g_assert (asn);
/* Should work */
GNode *asn;
gchar *value;
- asn = egg_asn1x_create (tests_asn1_tab, "TestExplicit");
+ asn = egg_asn1x_create (test_asn1_tab, "TestExplicit");
g_assert (asn);
/* Should work */
egg_asn1x_destroy (asn);
}
+
+DEFINE_TEST(asn1_bit_string_decode)
+{
+ GNode *asn;
+ guchar *bits;
+ guint n_bits;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ /* Should work */
+ if (!egg_asn1x_decode (asn, BITS_TEST, XL (BITS_TEST)))
+ g_assert_not_reached ();
+
+ bits = egg_asn1x_get_bits_as_raw (asn, NULL, &n_bits);
+ g_assert (bits);
+ g_assert_cmpuint (n_bits, ==, 18);
+ g_assert_cmpint (bits[0], ==, 0x6e);
+ g_assert_cmpint (bits[1], ==, 0x5d);
+ g_assert_cmpint (bits[2], ==, 0xc0);
+
+ g_free (bits);
+ egg_asn1x_destroy (asn);
+}
+
+DEFINE_TEST(asn1_bit_string_decode_bad)
+{
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ /* Should not work */
+ if (egg_asn1x_decode (asn, BITS_BAD, XL (BITS_BAD)))
+ g_assert_not_reached ();
+
+ egg_asn1x_destroy (asn);
+}
+
+DEFINE_TEST(asn1_bit_string_decode_ulong)
+{
+ GNode *asn;
+ gulong bits;
+ guint n_bits;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ /* Should work */
+ if (!egg_asn1x_decode (asn, BITS_TEST, XL (BITS_TEST)))
+ g_assert_not_reached ();
+
+ if (!egg_asn1x_get_bits_as_ulong (asn, &bits, &n_bits))
+ g_assert_not_reached ();
+
+ g_assert_cmpuint (n_bits, ==, 18);
+ g_assert_cmphex (bits, ==, 0x1b977);
+
+ egg_asn1x_destroy (asn);
+}
+
+DEFINE_TEST(asn1_bit_string_encode_decode)
+{
+ GNode *asn;
+ guchar bits[] = { 0x5d, 0x6e, 0x83 };
+ guchar *check;
+ guint n_check, n_bits = 17;
+ gpointer data;
+ gsize n_data;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ if (!egg_asn1x_set_bits_as_raw (asn, bits, n_bits, NULL))
+ g_assert_not_reached ();
+
+ data = egg_asn1x_encode (asn, NULL, &n_data);
+ g_assert (data);
+
+ if (!egg_asn1x_decode (asn, data, n_data))
+ g_assert_not_reached ();
+
+ check = egg_asn1x_get_bits_as_raw (asn, NULL, &n_check);
+ g_assert (check);
+ g_assert_cmpuint (n_check, ==, 17);
+ g_assert_cmpint (check[0], ==, 0x5d);
+ g_assert_cmpint (check[1], ==, 0x6e);
+ g_assert_cmpint (check[2], ==, 0x80);
+
+ g_free (check);
+
+ g_free (data);
+ egg_asn1x_destroy (asn);
+}
+
+DEFINE_TEST(asn1_bit_string_encode_decode_ulong)
+{
+ GNode *asn;
+ gulong check, bits = 0x0101b977;
+ guint n_check, n_bits = 18;
+ gpointer data;
+ gsize n_data;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ if (!egg_asn1x_set_bits_as_ulong (asn, bits, n_bits))
+ g_assert_not_reached ();
+
+ data = egg_asn1x_encode (asn, NULL, &n_data);
+ g_assert (data);
+
+ if (!egg_asn1x_decode (asn, data, n_data))
+ g_assert_not_reached ();
+
+ if (!egg_asn1x_get_bits_as_ulong (asn, &check, &n_check))
+ g_assert_not_reached ();
+
+ g_assert_cmpuint (n_check, ==, 18);
+ g_assert_cmphex (check, ==, 0x1b977);
+
+ g_free (data);
+ egg_asn1x_destroy (asn);
+}
+
+DEFINE_TEST(asn1_bit_string_encode_decode_zero)
+{
+ GNode *asn;
+ gpointer data;
+ gsize n_data;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ if (!egg_asn1x_set_bits_as_raw (asn, (guchar*)"", 0, NULL))
+ g_assert_not_reached ();
+
+ data = egg_asn1x_encode (asn, NULL, &n_data);
+ g_assert (data);
+
+ g_assert_cmpsize (n_data, ==, XL (BITS_ZERO));
+ g_assert (memcmp (data, BITS_ZERO, n_data) == 0);
+
+ g_free (data);
+ egg_asn1x_destroy (asn);
+}
+
+DEFINE_TEST(asn1_have)
+{
+ GNode *asn;
+ guchar *data;
+ gsize n_data;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBoolean");
+ g_assert (asn);
+
+ g_assert (!egg_asn1x_have (asn));
+
+ if (!egg_asn1x_set_boolean (asn, TRUE))
+ g_assert_not_reached ();
+
+ g_assert (!egg_asn1x_have (asn));
+
+ data = egg_asn1x_encode (asn, NULL, &n_data);
+ g_assert (data);
+
+ g_assert (egg_asn1x_have (asn));
+
+ g_free (data);
+ egg_asn1x_destroy (asn);
+}
+
+static gboolean is_freed = FALSE;
+
+static void
+test_is_freed (gpointer unused)
+{
+ g_assert (!is_freed);
+ is_freed = TRUE;
+}
+
+DEFINE_TEST(asn1_any_set_raw)
+{
+ GNode *asn, *node;
+ guchar *data;
+ const guchar *check;
+ gsize n_data, n_check;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestAnySeq");
+ g_assert (asn);
+
+ is_freed = FALSE;
+ node = egg_asn1x_node (asn, "contents", NULL);
+ g_assert (node);
+
+ if (!egg_asn1x_set_raw_element (node, (guchar*)SFARNSWORTH, XL (SFARNSWORTH), test_is_freed))
+ g_assert_not_reached ();
+
+ data = egg_asn1x_encode (asn, NULL, &n_data);
+ g_assert (data);
+
+ check = egg_asn1x_get_raw_element (node, &n_check);
+ g_assert (check);
+
+ g_assert (n_check == XL (SFARNSWORTH));
+ g_assert (memcmp (check, SFARNSWORTH, n_check) == 0);
+
+ g_free (data);
+ egg_asn1x_destroy (asn);
+ g_assert (is_freed);
+}
#include <stdlib.h>
#include <unistd.h>
-#define extern
-#include "egg/asn1-def-pkix.h"
-#include "egg/asn1-def-pk.h"
-#undef extern
+#include "egg/egg-asn1-defs.h"
#if 0
static void
test_some_asn1_stuff (pk_asn1_tab, "test-rsakey-1.der", "RSAPrivateKey");
test_some_asn1_stuff (pkix_asn1_tab, "test-personalname-1.der", "PersonalName");
test_some_asn1_stuff (pkix_asn1_tab, "test-pkcs7-1.der", "pkcs-7-ContentInfo");
+ test_some_asn1_stuff (pkix_asn1_tab, "test-pkcs7-2.der", "pkcs-7-ContentInfo");
test_some_asn1_stuff (pkix_asn1_tab, "test-pkcs12-1.der", "pkcs-12-PFX");
return 0;
#include "test-suite.h"
-#include "egg/egg-asn1.h"
+#include "egg/egg-asn1-defs.h"
+#include "egg/egg-asn1x.h"
#include "egg/egg-dn.h"
#include "egg/egg-oid.h"
#include <stdio.h>
#include <string.h>
-static ASN1_TYPE asn1_cert = NULL;
+static GNode* asn1_cert = NULL;
static guchar *data_cert = NULL;
static gsize n_data_cert = 0;
DEFINE_SETUP(dn_cert)
{
- ASN1_TYPE pkix;
- int res;
-
data_cert = testing_data_read ("test-certificate-1.der", &n_data_cert);
- /* We'll be catching this error later */
- pkix = egg_asn1_get_pkix_asn1type ();
- if (!pkix) return;
-
- res = asn1_create_element (pkix, "PKIX1.Certificate", &asn1_cert);
- g_assert (res == ASN1_SUCCESS);
+ asn1_cert = egg_asn1x_create (pkix_asn1_tab, "Certificate");
+ g_assert (asn1_cert != NULL);
- res = asn1_der_decoding (&asn1_cert, data_cert, n_data_cert, NULL);
- g_assert (res == ASN1_SUCCESS);
+ if (!egg_asn1x_decode (asn1_cert, data_cert, n_data_cert))
+ g_assert_not_reached ();
}
DEFINE_TEARDOWN(dn_cert)
{
- asn1_delete_structure (&asn1_cert);
+ egg_asn1x_destroy (asn1_cert);
g_free (data_cert);
data_cert = NULL;
}
{
gchar *dn;
- dn = egg_dn_read (asn1_cert, "tbsCertificate.issuer.rdnSequence");
+ dn = egg_dn_read (egg_asn1x_node (asn1_cert, "tbsCertificate", "issuer", "rdnSequence", NULL));
g_assert (dn != NULL);
g_assert_cmpstr (dn, ==, "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA, EMAIL=personal-premium@thawte.com");
g_free (dn);
-
- dn = egg_dn_read (asn1_cert, "tbsCertificate.nonExistant");
- g_assert (dn == NULL);
}
DEFINE_TEST(dn_value)
GString *dn = g_string_new ("");
last_index = 1;
- if (!egg_dn_parse (asn1_cert, "tbsCertificate.issuer.rdnSequence", concatenate_dn, dn))
+ if (!egg_dn_parse (egg_asn1x_node (asn1_cert, "tbsCertificate", "issuer", "rdnSequence", NULL), concatenate_dn, dn))
g_assert_not_reached ();
g_assert_cmpstr (dn->str, ==, "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA, EMAIL=personal-premium@thawte.com");
DEFINE_TEST(read_dn_part)
{
+ GNode *node;
gchar *value;
- value = egg_dn_read_part (asn1_cert, "tbsCertificate.issuer.rdnSequence", "CN");
+ node = egg_asn1x_node (asn1_cert, "tbsCertificate", "issuer", "rdnSequence", NULL);
+
+ value = egg_dn_read_part (node, "CN");
g_assert (value != NULL);
g_assert_cmpstr (value, ==, "Thawte Personal Premium CA");
g_free (value);
- value = egg_dn_read_part (asn1_cert, "tbsCertificate.issuer.rdnSequence", "2.5.4.8");
+ value = egg_dn_read_part (node, "2.5.4.8");
g_assert (value != NULL);
g_assert_cmpstr (value, ==, "Western Cape");
g_free (value);
- value = egg_dn_read_part (asn1_cert, "tbsCertificate.nonExistant", "CN");
- g_assert (value == NULL);
-
- value = egg_dn_read_part (asn1_cert, "tbsCertificate.issuer.rdnSequence", "DC");
+ value = egg_dn_read_part (node, "DC");
g_assert (value == NULL);
- value = egg_dn_read_part (asn1_cert, "tbsCertificate.issuer.rdnSequence", "0.0.0.0");
+ value = egg_dn_read_part (node, "0.0.0.0");
g_assert (value == NULL);
- value = egg_dn_read_part (asn1_cert, "tbsCertificate.issuer.rdnSequence", "2.5.4.9");
+ value = egg_dn_read_part (node, "2.5.4.9");
g_assert (value == NULL);
}
-TEST { }
+TESTS { }
DEFINITIONS EXPLICIT TAGS ::=
BEGIN
+TestInteger ::= INTEGER
+
+TestBoolean ::= BOOLEAN
+
+TestOctetString ::= OCTET STRING
+
+TestGeneralized ::= GeneralizedTime
+
+TestImplicit ::= [5] IMPLICIT OCTET STRING
+
+TestExplicit ::= [5] EXPLICIT OCTET STRING
+
+TestBitString ::= BIT STRING
+
TestIntegers ::= SEQUENCE {
uint1 INTEGER,
uint2 INTEGER,
}
TestData ::= SEQUENCE {
- data OCTET STRING,
+ data OCTET STRING
+}
+
+TestBooleanSeq ::= SEQUENCE {
boolean BOOLEAN DEFAULT FALSE
}
+TestOid ::= SEQUENCE {
+ oid OBJECT IDENTIFIER
+}
+
+TestAnySeq ::= SEQUENCE {
+ contents ANY
+}
+
END
+++ /dev/null
-TESTS { }
-
-DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-
-TestInteger ::= INTEGER
-
-TestBoolean ::= BOOLEAN
-
-TestOctetString ::= OCTET STRING
-
-TestGeneralized ::= GeneralizedTime
-
-TestImplicit ::= [5] IMPLICIT OCTET STRING
-
-TestExplicit ::= [5] EXPLICIT OCTET STRING
-
-END
#include "test-suite.h"
-#include "egg/egg-asn1.h"
+#include "egg/egg-asn1-defs.h"
+#include "egg/egg-asn1x.h"
#include "egg/egg-oid.h"
#include <glib.h>
#include <stdio.h>
#include <string.h>
-#define extern
-#include "asn1-def-test.h"
-#undef extern
+extern const ASN1_ARRAY_TYPE test_asn1_tab[];
-static ASN1_TYPE asn1_test = NULL;
-
-static ASN1_TYPE asn1_cert = NULL;
+static GNode *asn1_cert = NULL;
static guchar *data_cert = NULL;
static gsize n_data_cert = 0;
DEFINE_SETUP(asn1_tree)
{
- ASN1_TYPE pkix;
-
- int res = asn1_array2tree (test_asn1_tab, &asn1_test, NULL);
- g_assert (res == ASN1_SUCCESS);
-
- /* -------- */
-
data_cert = testing_data_read ("test-certificate-1.der", &n_data_cert);
- /* We'll be catching this error later */
- pkix = egg_asn1_get_pkix_asn1type ();
- if (!pkix) return;
-
- res = asn1_create_element (pkix, "PKIX1.Certificate", &asn1_cert);
- g_assert (res == ASN1_SUCCESS);
-
- res = asn1_der_decoding (&asn1_cert, data_cert, n_data_cert, NULL);
- g_assert (res == ASN1_SUCCESS);
+ asn1_cert = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data_cert, n_data_cert);
+ g_assert (asn1_cert != NULL);
}
DEFINE_TEARDOWN(asn1_tree)
{
- asn1_delete_structure (&asn1_test);
- asn1_delete_structure (&asn1_cert);
+ egg_asn1x_destroy (asn1_cert);
g_free (data_cert);
data_cert = NULL;
}
-DEFINE_TEST(asn1_types)
+DEFINE_TEST(node_name)
{
- ASN1_TYPE asn;
-
- asn = egg_asn1_get_pk_asn1type ();
- g_assert ("pk asn type is null" && asn != NULL);
-
- asn = egg_asn1_get_pkix_asn1type ();
- g_assert ("pkix asn type is null" && asn != NULL);
+ g_assert_cmpstr (egg_asn1x_name (asn1_cert), ==, "Certificate");
}
DEFINE_TEST(asn1_integers)
{
- ASN1_TYPE asn;
+ GNode *asn;
guchar *data;
gsize n_data;
gboolean ret;
- guint val;
- int res;
+ gulong val;
- res = asn1_create_element (asn1_test, "TEST.TestIntegers", &asn);
+ asn = egg_asn1x_create (test_asn1_tab, "TestIntegers");
g_assert ("asn test structure is null" && asn != NULL);
- ret = egg_asn1_write_uint (asn, "uint1", 35);
+ ret = egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "uint1", NULL), 35);
g_assert ("couldn't write integer" && ret);
- ret = egg_asn1_write_uint (asn, "uint2", 23456);
+ ret = egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "uint2", NULL), 23456);
g_assert ("couldn't write integer" && ret);
- ret = egg_asn1_write_uint (asn, "uint3", 209384022);
+ ret = egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "uint3", NULL), 209384022);
g_assert ("couldn't write integer" && ret);
/* Now encode the whole caboodle */
- data = egg_asn1_encode (asn, "", &n_data, NULL);
+ data = egg_asn1x_encode (asn, NULL, &n_data);
g_assert ("encoding asn1 didn't work" && data != NULL);
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (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);
+ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestIntegers", data, n_data);
+ g_return_if_fail (asn != NULL);
/* And get out the values */
- ret = egg_asn1_read_uint (asn, "uint1", &val);
+ ret = egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "uint1", NULL), &val);
g_assert ("couldn't read integer from asn1" && ret);
g_assert_cmpuint (val, ==, 35);
- ret = egg_asn1_read_uint (asn, "uint2", &val);
+ ret = egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "uint2", NULL), &val);
g_assert ("couldn't read integer from asn1" && ret);
g_assert_cmpuint (val, ==, 23456);
- ret = egg_asn1_read_uint (asn, "uint3", &val);
+ ret = egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "uint3", NULL), &val);
g_assert ("couldn't read integer from asn1" && ret);
g_assert_cmpuint (val, ==, 209384022);
+
+ g_free (data);
}
DEFINE_TEST(boolean)
{
- ASN1_TYPE asn = NULL;
+ GNode *asn = NULL;
gboolean value, ret;
- int res;
+ gpointer data;
+ gsize n_data;
- res = asn1_create_element (asn1_test, "TEST.TestData", &asn);
+ asn = egg_asn1x_create (test_asn1_tab, "TestBooleanSeq");
g_assert ("asn test structure is null" && asn != NULL);
- res = asn1_write_value (asn, "boolean", "TRUE", 4);
- g_assert (res == ASN1_SUCCESS);
+ /* Get the default value */
+ value = TRUE;
+ ret = egg_asn1x_get_boolean (egg_asn1x_node (asn, "boolean", NULL), &value);
+ g_assert (ret == TRUE);
+ g_assert (value == FALSE);
+
+ ret = egg_asn1x_set_boolean (egg_asn1x_node (asn, "boolean", NULL), TRUE);
+ g_assert (ret == TRUE);
+
+ data = egg_asn1x_encode (asn, NULL, &n_data);
+ g_assert (data);
- ret = egg_asn1_read_boolean (asn, "boolean", &value);
+ ret = egg_asn1x_get_boolean (egg_asn1x_node (asn, "boolean", NULL), &value);
g_assert (ret);
g_assert (value == TRUE);
- res = asn1_write_value (asn, "boolean", "FALSE", 5);
- g_assert (res == ASN1_SUCCESS);
+ ret = egg_asn1x_set_boolean (egg_asn1x_node (asn, "boolean", NULL), FALSE);
+ g_assert (ret == TRUE);
- ret = egg_asn1_read_boolean (asn, "boolean", &value);
+ g_free (data);
+ data = egg_asn1x_encode (asn, NULL, &n_data);
+ g_assert (data);
+
+ ret = egg_asn1x_get_boolean (egg_asn1x_node (asn, "boolean", NULL), &value);
g_assert (ret);
g_assert (value == FALSE);
- ret = egg_asn1_read_boolean (asn, "nonExistant", &value);
- g_assert (!ret);
-
- asn1_delete_structure (&asn);
+ g_free (data);
+ egg_asn1x_destroy (asn);
}
DEFINE_TEST(write_value)
{
- ASN1_TYPE asn = NULL;
+ GNode *asn = NULL;
guchar *data;
gsize n_data;
- int res;
+ guchar *encoded;
+ gsize n_encoded;
- res = asn1_create_element (asn1_test, "TEST.TestData", &asn);
+ asn = egg_asn1x_create (test_asn1_tab, "TestData");
g_assert ("asn test structure is null" && asn != NULL);
- if (!egg_asn1_write_value (asn, "data", (const guchar*)"SOME DATA", 9))
+ if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "data", NULL), (guchar*)"SOME DATA", 9, NULL))
g_assert_not_reached ();
- data = egg_asn1_read_value (asn, "data", &n_data, NULL);
+ encoded = egg_asn1x_encode (asn, NULL, &n_encoded);
+ g_assert (encoded);
+
+ data = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "data", NULL), NULL, &n_data);
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);
+ g_free (encoded);
+ egg_asn1x_destroy (asn);
}
DEFINE_TEST(element_length_content)
{
- ASN1_TYPE asn = NULL;
- guchar buffer[1024];
+ GNode *asn = NULL;
+ gchar *buffer;
const guchar *content;
gsize n_content;
- gint length;
- int res;
+ gsize n_buffer;
+ gssize length;
- res = asn1_create_element (asn1_test, "TEST.TestData", &asn);
+ asn = egg_asn1x_create (test_asn1_tab, "TestData");
g_assert ("asn test structure is null" && asn != NULL);
- res = asn1_write_value (asn, "data", "SOME DATA", 9);
- g_assert (res == ASN1_SUCCESS);
+ if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "data", NULL), (guchar*)"SOME DATA", 9, NULL))
+ g_assert_not_reached ();
- length = 1024;
- res = asn1_der_coding (asn, "", buffer, &length, NULL);
- g_assert (res == ASN1_SUCCESS);
+ buffer = egg_asn1x_encode (asn, NULL, &n_buffer);
+ g_assert (buffer != NULL);
/* Now the real test */
- length = egg_asn1_element_length (buffer, 1024);
+ length = egg_asn1x_element_length (buffer, n_buffer + 1024);
g_assert_cmpint (length, ==, 13);
- content = egg_asn1_element_content (buffer, length, &n_content);
+ content = egg_asn1x_element_content (buffer, length, &n_content);
g_assert (content);
g_assert_cmpuint (n_content, ==, 11);
- content = egg_asn1_element_content (content, n_content, &n_content);
+ content = egg_asn1x_element_content (content, n_content, &n_content);
g_assert (content);
g_assert_cmpuint (n_content, ==, 9);
g_assert (memcmp (content, "SOME DATA", 9) == 0);
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
+ g_free (buffer);
}
DEFINE_TEST(read_element)
{
- ASN1_TYPE asn = NULL;
- guchar buffer[1024];
- const guchar *data;
+ GNode *asn = NULL;
+ guchar *buffer;
+ gconstpointer data;
gsize n_data;
- gint length;
- int res;
+ gsize n_buffer;
- res = asn1_create_element (asn1_test, "TEST.TestData", &asn);
+ asn = egg_asn1x_create (test_asn1_tab, "TestData");
g_assert ("asn test structure is null" && asn != NULL);
- res = asn1_write_value (asn, "data", "SOME DATA", 9);
- g_assert (res == ASN1_SUCCESS);
+ if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "data", NULL), (guchar*)"SOME DATA", 9, NULL))
+ g_assert_not_reached ();
- length = 1024;
- res = asn1_der_coding (asn, "", buffer, &length, NULL);
- g_assert (res == ASN1_SUCCESS);
+ buffer = egg_asn1x_encode (asn, NULL, &n_buffer);
+ g_assert (buffer != NULL);
/* Now the real test */
- data = egg_asn1_read_element (asn, buffer, length, "data", &n_data);
+ data = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "data", NULL), &n_data);
g_assert (data != NULL);
g_assert_cmpint (n_data, ==, 11);
- data = egg_asn1_read_content (asn, buffer, length, "data", &n_data);
+ data = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "data", NULL), &n_data);
g_assert (data);
g_assert_cmpuint (n_data, ==, 9);
g_assert (memcmp (data, "SOME DATA", 9) == 0);
- /* Invalid should return null for both those */
- data = egg_asn1_read_element (asn, buffer, length, "nonExistant", &n_data);
- g_assert (data == NULL);
- data = egg_asn1_read_content (asn, buffer, length, "nonExistant", &n_data);
- g_assert (data == NULL);
-
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
+ g_free (buffer);
}
DEFINE_TEST(oid)
{
- ASN1_TYPE asn = NULL;
+ GNode *asn = NULL;
GQuark oid, check;
- int res;
+ guchar *buffer;
+ gsize n_buffer;
- res = asn1_create_element (asn1_test, "TEST.TestData", &asn);
+ asn = egg_asn1x_create (test_asn1_tab, "TestOid");
g_assert ("asn test structure is null" && asn != NULL);
- res = asn1_write_value (asn, "data", "SOME DATA", 9);
- g_assert (res == ASN1_SUCCESS);
+ if (!egg_asn1x_set_oid_as_string (egg_asn1x_node (asn, "oid", NULL), "1.2.34567.89"))
+ g_assert_not_reached ();
- /* No such element, should return 0 */
- oid = egg_asn1_read_oid (asn, "nonExistant");
- g_assert (oid == 0);
+ buffer = egg_asn1x_encode (asn, NULL, &n_buffer);
+ g_assert (buffer != NULL);
/* Now a quark has been defined */
- check = g_quark_from_static_string ("SOME DATA");
- oid = egg_asn1_read_oid (asn, "data");
+ check = g_quark_from_static_string ("1.2.34567.89");
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "oid", NULL));
+ g_assert (oid);
g_assert (check == oid);
- g_assert_cmpstr (g_quark_to_string (oid), ==, "SOME DATA");
+ g_assert_cmpstr (g_quark_to_string (oid), ==, "1.2.34567.89");
/* Write a different OID */
- if (!egg_asn1_write_oid (asn, "data", g_quark_from_static_string ("ANOTHER")))
+ if (!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "oid", NULL), g_quark_from_static_string ("5.4.3.2.1678")))
g_assert_not_reached ();
- oid = egg_asn1_read_oid (asn, "data");
+ g_free (buffer);
+ buffer = egg_asn1x_encode (asn, NULL, &n_buffer);
+ g_assert (buffer != NULL);
+
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "oid", NULL));
g_assert (oid);
- g_assert_cmpstr (g_quark_to_string (oid), ==, "ANOTHER");
+ g_assert_cmpstr (g_quark_to_string (oid), ==, "5.4.3.2.1678");
- asn1_delete_structure (&asn);
+ g_free (buffer);
+ egg_asn1x_destroy (asn);
}
typedef struct _TimeTestData {
const TimeTestData *data;
for (data = generalized_time_test_data; data->value; ++data) {
- when = egg_asn1_time_parse_general (data->value, -1);
+ when = egg_asn1x_parse_time_general (data->value, -1);
if (data->ref != when) {
printf ("%s", data->value);
printf ("%s != ", ctime (&when));
const TimeTestData *data;
for (data = utc_time_test_data; data->value; ++data) {
- when = egg_asn1_time_parse_utc (data->value, -1);
+ when = egg_asn1x_parse_time_utc (data->value, -1);
if (data->ref != when) {
printf ("%s", data->value);
printf ("%s != ", ctime (&when));
DEFINE_TEST(read_time)
{
- time_t time;
+ glong time;
- if (!egg_asn1_read_time (asn1_cert, "tbsCertificate.validity.notBefore", &time))
- g_assert_not_reached ();
+ time = egg_asn1x_get_time_as_long (egg_asn1x_node (asn1_cert, "tbsCertificate", "validity", "notBefore", NULL));
g_assert_cmpint (time, ==, 820454400);
}
DEFINE_TEST(read_date)
{
GDate date;
- if (!egg_asn1_read_date (asn1_cert, "tbsCertificate.validity.notAfter", &date))
+ if (!egg_asn1x_get_time_as_date (egg_asn1x_node (asn1_cert, "tbsCertificate", "validity", "notAfter", NULL), &date))
g_assert_not_reached ();
g_assert_cmpint (date.day, ==, 31);
g_assert_cmpint (date.month, ==, 12);
g_assert_cmpint (date.year, ==, 2020);
}
+
+DEFINE_TEST(create_by_oid)
+{
+ /* id-at-initials = X520initials */
+ GNode *node = egg_asn1x_create (pkix_asn1_tab, "2.5.4.43");
+ g_assert (node != NULL);
+ g_assert_cmpstr (egg_asn1x_name (node), ==, "X520initials");
+ egg_asn1x_destroy (node);
+}
+
+DEFINE_TEST(create_by_oid_invalid)
+{
+ GNode *node = egg_asn1x_create (pkix_asn1_tab, "23.23.23.23");
+ g_assert (node == NULL);
+}
+
+DEFINE_TEST(create_by_bad_order)
+{
+ /*
+ * In pkix.asn the definition for parts of this oid
+ * come in the wrong order. However this should still work.
+ */
+
+ /* id-pe-authorityInfoAccess = AuthorityInfoAccessSyntax */
+ GNode *node = egg_asn1x_create (pkix_asn1_tab, "1.3.6.1.5.5.7.1.1");
+ g_assert (node != NULL);
+ g_assert_cmpstr (egg_asn1x_name (node), ==, "AuthorityInfoAccessSyntax");
+ egg_asn1x_destroy (node);
+}
+
+DEFINE_TEST(count)
+{
+ GNode *node;
+
+ node = egg_asn1x_node (asn1_cert, "tbsCertificate", "issuer", "rdnSequence", NULL);
+ g_assert (node);
+ g_assert_cmpuint (egg_asn1x_count (node), ==, 7);
+}
#include "gcr-certificate.h"
#include "gcr-certificate-details-widget.h"
-#include "egg/egg-asn1.h"
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
#include "egg/egg-dn.h"
#include "egg/egg-oid.h"
#include "egg/egg-hex.h"
}
static gboolean
-append_extension (GcrCertificateDetailsWidget *self, ASN1_TYPE asn,
+append_extension (GcrCertificateDetailsWidget *self, GNode *asn,
const guchar *data, gsize n_data, gint index)
{
GQuark oid;
- gchar *name, *display;
+ gchar *display;
gsize n_value;
const guchar *value;
const gchar *text;
gboolean critical;
- int len, res;
+ GNode *node;
/* Make sure it is present */
- len = 0;
- name = g_strdup_printf ("tbsCertificate.extensions.?%u", index);
- res = asn1_read_value (asn, name, NULL, &len);
- g_free (name);
-
- if (res == ASN1_ELEMENT_NOT_FOUND)
+ asn = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, NULL);
+ if (asn == NULL)
return FALSE;
/* Dig out the OID */
- name = g_strdup_printf ("tbsCertificate.extensions.?%u.extnID", index);
- oid = egg_asn1_read_oid (asn, name);
- g_free (name);
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "extnID", NULL));
g_return_val_if_fail (oid, FALSE);
/* Extension value */
- name = g_strdup_printf ("tbsCertificate.extensions.?%u.extnValue", index);
- value = egg_asn1_read_content (asn, data, n_data, name, &n_value);
- g_free (name);
+ value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "extnValue", NULL), &n_value);
/* TODO: Parsing of extensions that we understand */
display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1);
/* Critical */
- name = g_strdup_printf ("tbsCertificate.extensions.?%u.critical", index);
- if (egg_asn1_read_boolean (asn, name, &critical))
- append_field_and_value (self, _("Critical"), critical ? _("Yes") : _("No"), FALSE);
- g_free (name);
+ node = egg_asn1x_node (asn, "critical", NULL);
+ if (node != NULL) {
+ if (egg_asn1x_get_boolean (node, &critical))
+ append_field_and_value (self, _("Critical"), critical ? _("Yes") : _("No"), FALSE);
+ }
return TRUE;
}
const guchar *data, *value;
gsize n_data, n_value;
const gchar *text;
- guint version, size;
- guint index;
+ gulong version;
+ guint index, size, n_bits;
gchar *display;
- ASN1_TYPE asn;
+ guchar *bits;
+ GNode *asn;
GQuark oid;
GDate date;
data = gcr_certificate_get_der_data (self->pv->certificate, &n_data);
g_return_if_fail (data);
- asn = egg_asn1_decode ("PKIX1.Certificate", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data);
g_return_if_fail (asn);
/* The subject */
append_heading (self, _("Subject Name"));
- egg_dn_parse (asn, "tbsCertificate.subject.rdnSequence", on_parsed_dn_part, self);
+ egg_dn_parse (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL), on_parsed_dn_part, self);
/* The Issuer */
append_heading (self, _("Issuer Name"));
- egg_dn_parse (asn, "tbsCertificate.issuer.rdnSequence", on_parsed_dn_part, self);
+ egg_dn_parse (egg_asn1x_node (asn, "tbsCertificate", "issuer", "rdnSequence", NULL), on_parsed_dn_part, self);
/* The Issued Parameters */
append_heading (self, _("Issued Certificate"));
- if (!egg_asn1_read_uint (asn, "tbsCertificate.version", &version))
+ if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "tbsCertificate", "version", NULL), &version))
g_return_if_reached ();
- display = g_strdup_printf ("%u", version + 1);
+ display = g_strdup_printf ("%lu", version + 1);
append_field_and_value (self, _("Version"), display, FALSE);
g_free (display);
- value = egg_asn1_read_content (asn, data, n_data, "tbsCertificate.serialNumber", &n_value);
+ value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "tbsCertificate", "serialNumber", NULL), &n_value);
g_return_if_fail (value);
display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1);
append_field_and_value (self, _("Serial Number"), display, TRUE);
g_free (display);
display = g_malloc0 (128);
- if (egg_asn1_read_date (asn, "tbsCertificate.validity.notBefore", &date)) {
+ if (egg_asn1x_get_time_as_date (egg_asn1x_node (asn, "tbsCertificate", "validity", "notBefore", NULL), &date)) {
if (!g_date_strftime (display, 128, "%Y-%m-%d", &date))
g_return_if_reached ();
append_field_and_value (self, _("Not Valid Before"), display, FALSE);
}
- if (egg_asn1_read_date (asn, "tbsCertificate.validity.notAfter", &date)) {
+ if (egg_asn1x_get_time_as_date (egg_asn1x_node (asn, "tbsCertificate", "validity", "notAfter", NULL), &date)) {
if (!g_date_strftime (display, 128, "%Y-%m-%d", &date))
g_return_if_reached ();
append_field_and_value (self, _("Not Valid After"), display, FALSE);
/* Signature */
append_heading (self, _("Signature"));
- oid = egg_asn1_read_oid (asn, "signatureAlgorithm.algorithm");
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "signatureAlgorithm", "algorithm", NULL));
text = egg_oid_get_description (oid);
append_field_and_value (self, _("Signature Algorithm"), text, FALSE);
- value = egg_asn1_read_content (asn, data, n_data, "signatureAlgorithm.parameters", &n_value);
+ value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "signatureAlgorithm", "parameters", NULL), &n_value);
if (value && n_value) {
display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1);
append_field_and_value (self, _("Signature Parameters"), display, TRUE);
g_free (display);
}
- value = egg_asn1_read_content (asn, data, n_data, "signature", &n_value);
+ value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "signature", NULL), &n_value);
g_return_if_fail (value);
display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1);
append_field_and_value (self, _("Signature"), display, TRUE);
/* Public Key Info */
append_heading (self, _("Public Key Info"));
- oid = egg_asn1_read_oid (asn, "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm");
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", "algorithm", "algorithm", NULL));
text = egg_oid_get_description (oid);
append_field_and_value (self, _("Key Algorithm"), text, FALSE);
- value = egg_asn1_read_content (asn, data, n_data, "tbsCertificate.subjectPublicKeyInfo.algorithm.parameters", &n_value);
+ value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", "algorithm", "parameters", NULL), &n_value);
if (value && n_value) {
display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1);
append_field_and_value (self, _("Key Parameters"), display, TRUE);
g_free (display);
}
- value = egg_asn1_read_content (asn, data, n_data, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", &n_value);
- g_return_if_fail (value);
- display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1);
+ bits = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", "subjectPublicKey", NULL), NULL, &n_bits);
+ g_return_if_fail (bits);
+ display = egg_hex_encode_full (bits, n_bits / 8, TRUE, ' ', 1);
append_field_and_value (self, _("Public Key"), display, TRUE);
g_free (display);
+ g_free (bits);
/* Fingerprints */
append_heading (self, _("Fingerprints"));
break;
}
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
}
/* -----------------------------------------------------------------------------
#include "gcr-internal.h"
#include "gcr-certificate.h"
-#include "egg/egg-asn1.h"
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
#include "egg/egg-dn.h"
#include "egg/egg-hex.h"
typedef struct _GcrCertificateInfo {
const guchar *der;
gsize n_der;
- ASN1_TYPE asn1;
+ GNode *asn1;
guint key_size;
} GcrCertificateInfo;
GcrCertificateInfo *info = data;
if (info) {
g_assert (info->asn1);
- asn1_delete_structure (&info->asn1);
+ egg_asn1x_destroy (info->asn1);
g_free (info);
}
}
certificate_info_load (GcrCertificate *cert)
{
GcrCertificateInfo *info;
- ASN1_TYPE asn1;
+ GNode *asn1;
const guchar *der;
gsize n_der;
}
/* Cache is invalid or non existent */
- asn1 = egg_asn1_decode ("PKIX1.Certificate", der, n_der);
+ asn1 = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", der, n_der);
if (asn1 == NULL) {
g_warning ("a derived class provided an invalid or unparseable X509 DER certificate data.");
return NULL;
static guint
calculate_rsa_key_size (const guchar *data, gsize n_data)
{
- ASN1_TYPE asn;
+ GNode *asn;
gsize n_content;
- asn = egg_asn1_decode ("PK.RSAPublicKey", data, n_data);
+ asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data, n_data);
g_return_val_if_fail (asn, 0);
- if (!egg_asn1_read_content (asn, data, n_data, "modulus", &n_content))
+ if (!egg_asn1x_get_raw_value (egg_asn1x_node (asn, "modulus", NULL), &n_content))
g_return_val_if_reached (0);
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
/* Removes the complement */
return (n_content / 2) * 2 * 8;
static guint
calculate_dsa_params_size (const guchar *data, gsize n_data)
{
- ASN1_TYPE asn;
+ GNode *asn;
gsize n_content;
- asn = egg_asn1_decode ("PK.DSAParameters", data, n_data);
+ asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", data, n_data);
g_return_val_if_fail (asn, 0);
- if (!egg_asn1_read_content (asn, data, n_data, "p", &n_content))
+ if (!egg_asn1x_get_raw_value (egg_asn1x_node (asn, "p", NULL), &n_content))
g_return_val_if_reached (0);
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
/* Removes the complement */
return (n_content / 2) * 2 * 8;
static guint
calculate_key_size (GcrCertificateInfo *info)
{
- ASN1_TYPE asn;
+ GNode *asn;
const guchar *data, *params;
- gsize n_data, n_params, n_key;
- guint key_size = 0;
+ gsize n_data, n_params;
+ guint key_size = 0, n_bits;
guchar *key;
GQuark oid;
- data = egg_asn1_read_element (info->asn1, info->der, info->n_der, "tbsCertificate.subjectPublicKeyInfo", &n_data);
+ data = egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL), &n_data);
g_return_val_if_fail (data != NULL, 0);
- asn = egg_asn1_decode ("PKIX1.SubjectPublicKeyInfo", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data, n_data);
g_return_val_if_fail (asn, 0);
/* Figure out the algorithm */
- oid = egg_asn1_read_oid (asn, "algorithm.algorithm");
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "algorithm", "algorithm", NULL));
g_return_val_if_fail (oid, 0);
/* RSA keys are stored in the main subjectPublicKey field */
if (oid == OID_RSA_KEY) {
/* A bit string so we cannot process in place */
- key = egg_asn1_read_value (asn, "subjectPublicKey", &n_key, NULL);
+ key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "subjectPublicKey", NULL), NULL, &n_bits);
g_return_val_if_fail (key, 0);
- key_size = calculate_rsa_key_size (key, n_key / 8);
+ key_size = calculate_rsa_key_size (key, n_bits / 8);
/* The DSA key size is discovered by the prime in params */
} else if (oid == OID_DSA_KEY) {
- params = egg_asn1_read_element (asn, data, n_data, "algorithm.parameters", &n_params);
+ params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "algorithm", "parameters", NULL), &n_params);
key_size = calculate_dsa_params_size (params, n_params);
} else {
g_message ("unsupported key algorithm in certificate: %s", g_quark_to_string (oid));
}
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
g_free (key);
return key_size;
info = certificate_info_load (self);
g_return_val_if_fail (info, NULL);
- return egg_dn_read_part (info->asn1, "tbsCertificate.issuer.rdnSequence", part);
+ return egg_dn_read_part (egg_asn1x_node (info->asn1, "tbsCertificate", "issuer", "rdnSequence", NULL), part);
}
/**
info = certificate_info_load (self);
g_return_val_if_fail (info, NULL);
- return egg_dn_read (info->asn1, "tbsCertificate.issuer.rdnSequence");
+ return egg_dn_read (egg_asn1x_node (info->asn1, "tbsCertificate", "issuer", "rdnSequence", NULL));
}
/**
info = certificate_info_load (self);
g_return_val_if_fail (info, NULL);
- return egg_dn_read_part (info->asn1, "tbsCertificate.subject.rdnSequence", part);
+ return egg_dn_read_part (egg_asn1x_node (info->asn1, "tbsCertificate", "subject", "rdnSequence", NULL), part);
}
/**
info = certificate_info_load (self);
g_return_val_if_fail (info, NULL);
- return egg_dn_read (info->asn1, "tbsCertificate.issuer.rdnSequence");
+ return egg_dn_read (egg_asn1x_node (info->asn1, "tbsCertificate", "issuer", "rdnSequence", NULL));
}
/**
g_return_val_if_fail (info, NULL);
date = g_date_new ();
- if (!egg_asn1_read_date (info->asn1, "tbsCertificate.validity.notBefore", date)) {
+ if (!egg_asn1x_get_time_as_date (egg_asn1x_node (info->asn1, "tbsCertificate", "validity", "notBefore", NULL), date)) {
g_date_free (date);
return NULL;
}
g_return_val_if_fail (info, NULL);
date = g_date_new ();
- if (!egg_asn1_read_date (info->asn1, "tbsCertificate.validity.notAfter", date)) {
+ if (!egg_asn1x_get_time_as_date (egg_asn1x_node (info->asn1, "tbsCertificate", "validity", "notAfter", NULL), date)) {
g_date_free (date);
return NULL;
}
gcr_certificate_get_serial_number (GcrCertificate *self, gsize *n_length)
{
GcrCertificateInfo *info;
+ gconstpointer serial;
g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
g_return_val_if_fail (n_length, NULL);
info = certificate_info_load (self);
g_return_val_if_fail (info, NULL);
- return egg_asn1_read_value (info->asn1, "tbsCertificate.serialNumber", n_length, g_realloc);
+ serial = egg_asn1x_get_raw_value (egg_asn1x_node (info->asn1, "tbsCertificate", "serialNumber", NULL), n_length);
+ return g_memdup (serial, *n_length);
}
/**
#include "gcr-parser.h"
#include "gcr-types.h"
-#include "egg/egg-asn1.h"
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
#include "egg/egg-dn.h"
#include "egg/egg-openssl.h"
#include "egg/egg-secure-memory.h"
*/
static gboolean
-parsed_asn1_attribute (GcrParser *self, ASN1_TYPE asn, const guchar *data, gsize n_data,
+parsed_asn1_attribute (GcrParser *self, GNode *asn, const guchar *data, gsize n_data,
const gchar *part, CK_ATTRIBUTE_TYPE type)
{
const guchar *value;
g_assert (GCR_IS_PARSER (self));
g_assert (asn);
g_assert (data);
- g_assert (part);
g_assert (self->pv->parsed_attrs);
- value = egg_asn1_read_content (asn, data, n_data, part, &n_value);
+ value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, part, NULL), &n_value);
if (value == NULL)
return FALSE;
+ /* TODO: Convert to USG FROM STD */
gp11_attributes_add_data (self->pv->parsed_attrs, type, value, n_value);
return TRUE;
}
parse_der_private_key_rsa (GcrParser *self, const guchar *data, gsize n_data)
{
gint res = GCR_ERROR_UNRECOGNIZED;
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
- guint version;
+ GNode *asn = NULL;
+ gulong version;
- asn = egg_asn1_decode ("PK.RSAPrivateKey", data, n_data);
+ asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data, n_data);
if (!asn)
goto done;
parsed_ulong (self, CKA_KEY_TYPE, CKK_RSA);
res = GCR_ERROR_FAILURE;
- if (!egg_asn1_read_uint (asn, "version", &version))
+ if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version))
goto done;
/* We only support simple version */
if (version != 0) {
res = GCR_ERROR_UNRECOGNIZED;
- g_message ("unsupported version of RSA key: %u", version);
+ g_message ("unsupported version of RSA key: %lu", version);
goto done;
}
res = SUCCESS;
done:
- if (asn)
- asn1_delete_structure (&asn);
-
+ egg_asn1x_destroy (asn);
if (res == GCR_ERROR_FAILURE)
g_message ("invalid RSA key");
parse_der_private_key_dsa (GcrParser *self, const guchar *data, gsize n_data)
{
gint ret = GCR_ERROR_UNRECOGNIZED;
- int res;
- ASN1_TYPE asn;
+ GNode *asn = NULL;
- asn = egg_asn1_decode ("PK.DSAPrivateKey", data, n_data);
+ asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data, n_data);
if (!asn)
goto done;
parsed_clear (self, CKO_PRIVATE_KEY);
parsed_ulong (self, CKA_KEY_TYPE, CKK_DSA);
- res = GCR_ERROR_FAILURE;
+ ret = GCR_ERROR_FAILURE;
if (!parsed_asn1_attribute (self, asn, data, n_data, "p", CKA_PRIME) ||
!parsed_asn1_attribute (self, asn, data, n_data, "q", CKA_SUBPRIME) ||
ret = SUCCESS;
done:
- if (asn)
- asn1_delete_structure (&asn);
-
+ egg_asn1x_destroy (asn);
if (ret == GCR_ERROR_FAILURE)
g_message ("invalid DSA key");
const guchar *params, gsize n_params)
{
gint ret = GCR_ERROR_UNRECOGNIZED;
- int res;
- ASN1_TYPE asn_params = ASN1_TYPE_EMPTY;
- ASN1_TYPE asn_key = ASN1_TYPE_EMPTY;
+ GNode *asn_params = NULL;
+ GNode *asn_key = NULL;
- asn_params = egg_asn1_decode ("PK.DSAParameters", params, n_params);
- asn_key = egg_asn1_decode ("PK.DSAPrivatePart", keydata, n_keydata);
+ asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params, n_params);
+ asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata, n_keydata);
if (!asn_params || !asn_key)
goto done;
parsed_clear (self, CKO_PRIVATE_KEY);
parsed_ulong (self, CKA_KEY_TYPE, CKK_DSA);
- res = GCR_ERROR_FAILURE;
+ ret = GCR_ERROR_FAILURE;
if (!parsed_asn1_attribute (self, asn_params, params, n_params, "p", CKA_PRIME) ||
!parsed_asn1_attribute (self, asn_params, params, n_params, "q", CKA_SUBPRIME) ||
!parsed_asn1_attribute (self, asn_params, params, n_params, "g", CKA_BASE) ||
- !parsed_asn1_attribute (self, asn_key, keydata, n_keydata, "", CKA_VALUE))
+ !parsed_asn1_attribute (self, asn_key, keydata, n_keydata, NULL, CKA_VALUE))
goto done;
parsed_fire (self);
ret = SUCCESS;
done:
- if (asn_key)
- asn1_delete_structure (&asn_key);
- if (asn_params)
- asn1_delete_structure (&asn_params);
-
+ egg_asn1x_destroy (asn_key);
+ egg_asn1x_destroy (asn_params);
if (ret == GCR_ERROR_FAILURE)
g_message ("invalid DSA key");
static gint
parse_der_pkcs8_plain (GcrParser *self, const guchar *data, gsize n_data)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
gint ret;
CK_KEY_TYPE key_type;
GQuark key_algo;
gsize n_keydata;
const guchar *params;
gsize n_params;
+ GNode *asn = NULL;
ret = GCR_ERROR_UNRECOGNIZED;
- asn = egg_asn1_decode ("PKIX1.pkcs-8-PrivateKeyInfo", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data, n_data);
if (!asn)
goto done;
ret = GCR_ERROR_FAILURE;
key_type = GP11_INVALID;
- key_algo = egg_asn1_read_oid (asn, "privateKeyAlgorithm.algorithm");
+ key_algo = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "privateKeyAlgorithm", "algorithm", NULL));
if (!key_algo)
goto done;
else if (key_algo == OID_PKIX1_RSA)
goto done;
}
- keydata = egg_asn1_read_content (asn, data, n_data, "privateKey", &n_keydata);
+ keydata = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "privateKey", NULL), &n_keydata);
if (!keydata)
goto done;
- params = egg_asn1_read_element (asn, data, n_data, "privateKeyAlgorithm.parameters",
- &n_params);
+ params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL), &n_params);
ret = SUCCESS;
g_message ("invalid PKCS#8 key");
}
- if (asn)
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
return ret;
}
parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
{
PasswordState pstate = PASSWORD_STATE_INIT;
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
gcry_cipher_hd_t cih = NULL;
gcry_error_t gcry;
gint ret, r;
ret = GCR_ERROR_UNRECOGNIZED;
- asn = egg_asn1_decode ("PKIX1.pkcs-8-EncryptedPrivateKeyInfo", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data, n_data);
if (!asn)
goto done;
ret = GCR_ERROR_FAILURE;
/* Figure out the type of encryption */
- scheme = egg_asn1_read_oid (asn, "encryptionAlgorithm.algorithm");
+ scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL));
if (!scheme)
goto done;
- params = egg_asn1_read_element (asn, data, n_data, "encryptionAlgorithm.parameters", &n_params);
+ params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), &n_params);
parsed_clear (self, CKO_PRIVATE_KEY);
if (!egg_symkey_read_cipher (scheme, password, -1, params, n_params, &cih))
break;
- crypted = egg_asn1_read_value (asn, "encryptedData", &n_crypted, (EggAllocator)egg_secure_realloc);
+ crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedData", NULL), egg_secure_realloc, &n_crypted);
if (!crypted)
break;
}
/* Unpad the DER data */
- l = egg_asn1_element_length (crypted, n_crypted);
+ l = egg_asn1x_element_length (crypted, n_crypted);
if (l > 0)
n_crypted = l;
/* Try to parse the resulting key */
r = parse_der_pkcs8_plain (self, crypted, n_crypted);
- egg_secure_free (crypted);
crypted = NULL;
if (r != GCR_ERROR_UNRECOGNIZED) {
done:
if (cih)
gcry_cipher_close (cih);
- if (asn)
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
egg_secure_free (crypted);
return ret;
static gint
parse_der_certificate (GcrParser *self, const guchar *data, gsize n_data)
{
- ASN1_TYPE asn;
+ GNode *asn;
gchar *name;
- asn = egg_asn1_decode ("PKIX1.Certificate", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data);
if (asn == NULL)
return GCR_ERROR_UNRECOGNIZED;
parsed_clear (self, CKO_CERTIFICATE);
parsed_ulong (self, CKA_CERTIFICATE_TYPE, CKC_X_509);
- name = egg_dn_read_part (asn, "tbsCertificate.subject.rdnSequence", "CN");
- asn1_delete_structure (&asn);
+ name = egg_dn_read_part (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL), "CN");
+ egg_asn1x_destroy (asn);
if (name != NULL) {
parsed_label (self, name);
static gint
handle_pkcs7_signed_data (GcrParser *self, const guchar *data, gsize n_data)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
+ GNode *node;
gint ret;
- gchar *part;
const guchar *certificate;
gsize n_certificate;
int i;
ret = GCR_ERROR_UNRECOGNIZED;
- asn = egg_asn1_decode ("PKIX1.pkcs-7-SignedData", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-SignedData", data, n_data);
if (!asn)
goto done;
for (i = 0; TRUE; ++i) {
- part = g_strdup_printf ("certificates.?%u", i + 1);
- certificate = egg_asn1_read_element (asn, data, n_data, part, &n_certificate);
- g_free (part);
+ node = egg_asn1x_node (asn, "certificates", i + 1, NULL);
/* No more certificates? */
- if (!certificate)
+ if (node == NULL)
break;
+ certificate = egg_asn1x_get_raw_element (node, &n_certificate);
+
ret = parse_der_certificate (self, certificate, n_certificate);
if (ret != SUCCESS)
goto done;
ret = SUCCESS;
done:
- if (asn)
- asn1_delete_structure (&asn);
-
+ egg_asn1x_destroy (asn);
return ret;
}
static gint
parse_der_pkcs7 (GcrParser *self, const guchar *data, gsize n_data)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
+ GNode *node;
gint ret;
const guchar* content = NULL;
gsize n_content;
ret = GCR_ERROR_UNRECOGNIZED;
- asn = egg_asn1_decode ("PKIX1.pkcs-7-ContentInfo", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-ContentInfo", data, n_data);
if (!asn)
goto done;
ret = GCR_ERROR_FAILURE;
- oid = egg_asn1_read_oid (asn, "contentType");
- if (!oid)
+ node = egg_asn1x_node (asn, "contentType", NULL);
+ if (!node)
goto done;
+ oid = egg_asn1x_get_oid_as_quark (node);
+ g_return_val_if_fail (oid, GCR_ERROR_FAILURE);
+
/* Outer most one must just be plain data */
if (oid != OID_PKCS7_SIGNED_DATA) {
g_message ("unsupported outer content type in pkcs7: %s", g_quark_to_string (oid));
goto done;
}
- content = egg_asn1_read_content (asn, data, n_data, "content", &n_content);
+ content = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "content", NULL), &n_content);
if (!content)
goto done;
ret = handle_pkcs7_signed_data (self, content, n_content);
done:
- if (asn)
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
return ret;
}
static gint
handle_pkcs12_cert_bag (GcrParser *self, const guchar *data, gsize n_data)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
- const guchar *certificate;
- gsize n_certificate;
+ GNode *asn = NULL;
+ GNode *asn_content = NULL;
+ guchar *certificate;
+ const guchar *element;
+ gsize n_certificate, n_element;
gint ret;
ret = GCR_ERROR_UNRECOGNIZED;
-
- asn = egg_asn1_decode ("PKIX1.pkcs-12-CertBag", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-CertBag", data, n_data);
if (!asn)
goto done;
ret = GCR_ERROR_FAILURE;
- certificate = egg_asn1_read_content (asn, data, n_data, "certValue", &n_certificate);
- if (!certificate)
+ element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "certValue", NULL), &n_element);
+ if (!element)
goto done;
- /*
- * Wrapped in an OCTET STRING, so unwrap here, rather than allocating
- * a whole bunch more memory for a full ASN.1 parsing context.
- */
- certificate = egg_asn1_element_content (certificate, n_certificate, &n_certificate);
+ asn_content = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-Data", element, n_element);
+ if (!asn_content)
+ goto done;
+
+ certificate = egg_asn1x_get_string_as_raw (asn_content, NULL, &n_certificate);
if (!certificate)
goto done;
ret = parse_der_certificate (self, certificate, n_certificate);
done:
- if (asn)
- asn1_delete_structure (&asn);
-
+ egg_asn1x_destroy (asn_content);
+ egg_asn1x_destroy (asn);
+ g_free (certificate);
return ret;
}
static gint
handle_pkcs12_bag (GcrParser *self, const guchar *data, gsize n_data)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
gint ret, r;
- int res, count = 0;
+ guint count = 0;
GQuark oid;
const guchar *element;
gsize n_element;
ret = GCR_ERROR_UNRECOGNIZED;
- asn = egg_asn1_decode ("PKIX1.pkcs-12-SafeContents", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-SafeContents", data, n_data);
if (!asn)
goto done;
ret = GCR_ERROR_FAILURE;
/* Get the number of elements in this bag */
- res = asn1_number_of_elements (asn, "", &count);
- if (res != ASN1_SUCCESS)
- goto done;
+ count = egg_asn1x_count (asn);
/*
* Now inside each bag are multiple elements. Who comes up
*/
if (count >= 1) {
- oid = egg_asn1_read_oid (asn, "?1.bagId");
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, 1, "bagId", NULL));
if (!oid)
goto done;
- element = egg_asn1_read_content (asn, data, n_data, "?1.bagValue", &n_element);
+ element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, 1, "bagValue", NULL), &n_element);
if (!element)
goto done;
ret = SUCCESS;
done:
- if (asn)
- asn1_delete_structure (&asn);
-
+ egg_asn1x_destroy (asn);
return ret;
}
handle_pkcs12_encrypted_bag (GcrParser *self, const guchar *data, gsize n_data)
{
PasswordState pstate = PASSWORD_STATE_INIT;
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
gcry_cipher_hd_t cih = NULL;
gcry_error_t gcry;
guchar *crypted = NULL;
ret = GCR_ERROR_UNRECOGNIZED;
- asn = egg_asn1_decode ("PKIX1.pkcs-7-EncryptedData", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-EncryptedData", data, n_data);
if (!asn)
goto done;
ret = GCR_ERROR_FAILURE;
/* Check the encryption schema OID */
- scheme = egg_asn1_read_oid (asn, "encryptedContentInfo.contentEncryptionAlgorithm.algorithm");
+ scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptedContentInfo", "contentEncryptionAlgorithm", "algorithm", NULL));
if (!scheme)
goto done;
- params = egg_asn1_read_element (asn, data, n_data, "encryptedContentInfo.contentEncryptionAlgorithm.parameters", &n_params);
+ params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptedContentInfo", "contentEncryptionAlgorithm", "parameters", NULL), &n_params);
if (!params)
goto done;
goto done;
}
- crypted = egg_asn1_read_value (asn, "encryptedContentInfo.encryptedContent",
- &n_crypted, (EggAllocator)egg_secure_realloc);
+ crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedContentInfo", "encryptedContent", NULL),
+ egg_secure_realloc, &n_crypted);
if (!crypted)
goto done;
}
/* Unpad the DER data */
- l = egg_asn1_element_length (crypted, n_crypted);
+ l = egg_asn1x_element_length (crypted, n_crypted);
if (l > 0)
n_crypted = l;
done:
if (cih)
gcry_cipher_close (cih);
- if (asn)
- asn1_delete_structure (&asn);
+ egg_asn1x_destroy (asn);
egg_secure_free (crypted);
-
return ret;
}
static gint
handle_pkcs12_safe (GcrParser *self, const guchar *data, gsize n_data)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
+ GNode *asn_content = NULL;
gint ret, r;
const guchar *bag;
- gsize n_bag;
- gchar *part;
+ guchar *content = NULL;
+ gsize n_bag, n_content;
GQuark oid;
guint i;
+ GNode *node;
ret = GCR_ERROR_UNRECOGNIZED;
- asn = egg_asn1_decode ("PKIX1.pkcs-12-AuthenticatedSafe", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-AuthenticatedSafe", data, n_data);
if (!asn)
goto done;
* Inside each PKCS12 safe there are multiple bags.
*/
for (i = 0; TRUE; ++i) {
-
- part = g_strdup_printf ("?%u.contentType", i + 1);
- oid = egg_asn1_read_oid (asn, part);
- g_free (part);
+ node = egg_asn1x_node (asn, i + 1, "contentType", NULL);
/* All done? no more bags */
- if (!oid)
+ if (!node)
break;
- part = g_strdup_printf ("?%u.content", i + 1);
- bag = egg_asn1_read_content (asn, data, n_data, part, &n_bag);
- g_free (part);
+ oid = egg_asn1x_get_oid_as_quark (node);
- if (!bag) /* A parse error */
+ node = egg_asn1x_node (asn, i + 1, "content", NULL);
+ if (!node)
goto done;
+ bag = egg_asn1x_get_raw_element (node, &n_bag);
+ g_return_val_if_fail (bag, ret);
+
/* A non encrypted bag, just parse */
if (oid == OID_PKCS7_DATA) {
- /*
- * Wrapped in an OCTET STRING, so unwrap here, rather than allocating
- * a whole bunch more memory for a full ASN.1 parsing context.
- */
- bag = egg_asn1_element_content (bag, n_bag, &n_bag);
- if (!bag)
+ egg_asn1x_destroy (asn_content);
+ asn_content = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-Data", bag, n_bag);
+ if (!asn_content)
+ goto done;
+
+ g_free (content);
+ content = egg_asn1x_get_string_as_raw (asn_content, NULL, &n_content);
+ if (!content)
goto done;
- r = handle_pkcs12_bag (self, bag, n_bag);
+ r = handle_pkcs12_bag (self, content, n_content);
/* Encrypted data first needs decryption */
} else if (oid == OID_PKCS7_ENCRYPTED_DATA) {
ret = SUCCESS;
done:
- if (asn)
- asn1_delete_structure (&asn);
-
+ egg_asn1x_destroy (asn);
+ egg_asn1x_destroy (asn_content);
+ g_free (content);
return ret;
}
static gint
parse_der_pkcs12 (GcrParser *self, const guchar *data, gsize n_data)
{
- ASN1_TYPE asn = ASN1_TYPE_EMPTY;
+ GNode *asn = NULL;
+ GNode *asn_content = NULL;
gint ret;
- const guchar* content = NULL;
- gsize n_content;
+ const guchar* element = NULL;
+ guchar *content = NULL;
+ gsize n_element, n_content;
GQuark oid;
ret = GCR_ERROR_UNRECOGNIZED;
- asn = egg_asn1_decode ("PKIX1.pkcs-12-PFX", data, n_data);
+ asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-PFX", data, n_data);
if (!asn)
goto done;
- oid = egg_asn1_read_oid (asn, "authSafe.contentType");
+ ret = GCR_ERROR_FAILURE;
+
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "authSafe", "contentType", NULL));
if (!oid)
goto done;
goto done;
}
- content = egg_asn1_read_content (asn, data, n_data, "authSafe.content", &n_content);
- if (!content)
+ element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "authSafe", "content", NULL), &n_element);
+ if (!element)
goto done;
- /*
- * Wrapped in an OCTET STRING, so unwrap here, rather than allocating
- * a whole bunch more memory for a full ASN.1 parsing context.
- */
- content = egg_asn1_element_content (content, n_content, &n_content);
+ asn_content = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-Data", element, n_element);
+ if (!asn_content)
+ goto done;
+
+ content = egg_asn1x_get_string_as_raw (asn_content, g_realloc, &n_content);
if (!content)
goto done;
ret = handle_pkcs12_safe (self, content, n_content);
done:
- if (asn)
- asn1_delete_structure (&asn);
+ g_free (content);
+ egg_asn1x_destroy (asn_content);
+ egg_asn1x_destroy (asn);
return ret;
}
g_assert (decrypted);
/* Unpad the DER data */
- l = egg_asn1_element_length (decrypted, n_decrypted);
+ l = egg_asn1x_element_length (decrypted, n_decrypted);
if (l > 0)
n_decrypted = l;
#include "gcr-internal.h"
#include "gcr-simple-certificate.h"
-#include "egg/egg-asn1.h"
#include "egg/egg-hex.h"
#include <string.h>