gcr: Use GBytes immutable ref counted byte buffers
authorStef Walter <stefw@collabora.co.uk>
Wed, 16 Nov 2011 07:38:44 +0000 (08:38 +0100)
committerStef Walter <stefw@collabora.co.uk>
Wed, 16 Nov 2011 07:38:44 +0000 (08:38 +0100)
 * Copy from glib patch to EggBytes
 * This allows us to reliably build up ASN.1 structures from different
   sources, and is needed for the certificate request work.

https://bugzilla.gnome.org/show_bug.cgi?id=663291

34 files changed:
egg/Makefile.am
egg/egg-armor.c
egg/egg-armor.h
egg/egg-asn1x.c
egg/egg-asn1x.h
egg/egg-byte-array.c [deleted file]
egg/egg-byte-array.h [deleted file]
egg/egg-bytes.c [new file with mode: 0644]
egg/egg-bytes.h [new file with mode: 0644]
egg/egg-dn.c
egg/egg-dn.h
egg/egg-openssl.c
egg/egg-openssl.h
egg/egg-symkey.c
egg/egg-symkey.h
egg/tests/test-asn1.c
egg/tests/test-asn1x.c
egg/tests/test-dn.c
egg/tests/test-openssl.c
gcr/gcr-certificate-extensions.c
gcr/gcr-certificate-extensions.h
gcr/gcr-certificate-renderer.c
gcr/gcr-certificate.c
gcr/gcr-fingerprint.c
gcr/gcr-openpgp.c
gcr/gcr-openpgp.h
gcr/gcr-openssh.c
gcr/gcr-openssh.h
gcr/gcr-parser.c
gcr/tests/frob-openpgp.c
gcr/tests/test-fingerprint.c
gcr/tests/test-openpgp.c
gcr/tests/test-openssh.c
gcr/tests/test-pkcs11-certificate.c

index 5eaff47..259d522 100644 (file)
@@ -20,7 +20,7 @@ libegg_la_SOURCES = \
        egg-armor.c egg-armor.h \
        egg-asn1x.c egg-asn1x.h \
        egg-buffer.c egg-buffer.h \
-       egg-byte-array.c egg-byte-array.h \
+       egg-bytes.c egg-bytes.h \
        egg-dh.c egg-dh.h \
        egg-dn.c egg-dn.h \
        egg-error.h \
index 5a4b047..b82730b 100644 (file)
@@ -269,48 +269,52 @@ egg_armor_headers_new (void)
 }
 
 guint
-egg_armor_parse (gconstpointer data,
-                 gsize n_data,
+egg_armor_parse (EggBytes *data,
                  EggArmorCallback callback,
                  gpointer user_data)
 {
-       const gchar *beg, *end;
+       const gchar *beg, *end, *at;
        const gchar *outer_beg, *outer_end;
        guint nfound = 0;
        guchar *decoded = NULL;
        gsize n_decoded = 0;
        GHashTable *headers = NULL;
+       EggBytes *dec;
+       EggBytes *outer;
        GQuark type;
+       gsize n_at;
 
-       g_return_val_if_fail (data, 0);
-       g_return_val_if_fail (n_data, 0);
+       g_return_val_if_fail (data != NULL, 0);
+       at = egg_bytes_get_data (data);
+       n_at = egg_bytes_get_size (data);
 
-       while (n_data > 0) {
+       while (n_at > 0) {
 
                /* This returns the first character after the PEM BEGIN header */
-               beg = armor_find_begin ((const gchar*)data, n_data, &type, &outer_beg);
+               beg = armor_find_begin (at, n_at, &type, &outer_beg);
                if (beg == NULL)
                        break;
 
                g_assert (type);
 
                /* This returns the character position before the PEM END header */
-               end = armor_find_end ((const gchar*)beg,
-                                     n_data - ((const gchar*)beg - (const gchar *)data),
-                                     type, &outer_end);
+               end = armor_find_end (beg, n_at - (beg - at), type, &outer_end);
                if (end == NULL)
                        break;
 
                if (beg != end) {
                        if (armor_parse_block (beg, end - beg, &decoded, &n_decoded, &headers)) {
                                g_assert (outer_end > outer_beg);
-                               if (callback != NULL)
-                                       (callback) (type,
-                                                   decoded, n_decoded,
-                                                   outer_beg, outer_end - outer_beg,
-                                                   headers, user_data);
+                               dec = egg_bytes_new_with_free_func (decoded, n_decoded,
+                                                                   egg_secure_free, decoded);
+                               if (callback != NULL) {
+                                       outer = egg_bytes_new_with_free_func (outer_beg, outer_end - outer_beg,
+                                                                             egg_bytes_unref, egg_bytes_ref (data));
+                                       (callback) (type, dec, outer, headers, user_data);
+                                       egg_bytes_unref (outer);
+                               }
+                               egg_bytes_unref (dec);
                                ++nfound;
-                               egg_secure_free (decoded);
                                if (headers)
                                        g_hash_table_remove_all (headers);
                        }
@@ -318,8 +322,8 @@ egg_armor_parse (gconstpointer data,
 
                /* Try for another block */
                end += ARMOR_SUFF_L;
-               n_data -= (const gchar*)end - (const gchar*)data;
-               data = end;
+               n_at -= (const gchar*)end - (const gchar*)at;
+               at = end;
        }
 
        if (headers)
index e0f13d3..586a0d2 100644 (file)
 
 #include <glib.h>
 
+#include <egg/egg-bytes.h>
+
 typedef void (*EggArmorCallback) (GQuark type,
-                                  const guchar *data,
-                                  gsize n_data,
-                                  const gchar *outer,
-                                  gsize n_outer,
+                                  EggBytes *data,
+                                  EggBytes *outer,
                                   GHashTable *headers,
                                   gpointer user_data);
 
 GHashTable*      egg_armor_headers_new   (void);
 
-guint            egg_armor_parse         (gconstpointer data,
-                                          gsize n_data,
+guint            egg_armor_parse         (EggBytes *data,
                                           EggArmorCallback callback,
                                           gpointer user_data);
 
index f2d4b42..ab862e0 100644 (file)
@@ -107,6 +107,11 @@ enum {
        FLAG_RIGHT = (1<<30),
 };
 
+typedef gboolean (*Aencoder) (gpointer data,
+                              GNode *node,
+                              guchar *buf,
+                              gsize n_buf);
+
 typedef struct _Aenc Aenc;
 typedef struct _Atlv Atlv;
 typedef struct _Anode Anode;
@@ -114,8 +119,9 @@ typedef struct _Abuf Abuf;
 typedef struct _Abits Abits;
 
 struct _Aenc {
-       EggAsn1xEncoder encoder;
+       Aencoder encoder;
        gpointer data;
+       GDestroyNotify destroy;
 };
 
 struct _Atlv {
@@ -136,9 +142,7 @@ struct _Anode {
        Atlv *tlv;
        Aenc *enc;
 
-       gpointer user_data;
-       GDestroyNotify destroy;
-
+       EggBytes *backing;
        gchar* failure;
 
        gint chosen : 1;
@@ -152,13 +156,12 @@ struct _Abuf {
 
 struct _Abits {
        guint n_bits;
-       guchar *bits;
-       GDestroyNotify destroy;
+       EggBytes *bits;
 };
 
 /* Forward Declarations */
-static gboolean anode_decode_anything (GNode*, Atlv*);
-static gboolean anode_decode_anything_for_flags (GNode *, Atlv*, gint);
+static gboolean anode_decode_anything (GNode*, EggBytes*, Atlv*);
+static gboolean anode_decode_anything_for_flags (GNode *, EggBytes*, Atlv*, gint);
 static gboolean anode_validate_anything (GNode*, gboolean);
 static gboolean anode_encode_prepare (GNode*, gboolean want);
 
@@ -367,17 +370,48 @@ compare_tlvs (Atlv *tlva, Atlv *tlvb)
        return la < lb ? -1 : 1;
 }
 
+static inline EggBytes *
+anode_get_backing (GNode *node)
+{
+       Anode *an = node->data;
+       return an->backing;
+}
+
+static inline void
+anode_clr_backing (GNode *node)
+{
+       Anode *an = node->data;
+       if (an->backing)
+               egg_bytes_unref (an->backing);
+       an->backing = NULL;
+}
+
+static inline void
+anode_set_backing (GNode *node,
+                   EggBytes *backing)
+{
+       Anode *an = node->data;
+       if (backing)
+               egg_bytes_ref (backing);
+       if (an->backing)
+               egg_bytes_unref (an->backing);
+       an->backing = backing;
+}
+
 static void
-anode_set_tlv_data (GNode *node, Atlv *tlv)
+anode_set_tlv_data (GNode *node,
+                    EggBytes *backing,
+                    Atlv *tlv)
 {
        Anode *an = node->data;
-       g_assert (!an->tlv);
+       g_assert (an->tlv == NULL);
        g_assert (tlv->len >= 0);
+       anode_set_backing (node, backing);
        an->tlv = g_slice_new0 (Atlv);
        memcpy (an->tlv, tlv, sizeof (Atlv));
 }
 
-static Atlv*
+static inline Atlv *
 anode_get_tlv_data (GNode *node)
 {
        Anode *an = node->data;
@@ -398,31 +432,26 @@ anode_clr_enc_data (GNode *node)
 {
        Anode *an = node->data;
        if (an->enc) {
+               if (an->enc->destroy)
+                       (an->enc->destroy) (an->enc->data);
                g_slice_free (Aenc, an->enc);
                an->enc = NULL;
        }
 }
 
 static void
-anode_set_enc_data (GNode *node, EggAsn1xEncoder encoder, gpointer enc_data)
+anode_set_enc_data (GNode *node,
+                    Aencoder encoder,
+                    gpointer data,
+                    GDestroyNotify destroy)
 {
        Anode *an = node->data;
        g_assert (!an->enc);
        an->enc = g_slice_new0 (Aenc);
        an->enc->encoder = encoder;
-       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;
+       an->enc->data = data;
+       an->enc->destroy = destroy;
+       anode_clr_backing (node);
 }
 
 static Aenc*
@@ -462,9 +491,9 @@ static void
 anode_clear (GNode *node)
 {
        Anode *an = node->data;
+       anode_clr_backing (node);
        anode_clr_tlv_data (node);
        anode_clr_enc_data (node);
-       anode_set_user_data (node, NULL, NULL);
        g_free (an->failure);
        an->failure = NULL;
 }
@@ -483,9 +512,9 @@ static void
 abits_destroy (gpointer data)
 {
        Abits *ab = data;
-       g_assert (ab);
-       if (ab->destroy)
-               (ab->destroy) (ab->bits);
+       g_assert (ab != NULL);
+       if (ab->bits)
+               egg_bytes_unref (ab->bits);
        g_slice_free (Abits, ab);
 }
 
@@ -826,7 +855,9 @@ anode_decode_tlv_for_contents (Atlv *outer, gboolean first, Atlv *tlv)
 }
 
 static gboolean
-anode_decode_choice (GNode *node, Atlv *tlv)
+anode_decode_choice (GNode *node,
+                     EggBytes *backing,
+                     Atlv *tlv)
 {
        gboolean have = FALSE;
        GNode *child;
@@ -834,7 +865,7 @@ anode_decode_choice (GNode *node, Atlv *tlv)
 
        for (child = node->children; child; child = child->next) {
                an = (Anode*)child->data;
-               if (!have && anode_decode_anything (child, tlv)) {
+               if (!have && anode_decode_anything (child, backing, tlv)) {
                        an->chosen = 1;
                        have = TRUE;
                } else {
@@ -882,7 +913,9 @@ anode_decode_struct_any (GNode *node, Atlv *tlv)
 }
 
 static gboolean
-anode_decode_sequence_or_set (GNode *node, Atlv *outer)
+anode_decode_sequence_or_set (GNode *node,
+                              EggBytes *backing,
+                              Atlv *outer)
 {
        GNode *child;
        Atlv tlv;
@@ -902,7 +935,7 @@ anode_decode_sequence_or_set (GNode *node, Atlv *outer)
                if (!anode_decode_tlv_for_contents (outer, i == 0, &tlv))
                        return anode_failure (node, "invalid encoding of child");
 
-               if (!anode_decode_anything (child, &tlv))
+               if (!anode_decode_anything (child, backing, &tlv))
                        return FALSE;
 
                outer->len = (tlv.end - outer->buf) - outer->off;
@@ -913,7 +946,9 @@ anode_decode_sequence_or_set (GNode *node, Atlv *outer)
 }
 
 static gboolean
-anode_decode_sequence_or_set_of (GNode *node, Atlv *outer)
+anode_decode_sequence_or_set_of (GNode *node,
+                                 EggBytes *backing,
+                                 Atlv *outer)
 {
        GNode *child, *other;
        Atlv tlv;
@@ -946,7 +981,7 @@ anode_decode_sequence_or_set_of (GNode *node, Atlv *outer)
                        g_node_append (node, other);
                }
 
-               if (!anode_decode_anything (other, &tlv))
+               if (!anode_decode_anything (other, backing, &tlv))
                        return FALSE;
 
                outer->len = (tlv.end - outer->buf) - outer->off;
@@ -957,7 +992,10 @@ anode_decode_sequence_or_set_of (GNode *node, Atlv *outer)
 }
 
 static gboolean
-anode_decode_primitive (GNode *node, Atlv *tlv, gint flags)
+anode_decode_primitive (GNode *node,
+                        EggBytes *backing,
+                        Atlv *tlv,
+                        gint flags)
 {
        gint type;
 
@@ -978,18 +1016,18 @@ anode_decode_primitive (GNode *node, Atlv *tlv, gint flags)
        case TYPE_NULL:
        case TYPE_GENERALSTRING:
        case TYPE_TIME:
-               anode_set_tlv_data (node, tlv);
+               anode_set_tlv_data (node, backing, tlv);
                return TRUE;
 
        /* Transparent types */
        case TYPE_ANY:
-               anode_set_tlv_data (node, tlv);
+               anode_set_tlv_data (node, backing, tlv);
                return TRUE;
 
        case TYPE_CHOICE:
-               if (!anode_decode_choice (node, tlv))
+               if (!anode_decode_choice (node, backing, tlv))
                        return FALSE;
-               anode_set_tlv_data (node, tlv);
+               anode_set_tlv_data (node, backing, tlv);
                return TRUE;
 
        default:
@@ -1000,7 +1038,10 @@ anode_decode_primitive (GNode *node, Atlv *tlv, gint flags)
 }
 
 static gboolean
-anode_decode_structured (GNode *node, Atlv *tlv, gint flags)
+anode_decode_structured (GNode *node,
+                         EggBytes *backing,
+                         Atlv *tlv,
+                         gint flags)
 {
        gboolean definite;
        const guchar *end;
@@ -1020,7 +1061,7 @@ anode_decode_structured (GNode *node, Atlv *tlv, gint flags)
                if (!anode_decode_tlv_for_contents (tlv, TRUE, &ctlv))
                        return anode_failure (node, "invalid encoding of child");
                flags &= ~FLAG_TAG;
-               if (!anode_decode_anything_for_flags (node, &ctlv, flags))
+               if (!anode_decode_anything_for_flags (node, backing, &ctlv, flags))
                        return FALSE;
 
                /* Use most of the child's tlv */
@@ -1039,7 +1080,7 @@ anode_decode_structured (GNode *node, Atlv *tlv, gint flags)
                                return FALSE;
                        break;
                case TYPE_CHOICE:
-                       if (!anode_decode_choice (node, tlv))
+                       if (!anode_decode_choice (node, backing, tlv))
                                return FALSE;
                        break;
                case TYPE_GENERALSTRING:
@@ -1049,12 +1090,12 @@ anode_decode_structured (GNode *node, Atlv *tlv, gint flags)
                        break;
                case TYPE_SEQUENCE:
                case TYPE_SET:
-                       if (!anode_decode_sequence_or_set (node, tlv))
+                       if (!anode_decode_sequence_or_set (node, backing, tlv))
                                return FALSE;
                        break;
                case TYPE_SEQUENCE_OF:
                case TYPE_SET_OF:
-                       if (!anode_decode_sequence_or_set_of (node, tlv))
+                       if (!anode_decode_sequence_or_set_of (node, backing, tlv))
                                return FALSE;
                        break;
                default:
@@ -1080,7 +1121,7 @@ anode_decode_structured (GNode *node, Atlv *tlv, gint flags)
        g_return_val_if_fail (tlv->buf + tlv->off + tlv->len + off == end, FALSE);
 
        tlv->end = end;
-       anode_set_tlv_data (node, tlv);
+       anode_set_tlv_data (node, backing, tlv);
        return TRUE;
 }
 
@@ -1099,7 +1140,10 @@ anode_decode_option_or_default (GNode *node, Atlv *tlv, gint flags)
 }
 
 static gboolean
-anode_decode_anything_for_flags (GNode *node, Atlv *tlv, gint flags)
+anode_decode_anything_for_flags (GNode *node,
+                                 EggBytes *bytes,
+                                 Atlv *tlv,
+                                 gint flags)
 {
        gboolean ret;
        gulong tag;
@@ -1119,21 +1163,23 @@ anode_decode_anything_for_flags (GNode *node, Atlv *tlv, gint flags)
 
        /* Structured value */
        if (tlv->cls & ASN1_CLASS_STRUCTURED)
-               ret = anode_decode_structured (node, tlv, flags);
+               ret = anode_decode_structured (node, bytes, tlv, flags);
 
        /* A primitive simple value */
        else
-               ret = anode_decode_primitive (node, tlv, flags);
+               ret = anode_decode_primitive (node, bytes, tlv, flags);
 
        return ret;
 }
 
 static gboolean
-anode_decode_anything (GNode *node, Atlv *tlv)
+anode_decode_anything (GNode *node,
+                       EggBytes *bytes,
+                       Atlv *tlv)
 {
        gint flags = anode_def_flags (node);
 
-       if (!anode_decode_anything_for_flags (node, tlv, flags))
+       if (!anode_decode_anything_for_flags (node, bytes, tlv, flags))
                return anode_decode_option_or_default (node, tlv, flags);
 
        return TRUE;
@@ -1141,20 +1187,26 @@ anode_decode_anything (GNode *node, Atlv *tlv)
 
 gboolean
 egg_asn1x_decode_no_validate (GNode *asn,
-                              gconstpointer data,
-                              gsize n_data)
+                              EggBytes *data)
 {
+       const guchar *dat;
+       gsize size;
        Atlv tlv;
 
+       g_return_val_if_fail (asn != NULL, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
+
        egg_asn1x_clear (asn);
 
-       if (!anode_decode_tlv_for_data (data, (const guchar*)data + n_data, &tlv))
+       dat = egg_bytes_get_data (data);
+       size = egg_bytes_get_size (data);
+       if (!anode_decode_tlv_for_data (dat, dat + size, &tlv))
                return anode_failure (asn, "content is not encoded properly");
 
-       if (!anode_decode_anything (asn, &tlv))
+       if (!anode_decode_anything (asn, data, &tlv))
                return FALSE;
 
-       if (tlv.end - tlv.buf != n_data)
+       if (tlv.end - tlv.buf != size)
                return FALSE;
 
        return TRUE;
@@ -1162,16 +1214,14 @@ egg_asn1x_decode_no_validate (GNode *asn,
 
 gboolean
 egg_asn1x_decode (GNode *asn,
-                  gconstpointer data,
-                  gsize n_data)
+                  EggBytes *data)
 {
        gboolean ret;
 
-       g_return_val_if_fail (asn, FALSE);
-       g_return_val_if_fail (data, FALSE);
-       g_return_val_if_fail (n_data, FALSE);
+       g_return_val_if_fail (asn != NULL, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
-       ret = egg_asn1x_decode_no_validate (asn, data, n_data);
+       ret = egg_asn1x_decode_no_validate (asn, data);
        if (!ret)
                return ret;
 
@@ -1255,8 +1305,11 @@ anode_encode_cls_tag_len (guchar *data, gsize n_data, guchar cls,
 }
 
 static void
-anode_encode_tlv_and_enc (GNode *node, gsize n_data, EggAsn1xEncoder encoder,
-                          gpointer user_data, GDestroyNotify destroy)
+anode_encode_tlv_and_enc (GNode *node,
+                          gsize n_data,
+                          Aencoder encoder,
+                          gpointer user_data,
+                          GDestroyNotify destroy)
 {
        gboolean explicit = FALSE;
        gulong tag;
@@ -1328,13 +1381,15 @@ anode_encode_tlv_and_enc (GNode *node, gsize n_data, EggAsn1xEncoder encoder,
        tlv.buf = tlv.end = NULL;
 
        anode_clear (node);
-       anode_set_tlv_data (node, &tlv);
-       anode_set_enc_data (node, encoder, user_data);
-       anode_set_user_data (node, user_data, destroy);
+       anode_set_tlv_data (node, NULL, &tlv);
+       anode_set_enc_data (node, encoder, user_data, destroy);
 }
 
 static gboolean
-anode_encode_build (GNode *node, guchar *data, gsize n_data)
+anode_encode_build (GNode *node,
+                    EggBytes *backing,
+                    guchar *data,
+                    gsize n_data)
 {
        gint type;
        guchar cls;
@@ -1375,9 +1430,10 @@ anode_encode_build (GNode *node, guchar *data, gsize n_data)
        g_assert (tlv->len + tlv->off == n_data);
        tlv->buf = data;
        tlv->end = data + n_data;
+       anode_set_backing (node, backing);
 
        /* Encode in the data */
-       if (!(enc->encoder) (enc->data, data + tlv->off, tlv->len))
+       if (!(enc->encoder) (enc->data, node, data + tlv->off, tlv->len))
                return FALSE;
 
        return TRUE;
@@ -1437,7 +1493,8 @@ traverse_and_sort_set_of (GNode *node, gpointer user_data)
        GNode *child;
        GNode *next;
 
-       g_assert (allocator);
+       if (!allocator)
+               allocator = g_realloc;
 
        /* We have to sort any SET OF :( */
        if (anode_def_type (node) != TYPE_SET_OF)
@@ -1457,7 +1514,7 @@ traverse_and_sort_set_of (GNode *node, gpointer user_data)
                if (!data)
                        break;
 
-               if (!anode_encode_build (child, data, n_data)) {
+               if (!anode_encode_build (child, NULL, data, n_data)) {
                        (allocator) (data, 0);
                        continue;
                }
@@ -1485,7 +1542,22 @@ traverse_and_sort_set_of (GNode *node, gpointer user_data)
 }
 
 static gboolean
-anode_encoder_simple (gpointer user_data, guchar *data, gsize n_data)
+anode_encoder_bytes (gpointer user_data,
+                     GNode *node,
+                     guchar *data,
+                     gsize n_data)
+{
+       EggBytes *bytes = user_data;
+       g_assert (egg_bytes_get_size (bytes) >= n_data);
+       memcpy (data, egg_bytes_get_data (bytes), n_data);
+       return TRUE;
+}
+
+static gboolean
+anode_encoder_data (gpointer user_data,
+                    GNode *node,
+                    guchar *data,
+                    gsize n_data)
 {
        memcpy (data, user_data, n_data);
        return TRUE;
@@ -1493,11 +1565,13 @@ anode_encoder_simple (gpointer user_data, guchar *data, gsize n_data)
 
 static gboolean
 anode_encoder_unsigned (gpointer user_data,
+                        GNode *node,
                         guchar *data,
                         gsize n_data)
 {
+       EggBytes *value = user_data;
        gboolean sign;
-       gchar *p;
+       const gchar *p;
 
        /*
         * If top bit is set, the result would be negative in two's complement
@@ -1505,7 +1579,7 @@ anode_encoder_unsigned (gpointer user_data,
         * byte is already calculated into n_data, see egg_asn1x_set_integer_as_usg
         */
 
-       p = user_data;
+       p = egg_bytes_get_data (value);
        sign = !!(p[0] & 0x80);
        if (sign) {
                g_assert (n_data > 1);
@@ -1519,9 +1593,11 @@ anode_encoder_unsigned (gpointer user_data,
 }
 
 static gboolean
-anode_encoder_structured (gpointer user_data, guchar *data, gsize n_data)
+anode_encoder_structured (gpointer user_data,
+                          GNode *node,
+                          guchar *data,
+                          gsize n_data)
 {
-       GNode *node = user_data;
        GNode *child;
        gsize length;
        Atlv *tlv;
@@ -1531,7 +1607,8 @@ anode_encoder_structured (gpointer user_data, guchar *data, gsize n_data)
                if (tlv) {
                        length = tlv->off + tlv->len;
                        g_assert (length <= n_data);
-                       if (!anode_encode_build (child, data, length))
+                       if (!anode_encode_build (child, anode_get_backing (node),
+                                                data, length))
                                return FALSE;
                        data += length;
                        n_data -= length;
@@ -1542,7 +1619,10 @@ anode_encoder_structured (gpointer user_data, guchar *data, gsize n_data)
 }
 
 static gboolean
-anode_encoder_choice (gpointer user_data, guchar *data, gsize n_data)
+anode_encoder_choice (gpointer user_data,
+                      GNode *unused,
+                      guchar *data,
+                      gsize n_data)
 {
        GNode *node = user_data;
        Aenc *enc = NULL;
@@ -1560,7 +1640,7 @@ anode_encoder_choice (gpointer user_data, guchar *data, gsize n_data)
 
        enc = anode_get_enc_data (child);
        g_return_val_if_fail (enc, FALSE);
-       if (!(enc->encoder) (enc->data, data, n_data))
+       if (!(enc->encoder) (enc->data, node, data, n_data))
                return FALSE;
 
        /* Child's buffer matches ours */
@@ -1571,7 +1651,10 @@ anode_encoder_choice (gpointer user_data, guchar *data, gsize n_data)
 }
 
 static gboolean
-anode_encoder_bit_string (gpointer user_data, guchar *data, gsize n_data)
+anode_encoder_bit_string (gpointer user_data,
+                          GNode *node,
+                          guchar *data,
+                          gsize n_data)
 {
        Abits *ab = user_data;
        guchar empty, mask;
@@ -1588,7 +1671,7 @@ anode_encoder_bit_string (gpointer user_data, guchar *data, gsize n_data)
        data += 1;
 
        /* Fill in the actual data */
-       memcpy (data, ab->bits, len);
+       memcpy (data, egg_bytes_get_data (ab->bits), len);
 
        /* Set the extra bits to zero */
        if (len && empty) {
@@ -1611,8 +1694,10 @@ anode_encode_prepare_simple (GNode *node, gboolean want)
 
        /* Transfer the tlv data over to enc */
        enc = anode_get_enc_data (node);
-       if (enc == NULL)
-               anode_set_enc_data (node, anode_encoder_simple, (guchar*)tlv->buf + tlv->off);
+       if (enc == NULL) {
+               anode_set_enc_data (node, anode_encoder_data,
+                                   (guchar *)tlv->buf + tlv->off, NULL);
+       }
 
        tlv->buf = tlv->end = NULL;
        return TRUE;
@@ -1636,8 +1721,8 @@ anode_encode_prepare_choice (GNode *node, gboolean want)
        tlv = anode_get_tlv_data (child);
        g_return_val_if_fail (tlv, FALSE);
        anode_clr_tlv_data (node);
-       anode_set_tlv_data (node, tlv);
-       anode_set_enc_data (node, anode_encoder_choice, node);
+       anode_set_tlv_data (node, NULL, tlv);
+       anode_set_enc_data (node, anode_encoder_choice, node, NULL);
 
        return TRUE;
 
@@ -1716,20 +1801,55 @@ anode_encode_prepare (GNode *node, gboolean want)
        };
 }
 
-gpointer
-egg_asn1x_encode (GNode *asn, EggAllocator allocator, gsize *n_data)
+typedef struct {
+       EggAllocator allocator;
+       gpointer allocated;
+} AllocatorClosure;
+
+static void
+destroy_with_allocator (gpointer data)
+{
+       AllocatorClosure *closure = data;
+       g_assert (closure->allocator);
+       (closure->allocator) (closure->allocated, 0);
+       g_slice_free (AllocatorClosure, closure);
+}
+
+static EggBytes *
+new_bytes_with_allocator (EggAllocator allocator,
+                          guchar **data,
+                          gsize length)
+{
+       AllocatorClosure *closure;
+
+       if (allocator) {
+               *data = (allocator) (NULL, length + 1);
+               if (allocator == NULL)
+                       return NULL;
+               closure = g_slice_new (AllocatorClosure);
+               closure->allocated = *data;
+               closure->allocator = allocator;
+               return egg_bytes_new_with_free_func (*data, length,
+                                                    destroy_with_allocator,
+                                                    closure);
+       } else {
+               *data = g_malloc (length);
+               return egg_bytes_new_take (*data, length);
+       }
+}
+
+EggBytes *
+egg_asn1x_encode (GNode *asn,
+                  EggAllocator allocator)
 {
+       EggBytes *bytes;
        guchar *data;
        gsize length;
        Atlv *tlv;
 
-       g_return_val_if_fail (asn, NULL);
-       g_return_val_if_fail (n_data, NULL);
+       g_return_val_if_fail (asn != NULL, NULL);
        g_return_val_if_fail (anode_def_type_is_real (asn), NULL);
 
-       if (!allocator)
-               allocator = g_realloc;
-
        if (!anode_encode_prepare (asn, TRUE)) {
                anode_failure (asn, "missing value(s)");
                return NULL;
@@ -1744,18 +1864,17 @@ egg_asn1x_encode (GNode *asn, EggAllocator allocator, gsize *n_data)
 
        /* Allocate enough memory for entire thingy */
        length = tlv->off + tlv->len;
-       data = (allocator) (NULL, length + 1);
+       bytes = new_bytes_with_allocator (allocator, &data, length);
        if (data == NULL)
                return NULL;
 
-       if (anode_encode_build (asn, data, length) &&
+       if (anode_encode_build (asn, bytes, data, length) &&
            anode_validate_anything (asn, TRUE)) {
                anode_encode_commit (asn);
-               *n_data = length;
-               return data;
+               return bytes;
        }
 
-       (allocator) (data, 0);
+       egg_bytes_unref (bytes);
        anode_encode_rollback (asn);
        return NULL;
 }
@@ -2472,7 +2591,7 @@ egg_asn1x_set_boolean (GNode *node, gboolean value)
        data = g_malloc0 (1);
        if (!anode_write_boolean (value, data, &n_data))
                return FALSE;
-       anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, data, g_free);
+       anode_encode_tlv_and_enc (node, n_data, anode_encoder_data, data, g_free);
        return TRUE;
 }
 
@@ -2483,7 +2602,7 @@ egg_asn1x_set_null (GNode *node)
        g_return_val_if_fail (anode_def_type (node) == TYPE_NULL, FALSE);
 
        /* Encode zero characters */
-       anode_encode_tlv_and_enc (node, 0, anode_encoder_simple, "", NULL);
+       anode_encode_tlv_and_enc (node, 0, anode_encoder_data, "", NULL);
        return TRUE;
 }
 
@@ -2553,7 +2672,7 @@ egg_asn1x_set_enumerated (GNode *node, GQuark value)
        if (!anode_write_integer_ulong (val, data, &n_data))
                return FALSE;
 
-       anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, data, g_free);
+       anode_encode_tlv_and_enc (node, n_data, anode_encoder_data, data, g_free);
        return TRUE;
 }
 
@@ -2611,100 +2730,132 @@ egg_asn1x_set_integer_as_ulong (GNode *node, gulong value)
        data = g_malloc0 (n_data);
        if (!anode_write_integer_ulong (value, data, &n_data))
                return FALSE;
-       anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, data, g_free);
+       anode_encode_tlv_and_enc (node, n_data, anode_encoder_data, data, g_free);
        return TRUE;
 }
 
-gconstpointer
-egg_asn1x_get_integer_as_raw (GNode *node, gsize *n_data)
+EggBytes *
+egg_asn1x_get_integer_as_raw (GNode *node)
 {
+       EggBytes *backing;
        Atlv *tlv;
 
        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);
 
        tlv = anode_get_tlv_data (node);
        if (tlv == NULL || tlv->buf == NULL)
                return NULL;
 
-       *n_data = tlv->len;
-       return tlv->buf + tlv->off;
+       backing = anode_get_backing (node);
+       if (backing == NULL)
+               return NULL;
+
+       return egg_bytes_new_with_free_func (tlv->buf + tlv->off, tlv->len,
+                                            egg_bytes_unref, egg_bytes_ref (backing));
 }
 
-gconstpointer
-egg_asn1x_get_integer_as_usg (GNode *node,
-                              gsize *n_data)
+EggBytes *
+egg_asn1x_get_integer_as_usg (GNode *node)
 {
+       EggBytes *backing;
        const guchar *p;
        gboolean sign;
+       Atlv *tlv;
+       gsize n_data;
        gsize len;
 
-       g_return_val_if_fail (node, FALSE);
-       g_return_val_if_fail (n_data, FALSE);
+       g_return_val_if_fail (node != NULL, FALSE);
        g_return_val_if_fail (anode_def_type (node) == TYPE_INTEGER, FALSE);
 
-       p = egg_asn1x_get_integer_as_raw (node, &len);
+       tlv = anode_get_tlv_data (node);
+       if (tlv == NULL || tlv->buf == NULL)
+               return NULL;
+
+       backing = anode_get_backing (node);
+       if (backing == NULL)
+               return NULL;
+
+       p = tlv->buf + tlv->off;
+       len = tlv->len;
+
        sign = !!(p[0] & 0x80);
        if (sign) {
                g_warning ("invalid two's complement integer is negative, but expected unsigned");
                return NULL;
        }
 
-       *n_data = len;
+       n_data = len;
 
        /* Strip off the extra zero byte that was preventing it from being negative */
        if (p[0] == 0 && len > 1) {
                sign = !!(p[1] & 0x80);
                if (sign) {
                        p++;
-                       *n_data = len - 1;
+                       n_data = len - 1;
                }
        }
 
-       return p;
+       return egg_bytes_new_with_free_func (p, n_data,
+                                            egg_bytes_unref,
+                                            egg_bytes_ref (backing));
 }
 
-gboolean
-egg_asn1x_set_integer_as_raw (GNode *node, gconstpointer data, gsize n_data, GDestroyNotify destroy)
+void
+egg_asn1x_set_integer_as_raw (GNode *node,
+                              EggBytes *value)
+{
+       g_return_if_fail (value != NULL);
+       egg_asn1x_take_integer_as_raw (node, egg_bytes_ref (value));
+}
+
+void
+egg_asn1x_take_integer_as_raw (GNode *node,
+                               EggBytes *value)
 {
        gboolean sign;
-       guchar *p;
+       const 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);
+       g_return_if_fail (node != NULL);
+       g_return_if_fail (value != NULL);
+       g_return_if_fail (anode_def_type (node) == TYPE_INTEGER);
 
        /* Make sure the integer is properly encoded in twos complement*/
-       p = (guchar*)data;
+       p = egg_bytes_get_data (value);
        sign = !!(p[0] & 0x80);
        if (sign) {
                g_warning ("integer in egg_asn1x_set_integer_as_raw is not two's complement");
-               return FALSE;
+               return;
        }
 
-       anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, (gpointer)data, destroy);
-       return TRUE;
+       anode_encode_tlv_and_enc (node, egg_bytes_get_size (value), anode_encoder_bytes,
+                                 value, egg_bytes_unref);
 }
 
-gboolean
+void
 egg_asn1x_set_integer_as_usg (GNode *node,
-                              gconstpointer data,
-                              gsize n_data,
-                              GDestroyNotify destroy)
+                              EggBytes *value)
+{
+       g_return_if_fail (value != NULL);
+       egg_asn1x_take_integer_as_usg (node, egg_bytes_ref (value));
+}
+
+void
+egg_asn1x_take_integer_as_usg (GNode *node,
+                               EggBytes *value)
 {
        gboolean sign;
-       guchar *p;
+       const guchar *p;
+       gsize len;
 
-       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);
+       g_return_if_fail (node != NULL);
+       g_return_if_fail (value != NULL);
+       g_return_if_fail (anode_def_type (node) == TYPE_INTEGER);
 
        /* Make sure the integer is properly encoded in twos complement*/
-       p = (guchar*)data;
+       p = egg_bytes_get_data (value);
        sign = !!(p[0] & 0x80);
+       len = egg_bytes_get_size (value);
 
        /*
         * If in two's complement this would be negative, add a zero byte so
@@ -2712,50 +2863,63 @@ egg_asn1x_set_integer_as_usg (GNode *node,
         * longer. In anode_encoder_unsigned we actually add the zero byte.
         */
        if (sign)
-               n_data += 1;
+               len += 1;
 
-       anode_encode_tlv_and_enc (node, n_data, anode_encoder_unsigned,
-                                 (gpointer)data, destroy);
-       return TRUE;
+       anode_encode_tlv_and_enc (node, len, anode_encoder_unsigned,
+                                 value, egg_bytes_unref);
 }
 
-gconstpointer
-egg_asn1x_get_raw_element (GNode *node, gsize *n_element)
+EggBytes *
+egg_asn1x_get_raw_element (GNode *node)
 {
+       EggBytes *backing;
+       const guchar *p;
+       gsize len;
        Atlv *tlv;
 
-       g_return_val_if_fail (node, NULL);
-       g_return_val_if_fail (n_element, NULL);
+       g_return_val_if_fail (node != NULL, NULL);
 
        tlv = anode_get_tlv_data (node);
        if (tlv == NULL || tlv->buf == NULL)
                return NULL;
 
+       backing = anode_get_backing (node);
+       if (backing == NULL)
+               return NULL;
+
        if (anode_calc_explicit (node)) {
-               *n_element = (tlv->len + tlv->off) - tlv->oft;
-               return tlv->buf + tlv->oft;
+               len = (tlv->len + tlv->off) - tlv->oft;
+               p = tlv->buf + tlv->oft;
        } else {
-               *n_element = tlv->len + tlv->off;
-               return tlv->buf;
+               len = tlv->len + tlv->off;
+               p = tlv->buf;
        }
+
+       return egg_bytes_new_with_free_func (p, len, egg_bytes_unref,
+                                            egg_bytes_ref (backing));
 }
 
 gboolean
-egg_asn1x_set_raw_element (GNode *node, gpointer data,
-                           gsize n_data, GDestroyNotify destroy)
+egg_asn1x_set_raw_element (GNode *node,
+                           EggBytes *element)
 {
        Atlv dtlv, *tlv;
        gint oft, flags;
+       const guchar *data;
+       EggBytes *sub;
+       gsize size;
 
-       g_return_val_if_fail (node, FALSE);
-       g_return_val_if_fail (data, FALSE);
-       g_return_val_if_fail (n_data, FALSE);
+       g_return_val_if_fail (node != NULL, FALSE);
+       g_return_val_if_fail (element != NULL, FALSE);
 
        anode_clear (node);
        memset (&dtlv, 0, sizeof (dtlv));
 
+       data = egg_bytes_get_data (element);
+       size = egg_bytes_get_size (element);
+
        /* Decode the beginning TLV */
-       if (!anode_decode_tlv_for_data (data, (const guchar*)data + n_data, &dtlv))
+       if (!anode_decode_tlv_for_data (data, data + size, &dtlv))
                return FALSE;
 
        /*
@@ -2767,11 +2931,11 @@ egg_asn1x_set_raw_element (GNode *node, gpointer data,
         */
        flags = anode_def_flags (node);
        flags &= ~(FLAG_TAG | FLAG_DEFAULT | FLAG_OPTION);
-       if (!anode_decode_anything_for_flags (node, &dtlv, flags))
+       if (!anode_decode_anything_for_flags (node, element, &dtlv, flags))
                return FALSE;
 
        /* There was extra data */
-       if (dtlv.end - dtlv.buf != n_data)
+       if (dtlv.end - dtlv.buf != size)
                return FALSE;
 
        /* Clear buffer from TLV so it gets encoded */
@@ -2782,44 +2946,39 @@ egg_asn1x_set_raw_element (GNode *node, gpointer data,
        /* Explicit tagging: leave space for the outer tag */
        if (anode_calc_explicit (node)) {
                oft = anode_encode_cls_tag_len (NULL, 0, (ASN1_CLASS_STRUCTURED | ASN1_CLASS_CONTEXT_SPECIFIC),
-                                               anode_calc_tag (node), n_data);
+                                               anode_calc_tag (node), size);
 
                tlv->off += oft;
                tlv->oft = oft;
        }
 
+       sub = egg_bytes_new_with_free_func (dtlv.buf + dtlv.off, dtlv.len,
+                                           egg_bytes_unref, egg_bytes_ref (element));
+
        /* Setup encoding of the contents */
-       anode_set_enc_data (node, anode_encoder_simple, (gpointer)(dtlv.buf + dtlv.off));
-       anode_set_user_data (node, data, destroy);
+       anode_set_enc_data (node, anode_encoder_bytes, sub, egg_bytes_unref);
        return TRUE;
 }
 
-gconstpointer
-egg_asn1x_get_raw_value (GNode *node, gsize *n_content)
+EggBytes *
+egg_asn1x_get_raw_value (GNode *node)
 {
+       EggBytes *backing;
        Atlv *tlv;
 
        g_return_val_if_fail (node, NULL);
-       g_return_val_if_fail (n_content, NULL);
 
        tlv = anode_get_tlv_data (node);
        if (tlv == NULL || tlv->buf == NULL)
                return NULL;
        g_return_val_if_fail (!(tlv->cls & ASN1_CLASS_STRUCTURED), NULL);
 
-       *n_content = tlv->len;
-       return tlv->buf + tlv->off;
-}
-
-gboolean
-egg_asn1x_set_raw_value (GNode *node, gsize length, EggAsn1xEncoder encoder,
-                         gpointer user_data, GDestroyNotify destroy)
-{
-       g_return_val_if_fail (node, FALSE);
-       g_return_val_if_fail (encoder, FALSE);
+       backing = anode_get_backing (node);
+       if (backing == NULL)
+               return NULL;
 
-       anode_encode_tlv_and_enc (node, length, encoder, user_data, destroy);
-       return TRUE;
+       return egg_bytes_new_with_free_func (tlv->buf + tlv->off, tlv->len,
+                                            egg_bytes_unref, egg_bytes_ref (backing));
 }
 
 guchar*
@@ -2872,10 +3031,25 @@ egg_asn1x_set_string_as_raw (GNode *node, guchar *data, gsize n_data, GDestroyNo
        type = anode_def_type (node);
        g_return_val_if_fail (type == TYPE_OCTET_STRING || type == TYPE_GENERALSTRING, FALSE);
 
-       anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, data, destroy);
+       anode_encode_tlv_and_enc (node, n_data, anode_encoder_data, data, destroy);
        return TRUE;
 }
 
+EggBytes *
+egg_asn1x_get_string_as_bytes (GNode *node)
+{
+       gpointer raw;
+       gsize length;
+
+       g_return_val_if_fail (node != NULL, NULL);
+
+       raw = egg_asn1x_get_string_as_raw (node, NULL, &length);
+       if (raw == NULL)
+               return NULL;
+
+       return egg_bytes_new_take (raw, length);
+}
+
 gchar *
 egg_asn1x_get_bmpstring_as_utf8 (GNode *node)
 {
@@ -2933,61 +3107,67 @@ egg_asn1x_set_string_as_utf8 (GNode *node, gchar *data, GDestroyNotify destroy)
        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)
+EggBytes *
+egg_asn1x_get_bits_as_raw (GNode *node, guint *n_bits)
 {
-       Atlv *tlv;
-       gpointer bits;
+       EggBytes *backing;
        guchar padded;
+       Atlv *tlv;
 
        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;
 
+       backing = anode_get_backing (node);
+       if (backing == 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;
+       return egg_bytes_new_with_free_func (tlv->buf + tlv->off + 1, tlv->len - 1,
+                                            egg_bytes_unref, egg_bytes_ref (backing));
 }
 
-gboolean
-egg_asn1x_set_bits_as_raw (GNode *node, guchar *bits, guint n_bits, GDestroyNotify destroy)
+void
+egg_asn1x_set_bits_as_raw (GNode *node,
+                           EggBytes *value,
+                           guint n_bits)
+{
+       g_return_if_fail (value != NULL);
+       egg_asn1x_take_bits_as_raw (node, egg_bytes_ref (value), n_bits);
+}
+
+void
+egg_asn1x_take_bits_as_raw (GNode *node,
+                            EggBytes *value,
+                            guint n_bits)
 {
        gint type;
        gsize length;
        Abits *ab;
 
-       g_return_val_if_fail (node, FALSE);
-       g_return_val_if_fail (bits, FALSE);
+       g_return_if_fail (node != NULL);
+       g_return_if_fail (value != NULL);
 
        type = anode_def_type (node);
-       g_return_val_if_fail (type == TYPE_BIT_STRING, FALSE);
+       g_return_if_fail (type == TYPE_BIT_STRING);
 
        length = (n_bits / 8);
        if (n_bits % 8)
                length += 1;
 
        ab = g_slice_new0 (Abits);
-       ab->bits = bits;
+       ab->bits = egg_bytes_ref (value);
        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
@@ -3056,9 +3236,8 @@ egg_asn1x_set_bits_as_ulong (GNode *node, gulong bits, guint n_bits)
                data[(length - i) - 1] = (value >> i * 8) & 0xFF;
 
        ab = g_slice_new0 (Abits);
-       ab->bits = data;
+       ab->bits = egg_bytes_new_take (data, sizeof (gulong));
        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;
@@ -3166,7 +3345,7 @@ egg_asn1x_set_oid_as_string (GNode *node, const gchar *oid)
                return FALSE;
        }
 
-       anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, data, g_free);
+       anode_encode_tlv_and_enc (node, n_data, anode_encoder_data, data, g_free);
        return TRUE;
 }
 
@@ -3919,8 +4098,9 @@ egg_asn1x_create_quark (const ASN1_ARRAY_TYPE *defs, GQuark type)
 }
 
 GNode*
-egg_asn1x_create_and_decode (const ASN1_ARRAY_TYPE *defs, const gchar *identifier,
-                             gconstpointer data, gsize n_data)
+egg_asn1x_create_and_decode (const ASN1_ARRAY_TYPE *defs,
+                             const gchar *identifier,
+                             EggBytes *data)
 {
        GNode *asn;
 
@@ -3930,7 +4110,7 @@ egg_asn1x_create_and_decode (const ASN1_ARRAY_TYPE *defs, const gchar *identifie
        asn = egg_asn1x_create (defs, identifier);
        g_return_val_if_fail (asn, NULL);
 
-       if (!egg_asn1x_decode (asn, data, n_data)) {
+       if (!egg_asn1x_decode (asn, data)) {
                egg_asn1x_destroy (asn);
                return NULL;
        }
@@ -4156,16 +4336,17 @@ egg_asn1x_parse_time_utc (const gchar *time, gssize n_time)
  */
 
 gssize
-egg_asn1x_element_length (gconstpointer data, gsize n_data)
+egg_asn1x_element_length (const guchar *data,
+                          gsize n_data)
 {
        guchar cls;
        int counter = 0;
        int cb, len;
        gulong tag;
 
-       if (anode_decode_cls_tag (data, (const guchar*)data + n_data, &cls, &tag, &cb)) {
+       if (anode_decode_cls_tag (data, data + n_data, &cls, &tag, &cb)) {
                counter += cb;
-               len = anode_decode_length ((const guchar*)data + cb, (const guchar*)data + n_data, &cb);
+               len = anode_decode_length (data + cb, data + n_data, &cb);
                counter += cb;
                if (len >= 0) {
                        len += counter;
@@ -4178,7 +4359,9 @@ egg_asn1x_element_length (gconstpointer data, gsize n_data)
 }
 
 gconstpointer
-egg_asn1x_element_content (gconstpointer data, gsize n_data, gsize *n_content)
+egg_asn1x_element_content (const guchar *data,
+                           gsize n_data,
+                           gsize *n_content)
 {
        int counter = 0;
        guchar cls;
index 3f74655..e211b6d 100644 (file)
 
 #include <glib.h>
 
+#include "egg-bytes.h"
+
 #ifndef HAVE_EGG_ALLOCATOR
 typedef void* (*EggAllocator) (void* p, gsize);
 #define HAVE_EGG_ALLOCATOR
 #endif
 
-typedef gboolean (*EggAsn1xEncoder) (gpointer data, guchar *buf, gsize n_buf);
-
 struct static_struct_asn;
 
 GNode*              egg_asn1x_create                 (const struct static_struct_asn *defs,
@@ -43,27 +43,23 @@ GNode*              egg_asn1x_create_quark           (const struct static_struct
 
 GNode*              egg_asn1x_create_and_decode      (const struct static_struct_asn *defs,
                                                       const gchar *type,
-                                                      gconstpointer data,
-                                                      gsize n_data);
+                                                      EggBytes *data);
 
 void                egg_asn1x_dump                   (GNode *asn);
 
 void                egg_asn1x_clear                  (GNode *asn);
 
 gboolean            egg_asn1x_decode                 (GNode *asn,
-                                                      gconstpointer data,
-                                                      gsize n_data);
+                                                      EggBytes *data);
 
 gboolean            egg_asn1x_decode_no_validate     (GNode *asn,
-                                                      gconstpointer data,
-                                                      gsize n_data);
+                                                      EggBytes *data);
 
 gboolean            egg_asn1x_validate               (GNode *asn,
                                                       gboolean strict);
 
-gpointer            egg_asn1x_encode                 (GNode *asn,
-                                                      EggAllocator allocator,
-                                                      gsize *n_data);
+EggBytes *          egg_asn1x_encode                 (GNode *asn,
+                                                      EggAllocator allocator);
 
 const gchar*        egg_asn1x_message                (GNode *asn);
 
@@ -102,38 +98,28 @@ gboolean            egg_asn1x_get_integer_as_ulong   (GNode *node,
 gboolean            egg_asn1x_set_integer_as_ulong   (GNode *node,
                                                       gulong value);
 
-gconstpointer       egg_asn1x_get_integer_as_raw     (GNode *node,
-                                                      gsize *n_data);
+EggBytes *          egg_asn1x_get_integer_as_raw     (GNode *node);
 
-gboolean            egg_asn1x_set_integer_as_raw     (GNode *node,
-                                                      gconstpointer data,
-                                                      gsize n_data,
-                                                      GDestroyNotify destroy);
+void                egg_asn1x_set_integer_as_raw     (GNode *node,
+                                                      EggBytes *value);
 
-gconstpointer       egg_asn1x_get_integer_as_usg     (GNode *node,
-                                                      gsize *n_data);
+void                egg_asn1x_take_integer_as_raw    (GNode *node,
+                                                      EggBytes *value);
 
-gboolean            egg_asn1x_set_integer_as_usg     (GNode *node,
-                                                      gconstpointer data,
-                                                      gsize n_data,
-                                                      GDestroyNotify destroy);
+EggBytes *          egg_asn1x_get_integer_as_usg     (GNode *node);
 
-gconstpointer       egg_asn1x_get_raw_value          (GNode *node,
-                                                      gsize *n_content);
+void                egg_asn1x_set_integer_as_usg     (GNode *node,
+                                                      EggBytes *value);
 
-gboolean            egg_asn1x_set_raw_value          (GNode *node,
-                                                      gsize length,
-                                                      EggAsn1xEncoder encoder,
-                                                      gpointer user_data,
-                                                      GDestroyNotify destroy);
+void                egg_asn1x_take_integer_as_usg    (GNode *node,
+                                                      EggBytes *value);
+
+EggBytes *          egg_asn1x_get_raw_value          (GNode *node);
 
-gconstpointer       egg_asn1x_get_raw_element        (GNode *node,
-                                                      gsize *n_data);
+EggBytes *          egg_asn1x_get_raw_element        (GNode *node);
 
 gboolean            egg_asn1x_set_raw_element        (GNode *node,
-                                                      gpointer user_data,
-                                                      gsize n_data,
-                                                      GDestroyNotify destroy);
+                                                      EggBytes *value);
 
 guchar*             egg_asn1x_get_string_as_raw      (GNode *node,
                                                       EggAllocator allocator,
@@ -144,14 +130,18 @@ gboolean            egg_asn1x_set_string_as_raw      (GNode *node,
                                                       gsize n_data,
                                                       GDestroyNotify destroy);
 
-guchar*             egg_asn1x_get_bits_as_raw        (GNode *node,
-                                                      EggAllocator allocator,
+EggBytes *          egg_asn1x_get_string_as_bytes    (GNode *node);
+
+EggBytes *          egg_asn1x_get_bits_as_raw        (GNode *node,
                                                       guint *n_bits);
 
-gboolean            egg_asn1x_set_bits_as_raw        (GNode *node,
-                                                      guchar *data,
-                                                      guint n_bits,
-                                                      GDestroyNotify destroy);
+void                egg_asn1x_set_bits_as_raw        (GNode *node,
+                                                      EggBytes *value,
+                                                      guint n_bits);
+
+void                egg_asn1x_take_bits_as_raw       (GNode *node,
+                                                      EggBytes *value,
+                                                      guint n_bits);
 
 gboolean            egg_asn1x_get_bits_as_ulong      (GNode *node,
                                                       gulong *value,
@@ -161,7 +151,7 @@ gboolean            egg_asn1x_set_bits_as_ulong      (GNode *node,
                                                       gulong value,
                                                       guint n_bits);
 
-gchar             egg_asn1x_get_string_as_utf8     (GNode *node,
+gchar *             egg_asn1x_get_string_as_utf8     (GNode *node,
                                                       EggAllocator allocator);
 
 gboolean            egg_asn1x_set_string_as_utf8     (GNode *node,
@@ -186,7 +176,7 @@ GQuark              egg_asn1x_get_oid_as_quark       (GNode *node);
 gboolean            egg_asn1x_set_oid_as_quark       (GNode *node,
                                                       GQuark oid);
 
-gchar             egg_asn1x_get_oid_as_string      (GNode *node);
+gchar *             egg_asn1x_get_oid_as_string      (GNode *node);
 
 gboolean            egg_asn1x_set_oid_as_string      (GNode *node,
                                                       const gchar *oid);
@@ -199,10 +189,10 @@ glong               egg_asn1x_parse_time_general     (const gchar *time,
 glong               egg_asn1x_parse_time_utc         (const gchar *time,
                                                       gssize n_time);
 
-gssize              egg_asn1x_element_length         (gconstpointer data,
+gssize              egg_asn1x_element_length         (const guchar *data,
                                                       gsize n_data);
 
-gconstpointer       egg_asn1x_element_content        (gconstpointer data,
+gconstpointer       egg_asn1x_element_content        (const guchar *data,
                                                       gsize n_data,
                                                       gsize *n_content);
 
diff --git a/egg/egg-byte-array.c b/egg/egg-byte-array.c
deleted file mode 100644 (file)
index 6f9f736..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * gnome-keyring
- *
- * Copyright (C) 2010 Collabora Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General  License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General  License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Stef Walter <stefw@collabora.co.uk>
- */
-
-#include "egg-byte-array.h"
-
-#include <string.h>
-
-guint
-egg_byte_array_hash (gconstpointer v)
-{
-       const GByteArray *array = v;
-       const signed char *p;
-       guint32 h = 0;
-       gsize i;
-
-       g_assert (array);
-       g_assert (array->data);
-       p = (signed char*)array->data;
-
-       /* 31 bit hash function */
-       for (i = 0; i < array->len; ++i, ++p)
-               h = (h << 5) - h + *p;
-
-       return h;
-}
-
-gboolean
-egg_byte_array_equal (gconstpointer v1, gconstpointer v2)
-{
-       const GByteArray *array1 = v1;
-       const GByteArray *array2 = v2;
-
-       if (array1 == array2)
-               return TRUE;
-       if (!array1 || !array2)
-               return FALSE;
-
-       if (array1->len != array2->len)
-               return FALSE;
-
-       g_assert (array1->data);
-       g_assert (array2->data);
-
-       return (memcmp (array1->data, array2->data, array1->len) == 0);
-}
diff --git a/egg/egg-byte-array.h b/egg/egg-byte-array.h
deleted file mode 100644 (file)
index f03b34d..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * gnome-keyring
- *
- * Copyright (C) 2010 Collabora Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General  License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General  License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Stef Walter <stefw@collabora.co.uk>
- */
-
-#ifndef EGG_BYTE_ARRAY_H_
-#define EGG_BYTE_ARRAY_H_
-
-#include <glib.h>
-
-guint      egg_byte_array_hash    (gconstpointer v);
-
-gboolean   egg_byte_array_equal   (gconstpointer v1, gconstpointer v2);
-
-#endif /* EGG_BYTE_ARRAY_H_ */
diff --git a/egg/egg-bytes.c b/egg/egg-bytes.c
new file mode 100644 (file)
index 0000000..22bac5e
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ * Copyright Â© 2009, 2010 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt@desrt.ca>
+ */
+
+#include "config.h"
+
+#include "egg-bytes.h"
+
+#include <glib.h>
+
+#include <string.h>
+
+struct _EggBytes
+{
+  gconstpointer data;
+  gsize size;
+  gint ref_count;
+  GDestroyNotify free_func;
+  gpointer user_data;
+};
+
+/**
+ * egg_bytes_new:
+ * @data: (array length=size): the data to be used for the bytes
+ * @size: the size of @data
+ *
+ * Creates a new #EggBytes from @data.
+ *
+ * @data is copied.
+ *
+ * Returns: (transfer full): a new #EggBytes
+ *
+ * Since: 2.32
+ */
+EggBytes *
+egg_bytes_new (gconstpointer data,
+             gsize         size)
+{
+  return egg_bytes_new_take (g_memdup (data, size), size);
+}
+
+/**
+ * egg_bytes_new_take:
+ * @data: (transfer full) (array length=size): the data to be used for the bytes
+ * @size: the size of @data
+ *
+ * Creates a new #EggBytes from @data.
+ *
+ * After this call, @data belongs to the bytes and may no longer be
+ * modified by the caller.  g_free() will be called on @data when the
+ * bytes is no longer in use. Because of this @data must have been created by
+ * a call to g_malloc(), g_malloc0() or g_realloc() or by one of the many
+ * functions that wrap these calls (such as g_new(), g_strdup(), etc).
+ *
+ * Returns: (transfer full): a new #EggBytes
+ *
+ * Since: 2.32
+ */
+EggBytes *
+egg_bytes_new_take (gpointer data,
+                  gsize    size)
+{
+  return egg_bytes_new_with_free_func (data, size, g_free, data);
+}
+
+
+/**
+ * egg_bytes_new_static:
+ * @data: (array length=size): the data to be used for the bytes
+ * @size: the size of @data
+ *
+ * Creates a new #EggBytes from static data.
+ *
+ * @data must be static (ie: never modified or freed).
+ *
+ * Returns: (transfer full): a new #EggBytes
+ *
+ * Since: 2.32
+ */
+EggBytes *
+egg_bytes_new_static (gconstpointer data,
+                    gsize         size)
+{
+  return egg_bytes_new_with_free_func (data, size, NULL, NULL);
+}
+
+/**
+ * egg_bytes_new_with_free_func:
+ * @data: (array length=size): the data to be used for the bytes
+ * @size: the size of @data
+ * @free_func: the function to call to release the data
+ * @user_data: data to pass to @free_func
+ *
+ * Creates a #EggBytes from @data.
+ *
+ * When the last reference is dropped, @free_func will be called with the
+ * @user_data argument.
+ *
+ * @data must not be modified after this call is made until @free_func has
+ * been called to indicate that the bytes is no longer in use.
+ *
+ * Returns: (transfer full): a new #EggBytes
+ *
+ * Since: 2.32
+ */
+EggBytes *
+egg_bytes_new_with_free_func (gconstpointer  data,
+                            gsize          size,
+                            GDestroyNotify free_func,
+                            gpointer       user_data)
+{
+  EggBytes *bytes;
+
+  bytes = g_slice_new (EggBytes);
+  bytes->data = data;
+  bytes->size = size;
+  bytes->free_func = free_func;
+  bytes->user_data = user_data;
+  bytes->ref_count = 1;
+
+  return (EggBytes *)bytes;
+}
+
+/**
+ * egg_bytes_new_from_bytes:
+ * @bytes: a #EggBytes
+ * @offset: offset which subsection starts at
+ * @length: length of subsucsection
+ *
+ * Creates a #EggBytes which is a subsection of another #EggBytes.
+ *
+ * A reference to @bytes will be held by the newly created #EggBytes until
+ * the byte data is no longer needed.
+ *
+ * Returns: (transfer full): a new #EggBytes
+ *
+ * Since: 2.32
+ */
+EggBytes *
+egg_bytes_new_from_bytes (EggBytes  *bytes,
+                        goffset  offset,
+                        gsize    length)
+{
+  g_return_val_if_fail (bytes != NULL, NULL);
+  g_return_val_if_fail (offset <= bytes->size, NULL);
+  g_return_val_if_fail (offset + length <= bytes->size, NULL);
+
+  return egg_bytes_new_with_free_func ((gchar *)bytes->data + offset, length,
+                                     egg_bytes_unref, egg_bytes_ref (bytes));
+}
+
+/**
+ * egg_bytes_get_data:
+ * @bytes: a #EggBytes
+ *
+ * Get the byte data in the #EggBytes. This data should not be modified.
+ *
+ * This function will always return the same pointer for a given #EggBytes.
+ *
+ * Returns: a pointer to the byte data
+ *
+ * Since: 2.32
+ */
+gconstpointer
+egg_bytes_get_data (EggBytes *bytes)
+{
+  g_return_val_if_fail (bytes != NULL, NULL);
+  return bytes->data;
+}
+
+/**
+ * egg_bytes_get_size:
+ * @bytes: a #EggBytes
+ *
+ * Get the size of the byte data in the #EggBytes.
+ *
+ * This function will always return the same value for a given #EggBytes.
+ *
+ * Returns: the size
+ *
+ * Since: 2.32
+ */
+gsize
+egg_bytes_get_size (EggBytes *bytes)
+{
+  g_return_val_if_fail (bytes != NULL, 0);
+  return bytes->size;
+}
+
+
+/**
+ * egg_bytes_ref:
+ * @bytes: a #EggBytes
+ *
+ * Increase the reference count on @bytes.
+ *
+ * Returns: (transfer full): the #EggBytes
+ *
+ * Since: 2.32
+ */
+EggBytes *
+egg_bytes_ref (EggBytes *bytes)
+{
+  g_return_val_if_fail (bytes != NULL, NULL);
+
+  g_atomic_int_inc (&bytes->ref_count);
+
+  return bytes;
+}
+
+/**
+ * egg_bytes_unref:
+ * @bytes: (transfer full) (type GLib.Bytes): a #EggBytes
+ *
+ * Releases a reference on @bytes.  This may result in the bytes being
+ * freed.
+ *
+ * Since: 2.32
+ */
+void
+egg_bytes_unref (gpointer bytes)
+{
+  EggBytes *bytes_ = bytes;
+
+  g_return_if_fail (bytes_ != NULL);
+
+  if (g_atomic_int_dec_and_test (&bytes_->ref_count))
+    {
+      if (bytes_->free_func != NULL)
+        bytes_->free_func (bytes_->user_data);
+    }
+}
+
+/**
+ * egg_bytes_equal:
+ * @bytes1: (type GLib.Bytes): a pointer to a #EggBytes
+ * @bytes2: (type GLib.Bytes): a pointer to a #EggBytes to compare with @bytes1
+ *
+ * Compares the two #EggBytes values being pointed to and returns
+ * %TRUE if they are equal.
+ *
+ * This function can be passed to g_hash_table_new() as the @key_equal_func
+ * parameter, when using non-%NULL #EggBytes pointers as keys in a #GHashTable.
+ *
+ * Returns: %TRUE if the two keys match.
+ *
+ * Since: 2.32
+ */
+gboolean
+egg_bytes_equal (gconstpointer bytes1,
+               gconstpointer bytes2)
+{
+  const EggBytes *b1 = bytes1;
+  const EggBytes *b2 = bytes2;
+
+  g_return_val_if_fail (bytes1 != NULL, FALSE);
+  g_return_val_if_fail (bytes2 != NULL, FALSE);
+
+  return b1->size == b2->size &&
+         memcmp (b1->data, b2->data, b1->size) == 0;
+}
+
+/**
+ * egg_bytes_hash:
+ * @bytes: (type GLib.Bytes): a pointer to a #EggBytes key
+ *
+ * Creates an integer hash code for the byte data in the #EggBytes.
+ *
+ * This function can be passed to g_hash_table_new() as the @key_equal_func
+ * parameter, when using non-%NULL #EggBytes pointers as keys in a #GHashTable.
+ *
+ * Returns: a hash value corresponding to the key.
+ *
+ * Since: 2.32
+ */
+guint
+egg_bytes_hash (gconstpointer bytes)
+{
+  const EggBytes *a = bytes;
+  const signed char *p, *e;
+  guint32 h = 5381;
+
+  g_return_val_if_fail (bytes != NULL, 0);
+
+  for (p = (signed char *)a->data, e = (signed char *)a->data + a->size; p != e; p++)
+    h = (h << 5) + h + *p;
+
+  return h;
+}
+
+/**
+ * egg_bytes_compare:
+ * @bytes1: (type GLib.Bytes): a pointer to a #EggBytes
+ * @bytes2: (type GLib.Bytes): a pointer to a #EggBytes to compare with @bytes1
+ *
+ * Compares the two #EggBytes values.
+ *
+ * This function can be passed to g_tree_new() when using non-%NULL #EggBytes
+ * pointers as keys in a #GTree.
+ *
+ * Returns: a negative value if bytes2 is lesser, a positive value if bytes2 is
+ *          greater, and zero if bytes2 is equal to bytes1
+ *
+ * Since: 2.32
+ */
+gint
+egg_bytes_compare (gconstpointer bytes1,
+                 gconstpointer bytes2)
+{
+  const EggBytes *b1 = bytes1;
+  const EggBytes *b2 = bytes2;
+  gint ret;
+
+  g_return_val_if_fail (bytes1 != NULL, 0);
+  g_return_val_if_fail (bytes2 != NULL, 0);
+
+  ret = memcmp (b1->data, b2->data, MIN (b1->size, b2->size));
+  if (ret == 0 && b1->size != b2->size)
+      ret = b1->size < b2->size ? -1 : 1;
+  return ret;
+}
+
+/**
+ * egg_bytes_unref_to_array:
+ * @bytes: (transfer full): a #EggBytes
+ *
+ * Unreferences the bytes, and returns a new mutable #GByteArray containing
+ * the same byte data.
+ *
+ * As an optimization, the byte data is transferred to the array without copying
+ * if: this was the last reference to bytes and bytes was created with
+ * egg_bytes_new(), egg_bytes_new_take() or g_byte_array_free_to_bytes(). In all
+ * other cases the data is copied.
+ *
+ * Returns: (transfer full): a new mutable #GByteArray containing the same byte data
+ *
+ * Since: 2.32
+ */
+GByteArray *
+egg_bytes_unref_to_array (EggBytes *bytes)
+{
+  GByteArray *result = NULL;
+#if 0
+  gpointer data;
+  gsize size;
+#endif
+
+  g_return_val_if_fail (bytes != NULL, NULL);
+
+#if 0
+  data = egg_bytes_try_steal_and_unref (bytes, NULL, &size);
+  if (data != NULL)
+    {
+      /*
+       * Optimal path: if this is was the last reference, then we can have
+       * the GByteArray assume the data from this EggBytes without copying.
+       */
+      result = g_byte_array_new_take (data, size);
+    }
+  else
+#endif
+    {
+      /*
+       * Copy: Non g_malloc (or compatible) allocator, or static memory,
+       * so we have to copy, and then unref.
+       */
+      result = g_byte_array_append (g_byte_array_new (), bytes->data, bytes->size);
+      egg_bytes_unref (bytes);
+    }
+
+  return result;
+}
+
+/*
+ * The behavior of this function with regards to references cannot be easily
+ * modeled by most gobject-introspection consumers, so we use (skip).
+ */
+
+/**
+ * egg_bytes_try_steal_and_unref: (skip)
+ * @bytes: a #EggBytes
+ * @free_func: the function data is freed with, or %NULL for default
+ * @size: location to return the length of the data
+ *
+ * This is an advanced function, and seldom used.
+ *
+ * Try to take ownership of the data in the byte array. This is only successful
+ * if this is the last reference and @free_func matches the function that would
+ * have been used to free the data. This is to demonstrate that the caller
+ * is aware of the how the data in the #EggBytes was allocated. If %NULL is passed
+ * for @free_func this represents the standard Glib allocation routines.
+ *
+ * You should use %NULL instead of passing g_free() for @free_func. This is
+ * because the actual address of g_free() varies depending on how the calling
+ * application and library was linked.
+ *
+ * If the attempt to take ownership of the byte data is successful according to
+ * the above criteria, then the data is returned and @size is set to the length
+ * of the data. The #EggBytes is unreferenced and is no longer valid.
+ *
+ * If the attempt to take ownership of the byte data is unsuccessful, %NULL is
+ * returned. The #EggBytes is not unreferenced, and the caller must unreference
+ * the #EggBytes elsewhere.
+ *
+ * It is always incorrect to ignore the return value from this function.
+ *
+ * Returns: the stolen data, or %NULL if attempt failed
+ *
+ * Since: 2.32
+ */
+gpointer
+egg_bytes_try_steal_and_unref (EggBytes         *bytes,
+                             GDestroyNotify  free_func,
+                             gsize          *size)
+{
+  gpointer result;
+
+  g_return_val_if_fail (bytes != NULL, NULL);
+  g_return_val_if_fail (size != NULL, NULL);
+
+  if (free_func == NULL)
+    free_func = g_free;
+  if (bytes->free_func != free_func)
+    return NULL;
+
+  /* Are we the only reference? */
+  if (g_atomic_int_get (&bytes->ref_count) == 1)
+    {
+      *size = bytes->size;
+      result = (gpointer)bytes->data;
+      g_slice_free (EggBytes, bytes);
+      return result;
+    }
+
+  return NULL;
+}
diff --git a/egg/egg-bytes.h b/egg/egg-bytes.h
new file mode 100644 (file)
index 0000000..57cba03
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright Â© 2009, 2010 Codethink Limited
+ * Copyright Â© 2011 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt@desrt.ca>
+ *         Stef Walter <stefw@collabora.co.uk>
+ */
+
+#ifndef __EGG_BYTES_H__
+#define __EGG_BYTES_H__
+
+#include <glib/gtypes.h>
+#include <glib/garray.h>
+
+/**
+ * EggBytes:
+ *
+ * A simple refcounted data type representing an immutable byte sequence
+ * from an unspecified origin.
+ *
+ * The purpose of a #EggBytes is to keep the memory region that it holds
+ * alive for as long as anyone holds a reference to the bytes.  When
+ * the last reference count is dropped, the memory is released. Multiple
+ * unrelated callers can use byte data in the #EggBytes without coordinating
+ * their activities, resting assured that the byte data will not change or
+ * move while they hold a reference.
+ *
+ * A #EggBytes can come from many different origins that may have
+ * different procedures for freeing the memory region.  Examples are
+ * memory from g_malloc(), from memory slices, from a #GMappedFile or
+ * memory from other allocators.
+ *
+ * #EggBytes work well as keys in #GHashTable. Use egg_bytes_equal() and
+ * egg_bytes_hash() as parameters to g_hash_table_new() or g_hash_table_new_full().
+ * #EggBytes can also be used as keys in a #GTree by passing the egg_bytes_compare()
+ * function to g_tree_new().
+ *
+ * The data pointed to by this bytes must not be modified. For a mutable
+ * array of bytes see #GByteArray. Use egg_bytes_unref_to_array() to create a
+ * mutable array for a #EggBytes sequence. To create an immutable #EggBytes from
+ * a mutable #GByteArray, use the g_byte_array_free_to_bytes() function.
+ *
+ * Since: 2.32
+ **/
+
+typedef struct _EggBytes EggBytes;
+
+EggBytes *        egg_bytes_new                     (gconstpointer   data,
+                                                 gsize           size);
+
+EggBytes *        egg_bytes_new_take                (gpointer        data,
+                                                 gsize           size);
+
+EggBytes *        egg_bytes_new_static              (gconstpointer   data,
+                                                 gsize           size);
+
+EggBytes *        egg_bytes_new_with_free_func      (gconstpointer   data,
+                                                 gsize           size,
+                                                 GDestroyNotify  free_func,
+                                                 gpointer        user_data);
+
+EggBytes *        egg_bytes_new_from_bytes          (EggBytes         *bytes,
+                                                 goffset         offset,
+                                                 gsize           length);
+
+gconstpointer   egg_bytes_get_data                (EggBytes         *bytes);
+
+gsize           egg_bytes_get_size                (EggBytes         *bytes);
+
+EggBytes *        egg_bytes_ref                     (EggBytes         *bytes);
+
+void            egg_bytes_unref                   (gpointer        bytes);
+
+GByteArray *    egg_bytes_unref_to_array          (EggBytes         *bytes);
+
+gpointer        egg_bytes_try_steal_and_unref     (EggBytes         *bytes,
+                                                 GDestroyNotify  free_func,
+                                                 gsize          *size);
+
+guint           egg_bytes_hash                    (gconstpointer   bytes);
+
+gboolean        egg_bytes_equal                   (gconstpointer   bytes1,
+                                                 gconstpointer   bytes2);
+
+gint            egg_bytes_compare                 (gconstpointer   bytes1,
+                                                 gconstpointer   bytes2);
+
+#define egg_assert_equal_bytes(b, p, s) \
+       egg_assert_cmpmem (egg_bytes_get_data (b), egg_bytes_get_size (b), ==, (p), (s))
+
+#endif /* __EGG_BYTES_H__ */
index b41844e..1edcd59 100644 (file)
 static const char HEXC[] = "0123456789ABCDEF";
 
 static gchar*
-dn_print_hex_value (const guchar *data, gsize len)
+dn_print_hex_value (EggBytes *val)
 {
-       GString *result = g_string_sized_new (len * 2 + 1);
+       const gchar *data = egg_bytes_get_data (val);
+       gsize size = egg_bytes_get_size (val);
+       GString *result = g_string_sized_new (size * 2 + 1);
        gsize i;
 
        g_string_append_c (result, '#');
-       for (i = 0; i < len; ++i) {
+       for (i = 0; i < size; ++i) {
                g_string_append_c (result, HEXC[data[i] >> 4 & 0xf]);
                g_string_append_c (result, HEXC[data[i] & 0xf]);
        }
@@ -48,20 +50,22 @@ 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)
+dn_print_oid_value_parsed (GQuark oid,
+                           guint flags,
+                           EggBytes *val)
 {
        GNode *asn1, *node;
-       gconstpointer value;
-       gsize n_value;
+       EggBytes *value;
+       const gchar *data;
+       gsize size;
        gchar *result;
 
-       g_assert (data);
-       g_assert (len);
+       g_assert (val != NULL);
 
        asn1 = egg_asn1x_create_quark (pkix_asn1_tab, oid);
        g_return_val_if_fail (asn1, NULL);
 
-       if (!egg_asn1x_decode (asn1, data, len)) {
+       if (!egg_asn1x_decode (asn1, val)) {
                g_message ("couldn't decode value for OID: %s: %s",
                           g_quark_to_string (oid), egg_asn1x_message (asn1));
                egg_asn1x_destroy (asn1);
@@ -77,7 +81,9 @@ dn_print_oid_value_parsed (GQuark oid, guint flags, const guchar *data, gsize le
        else
                node = asn1;
 
-       value = egg_asn1x_get_raw_value (node, &n_value);
+       value = egg_asn1x_get_raw_value (node);
+       data = egg_bytes_get_data (value);
+       size = egg_bytes_get_size (value);
 
        /*
         * Now we make sure it's UTF-8.
@@ -87,33 +93,35 @@ dn_print_oid_value_parsed (GQuark oid, guint flags, const guchar *data, gsize le
                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 if (!g_utf8_validate (data, size, NULL)) {
+               result = dn_print_hex_value (value);
 
        } else {
-               result = g_strndup (value, n_value);
+               result = g_strndup (data, size);
        }
 
+       egg_bytes_unref (value);
        egg_asn1x_destroy (asn1);
 
        return result;
 }
 
 static gchar*
-dn_print_oid_value (GQuark oid, guint flags, const guchar *data, gsize len)
+dn_print_oid_value (GQuark oid,
+                    guint flags,
+                    EggBytes *val)
 {
        gchar *value;
 
-       g_assert (data);
-       g_assert (len);
+       g_assert (val != NULL);
 
        if (flags & EGG_OID_PRINTABLE) {
-               value = dn_print_oid_value_parsed (oid, flags, data, len);
+               value = dn_print_oid_value_parsed (oid, flags, val);
                if (value != NULL)
                        return value;
        }
 
-       return dn_print_hex_value (data, len);
+       return dn_print_hex_value (val);
 }
 
 static gchar*
@@ -122,8 +130,7 @@ dn_parse_rdn (GNode *asn)
        const gchar *name;
        guint flags;
        GQuark oid;
-       gconstpointer value;
-       gsize n_value;
+       EggBytes *value;
        gchar *display;
        gchar *result;
 
@@ -135,14 +142,15 @@ dn_parse_rdn (GNode *asn)
        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);
+       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "value", NULL));
        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);
        result = g_strconcat ((flags & EGG_OID_PRINTABLE) ? name : g_quark_to_string (oid),
                              "=", display, NULL);
        g_free (display);
 
+       egg_bytes_unref (value);
        return result;
 }
 
@@ -193,8 +201,7 @@ egg_dn_read_part (GNode *asn, const gchar *match)
 {
        gboolean done = FALSE;
        const gchar *name;
-       gconstpointer value;
-       gsize n_value;
+       EggBytes *value;
        GNode *node;
        GQuark oid;
        gint i, j;
@@ -226,10 +233,10 @@ egg_dn_read_part (GNode *asn, const gchar *match)
                        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);
+                       value = egg_asn1x_get_raw_element (node);
                        g_return_val_if_fail (value, NULL);
 
-                       return dn_print_oid_value (oid, egg_oid_get_flags (oid), value, n_value);
+                       return dn_print_oid_value (oid, egg_oid_get_flags (oid), value);
                }
        }
 
@@ -241,8 +248,7 @@ egg_dn_parse (GNode *asn, EggDnCallback callback, gpointer user_data)
 {
        gboolean done = FALSE;
        GNode *node;
-       gconstpointer value;
-       gsize n_value;
+       EggBytes *value;
        GQuark oid;
        guint i, j;
 
@@ -271,21 +277,24 @@ egg_dn_parse (GNode *asn, EggDnCallback callback, gpointer user_data)
                                break;
                        }
 
-                       value = egg_asn1x_get_raw_element (node, &n_value);
+                       value = egg_asn1x_get_raw_element (node);
 
                        if (callback)
-                               (callback) (i, oid, value, n_value, user_data);
+                               (callback) (i, oid, value, user_data);
+
+                       egg_bytes_unref (value);
                }
        }
 
        return i > 1;
 }
 
-gchar*
-egg_dn_print_value (GQuark oid, const guchar *value, gsize n_value)
+gchar *
+egg_dn_print_value (GQuark oid,
+                    EggBytes *value)
 {
-       g_return_val_if_fail (oid, NULL);
-       g_return_val_if_fail (value || !n_value, NULL);
+       g_return_val_if_fail (oid != 0, NULL);
+       g_return_val_if_fail (value != NULL, NULL);
 
-       return dn_print_oid_value (oid, egg_oid_get_flags (oid), value, n_value);
+       return dn_print_oid_value (oid, egg_oid_get_flags (oid), value);
 }
index 96fe5ff..5d36d7e 100644 (file)
@@ -26,6 +26,8 @@
 
 #include <glib.h>
 
+#include "egg/egg-bytes.h"
+
 gchar*             egg_dn_read                            (GNode *node);
 
 gchar*             egg_dn_read_part                       (GNode *node,
@@ -33,8 +35,7 @@ gchar*             egg_dn_read_part                       (GNode *node,
 
 typedef void       (*EggDnCallback)                       (guint index,
                                                            GQuark oid,
-                                                           const guchar *value,
-                                                           gsize n_value,
+                                                           EggBytes *value,
                                                            gpointer user_data);
 
 gboolean           egg_dn_parse                           (GNode *node,
@@ -42,7 +43,6 @@ gboolean           egg_dn_parse                           (GNode *node,
                                                            gpointer user_data);
 
 gchar*             egg_dn_print_value                     (GQuark oid,
-                                                           const guchar *value,
-                                                           gsize n_value);
+                                                           EggBytes *value);
 
 #endif /* EGG_DN_H_ */
index 77318f5..dc38e2b 100644 (file)
@@ -202,10 +202,12 @@ done:
        return success;
 }
 
-gboolean
-egg_openssl_decrypt_block (const gchar *dekinfo, const gchar *password,
-                           gssize n_password, const guchar *data, gsize n_data,
-                           guchar **decrypted, gsize *n_decrypted)
+guchar *
+egg_openssl_decrypt_block (const gchar *dekinfo,
+                           const gchar *password,
+                           gssize n_password,
+                           EggBytes *data,
+                           gsize *n_decrypted)
 {
        gcry_cipher_hd_t ch;
        guchar *key = NULL;
@@ -213,6 +215,7 @@ egg_openssl_decrypt_block (const gchar *dekinfo, const gchar *password,
        int gcry, ivlen;
        int algo = 0;
        int mode = 0;
+       guchar *decrypted;
 
        if (!parse_dekinfo (dekinfo, &algo, &mode, &iv))
                return FALSE;
@@ -224,43 +227,46 @@ egg_openssl_decrypt_block (const gchar *dekinfo, const gchar *password,
 
        /* IV is already set from the DEK info */
        if (!egg_symkey_generate_simple (algo, GCRY_MD_MD5, password,
-                                               n_password, iv, 8, 1, &key, NULL)) {
+                                        n_password, iv, 8, 1, &key, NULL)) {
                g_free (iv);
-               return FALSE;
+               return NULL;
        }
 
-       /* TODO: Use secure memory */
        gcry = gcry_cipher_open (&ch, algo, mode, 0);
-       g_return_val_if_fail (!gcry, FALSE);
+       g_return_val_if_fail (!gcry, NULL);
 
        gcry = gcry_cipher_setkey (ch, key, gcry_cipher_get_algo_keylen (algo));
-       g_return_val_if_fail (!gcry, FALSE);
+       g_return_val_if_fail (!gcry, NULL);
        egg_secure_free (key);
 
        /* 16 = 128 bits */
        gcry = gcry_cipher_setiv (ch, iv, ivlen);
-       g_return_val_if_fail (!gcry, FALSE);
+       g_return_val_if_fail (!gcry, NULL);
        g_free (iv);
 
        /* Allocate output area */
-       *n_decrypted = n_data;
-       *decrypted = egg_secure_alloc (n_data);
+       *n_decrypted = egg_bytes_get_size (data);
+       decrypted = egg_secure_alloc (*n_decrypted);
 
-       gcry = gcry_cipher_decrypt (ch, *decrypted, *n_decrypted, (void*)data, n_data);
+       gcry = gcry_cipher_decrypt (ch, decrypted, *n_decrypted,
+                                   egg_bytes_get_data (data),
+                                   egg_bytes_get_size (data));
        if (gcry) {
-               egg_secure_free (*decrypted);
-               g_return_val_if_reached (FALSE);
+               egg_secure_free (decrypted);
+               g_return_val_if_reached (NULL);
        }
 
        gcry_cipher_close (ch);
 
-       return TRUE;
+       return decrypted;
 }
 
-gboolean
-egg_openssl_encrypt_block (const gchar *dekinfo, const gchar *password,
-                                gssize n_password, const guchar *data, gsize n_data,
-                                guchar **encrypted, gsize *n_encrypted)
+guchar *
+egg_openssl_encrypt_block (const gchar *dekinfo,
+                           const gchar *password,
+                           gssize n_password,
+                           EggBytes *data,
+                           gsize *n_encrypted)
 {
        gsize n_overflow, n_batch, n_padding;
        gcry_cipher_hd_t ch;
@@ -270,65 +276,71 @@ egg_openssl_encrypt_block (const gchar *dekinfo, const gchar *password,
        int gcry, ivlen;
        int algo = 0;
        int mode = 0;
+       gsize n_data;
+       guchar *encrypted;
+       const guchar *dat;
 
        if (!parse_dekinfo (dekinfo, &algo, &mode, &iv))
-               g_return_val_if_reached (FALSE);
+               g_return_val_if_reached (NULL);
 
        ivlen = gcry_cipher_get_algo_blklen (algo);
 
        /* We assume the iv is at least as long as at 8 byte salt */
-       g_return_val_if_fail (ivlen >= 8, FALSE);
+       g_return_val_if_fail (ivlen >= 8, NULL);
 
        /* IV is already set from the DEK info */
        if (!egg_symkey_generate_simple (algo, GCRY_MD_MD5, password,
                                                n_password, iv, 8, 1, &key, NULL))
-               g_return_val_if_reached (FALSE);
+               g_return_val_if_reached (NULL);
 
        gcry = gcry_cipher_open (&ch, algo, mode, 0);
-       g_return_val_if_fail (!gcry, FALSE);
+       g_return_val_if_fail (!gcry, NULL);
 
        gcry = gcry_cipher_setkey (ch, key, gcry_cipher_get_algo_keylen (algo));
-       g_return_val_if_fail (!gcry, FALSE);
+       g_return_val_if_fail (!gcry, NULL);
        egg_secure_free (key);
 
        /* 16 = 128 bits */
        gcry = gcry_cipher_setiv (ch, iv, ivlen);
-       g_return_val_if_fail (!gcry, FALSE);
+       g_return_val_if_fail (!gcry, NULL);
        g_free (iv);
 
+       dat = egg_bytes_get_data (data);
+       n_data = egg_bytes_get_size (data);
+
        /* Allocate output area */
        n_overflow = (n_data % ivlen);
        n_padding = n_overflow ? (ivlen - n_overflow) : 0;
        n_batch = n_data - n_overflow;
        *n_encrypted = n_data + n_padding;
-       *encrypted = g_malloc0 (*n_encrypted);
+       encrypted = g_malloc0 (*n_encrypted);
 
        g_assert (*n_encrypted % ivlen == 0);
        g_assert (*n_encrypted >= n_data);
        g_assert (*n_encrypted == n_batch + n_overflow + n_padding);
 
        /* Encrypt everything but the last bit */
-       gcry = gcry_cipher_encrypt (ch, *encrypted, n_batch, (void*)data, n_batch);
+       gcry = gcry_cipher_encrypt (ch, encrypted, n_batch, dat, n_batch);
        if (gcry) {
-               g_free (*encrypted);
-               g_return_val_if_reached (FALSE);
+               g_free (encrypted);
+               g_return_val_if_reached (NULL);
        }
 
        /* Encrypt the padded block */
        if (n_overflow) {
                padded = egg_secure_alloc (ivlen);
                memset (padded, 0, ivlen);
-               memcpy (padded, data + n_batch, n_overflow);
-               gcry = gcry_cipher_encrypt (ch, *encrypted + n_batch, ivlen, padded, ivlen);
+               memcpy (padded, dat + n_batch, n_overflow);
+               gcry = gcry_cipher_encrypt (ch, encrypted + n_batch, ivlen, padded, ivlen);
                egg_secure_free (padded);
                if (gcry) {
-                       g_free (*encrypted);
-                       g_return_val_if_reached (FALSE);
+                       g_free (encrypted);
+                       g_return_val_if_reached (NULL);
                }
        }
 
        gcry_cipher_close (ch);
-       return TRUE;
+       return encrypted;
 }
 
 const gchar*
index a998c9e..642d906 100644 (file)
 
 #include <glib.h>
 
-int              egg_openssl_parse_algo        (const gchar *name, int *mode);
+#include <egg/egg-bytes.h>
 
-gboolean         egg_openssl_encrypt_block     (const gchar *dekinfo, const gchar *password,
-                                                gssize n_password, const guchar *data, gsize n_data,
-                                                guchar **encrypted, gsize *n_encrypted);
+int              egg_openssl_parse_algo        (const gchar *name, int *mode);
 
-gboolean         egg_openssl_decrypt_block     (const gchar *dekinfo, const gchar *password,
-                                                gssize n_password, const guchar *data, gsize n_data,
-                                                guchar **decrypted, gsize *n_decrypted);
+guchar *         egg_openssl_encrypt_block     (const gchar *dekinfo,
+                                                const gchar *password,
+                                                gssize n_password,
+                                                EggBytes *data,
+                                                gsize *n_encrypted);
+
+guchar *         egg_openssl_decrypt_block     (const gchar *dekinfo,
+                                                const gchar *password,
+                                                gssize n_password,
+                                                EggBytes *data,
+                                                gsize *n_decrypted);
 
 const gchar*     egg_openssl_get_dekinfo       (GHashTable *headers);
 
index 5f5070b..835d4a3 100644 (file)
@@ -658,14 +658,17 @@ egg_symkey_generate_pbkdf2 (int cipher_algo, int hash_algo,
 
 
 static gboolean
-read_cipher_pkcs5_pbe (int cipher_algo, int cipher_mode, int hash_algo,
-                       const gchar *password, gsize n_password, const guchar *data,
-                       gsize n_data, gcry_cipher_hd_t *cih)
+read_cipher_pkcs5_pbe (int cipher_algo,
+                       int cipher_mode,
+                       int hash_algo,
+                       const gchar *password,
+                       gsize n_password,
+                       EggBytes *data,
+                       gcry_cipher_hd_t *cih)
 {
        GNode *asn = NULL;
        gcry_error_t gcry;
-       gconstpointer salt;
-       gsize n_salt;
+       EggBytes *salt = NULL;
        gsize n_block, n_key;
        gulong iterations;
        guchar *key = NULL;
@@ -674,7 +677,7 @@ read_cipher_pkcs5_pbe (int cipher_algo, int cipher_mode, int hash_algo,
 
        g_return_val_if_fail (cipher_algo != 0 && cipher_mode != 0, FALSE);
        g_return_val_if_fail (cih != NULL, FALSE);
-       g_return_val_if_fail (data != NULL && n_data != 0, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
        *cih = NULL;
        ret = FALSE;
@@ -687,10 +690,10 @@ read_cipher_pkcs5_pbe (int cipher_algo, int cipher_mode, int hash_algo,
        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))
+       if (!egg_asn1x_decode (asn, data))
                goto done;
 
-       salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", NULL), &n_salt);
+       salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", NULL));
        if (!salt)
                goto done;
        if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterationCount", NULL), &iterations))
@@ -700,8 +703,9 @@ read_cipher_pkcs5_pbe (int cipher_algo, int cipher_mode, int hash_algo,
        g_return_val_if_fail (n_key > 0, FALSE);
        n_block = gcry_cipher_get_algo_blklen (cipher_algo);
 
-       if (!egg_symkey_generate_pbe (cipher_algo, hash_algo, password, n_password, salt,
-                                     n_salt, iterations, &key, n_block > 1 ? &iv : NULL))
+       if (!egg_symkey_generate_pbe (cipher_algo, hash_algo, password, n_password,
+                                     egg_bytes_get_data (salt), egg_bytes_get_size (salt),
+                                     iterations, &key, n_block > 1 ? &iv : NULL))
                goto done;
 
        gcry = gcry_cipher_open (cih, cipher_algo, cipher_mode, 0);
@@ -718,6 +722,8 @@ read_cipher_pkcs5_pbe (int cipher_algo, int cipher_mode, int hash_algo,
 
 done:
        g_free (iv);
+       if (salt != NULL)
+               egg_bytes_unref (salt);
        egg_secure_free (key);
        egg_asn1x_destroy (asn);
 
@@ -725,12 +731,12 @@ done:
 }
 
 static gboolean
-setup_pkcs5_rc2_params (const guchar *data, guchar n_data, gcry_cipher_hd_t cih)
+setup_pkcs5_rc2_params (EggBytes *data,
+                        gcry_cipher_hd_t cih)
 {
        GNode *asn = NULL;
        gcry_error_t gcry;
-       const guchar *iv;
-       gsize n_iv;
+       EggBytes *iv = NULL;
        gulong version;
        gboolean ret = FALSE;
 
@@ -739,90 +745,99 @@ setup_pkcs5_rc2_params (const guchar *data, guchar n_data, gcry_cipher_hd_t cih)
        asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-5-rc2-CBC-params");
        g_return_val_if_fail (asn, FALSE);
 
-       if (!egg_asn1x_decode (asn, data, n_data))
+       if (!egg_asn1x_decode (asn, data))
                goto done;
 
        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);
+       iv = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "iv", NULL));
        if (!iv)
                goto done;
 
-       gcry = gcry_cipher_setiv (cih, iv, n_iv);
+       gcry = gcry_cipher_setiv (cih, egg_bytes_get_data (iv), egg_bytes_get_size (iv));
        if (gcry != 0) {
-               g_message ("couldn't set %lu byte iv on cipher", (gulong)n_iv);
+               g_message ("couldn't set %lu byte iv on cipher", (gulong)egg_bytes_get_size (iv));
                goto done;
        }
 
        ret = TRUE;
 
 done:
+       if (iv != NULL)
+               egg_bytes_unref (iv);
        egg_asn1x_destroy (asn);
        return ret;
 }
 
 static gboolean
-setup_pkcs5_des_params (const guchar *data, guchar n_data, gcry_cipher_hd_t cih)
+setup_pkcs5_des_params (EggBytes *data,
+                        gcry_cipher_hd_t cih)
 {
        GNode *asn = NULL;
        gcry_error_t gcry;
-       gconstpointer iv;
-       gsize n_iv;
+       EggBytes *iv;
+       gboolean ret;
 
        g_assert (data);
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "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);
        if (!asn)
-               asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-des-CBC-params", data, n_data);
+               asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-des-CBC-params", data);
        if (!asn)
                return FALSE;
 
-       iv = egg_asn1x_get_raw_value (asn, &n_iv);
+       iv = egg_asn1x_get_raw_value (asn);
        egg_asn1x_destroy (asn);
 
        if (!iv)
                return FALSE;
 
-       gcry = gcry_cipher_setiv (cih, iv, n_iv);
-
+       gcry = gcry_cipher_setiv (cih, egg_bytes_get_data (iv), egg_bytes_get_size (iv));
        if (gcry != 0) {
-               g_message ("couldn't set %lu byte iv on cipher", (gulong)n_iv);
-               return FALSE;
+               g_message ("couldn't set %lu byte iv on cipher", (gulong)egg_bytes_get_size (iv));
+               ret = FALSE;
+       } else {
+               ret = TRUE;
        }
 
-       return TRUE;
+       egg_bytes_unref (iv);
+       return ret;
 }
 
 static gboolean
-setup_pkcs5_pbkdf2_params (const gchar *password, gsize n_password, const guchar *data,
-                           gsize n_data, int cipher_algo, gcry_cipher_hd_t cih)
+setup_pkcs5_pbkdf2_params (const gchar *password,
+                           gsize n_password,
+                           EggBytes *data,
+                           int cipher_algo,
+                           gcry_cipher_hd_t cih)
 {
        GNode *asn = NULL;
        gboolean ret;
        gcry_error_t gcry;
        guchar *key = NULL;
-       const guchar *salt;
-       gsize n_salt, n_key;
+       EggBytes *salt = NULL;
+       gsize n_key;
        gulong iterations;
 
        g_assert (cipher_algo);
-       g_assert (data);
+       g_assert (data != NULL);
 
        ret = FALSE;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-PBKDF2-params", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-PBKDF2-params", data);
        if (!asn)
                goto done;
 
        if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterationCount", NULL), &iterations))
                iterations = 1;
-       salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", "specified", NULL), &n_salt);
+       salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", "specified", NULL));
        if (!salt)
                goto done;
 
        if (!egg_symkey_generate_pbkdf2 (cipher_algo, GCRY_MD_SHA1, password, n_password,
-                                        salt, n_salt, iterations, &key, NULL))
+                                        egg_bytes_get_data (salt), egg_bytes_get_size (salt),
+                                        iterations, &key, NULL))
                goto done;
 
        n_key = gcry_cipher_get_algo_keylen (cipher_algo);
@@ -837,32 +852,35 @@ setup_pkcs5_pbkdf2_params (const gchar *password, gsize n_password, const guchar
        ret = TRUE;
 
 done:
+       if (salt != NULL)
+               egg_bytes_unref (salt);
        egg_secure_free (key);
        egg_asn1x_destroy (asn);
        return ret;
 }
 
 static gboolean
-read_cipher_pkcs5_pbes2 (const gchar *password, gsize n_password, const guchar *data,
-                         gsize n_data, gcry_cipher_hd_t *cih)
+read_cipher_pkcs5_pbes2 (const gchar *password,
+                         gsize n_password,
+                         EggBytes *data,
+                         gcry_cipher_hd_t *cih)
 {
        GNode *asn = NULL;
        gboolean r, ret;
        GQuark key_deriv_algo, enc_oid;
+       EggBytes *params = NULL;
        gcry_error_t gcry;
        int algo, mode;
-       gconstpointer params;
-       gsize n_params;
 
        g_return_val_if_fail (cih != NULL, FALSE);
-       g_return_val_if_fail (data != NULL && n_data != 0, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
        init_quarks ();
 
        *cih = NULL;
        ret = FALSE;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-PBES2-params", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-5-PBES2-params", data);
        if (!asn)
                goto done;
 
@@ -893,17 +911,17 @@ read_cipher_pkcs5_pbes2 (const gchar *password, gsize n_password, const guchar *
        }
 
        /* Read out the parameters */
-       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionScheme", "parameters", NULL), &n_params);
+       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionScheme", "parameters", NULL));
        if (!params)
                goto done;
 
        switch (algo) {
        case GCRY_CIPHER_3DES:
        case GCRY_CIPHER_DES:
-               r = setup_pkcs5_des_params (params, n_params, *cih);
+               r = setup_pkcs5_des_params (params, *cih);
                break;
        case GCRY_CIPHER_RFC2268_128:
-               r = setup_pkcs5_rc2_params (params, n_params, *cih);
+               r = setup_pkcs5_rc2_params (params, *cih);
                break;
        default:
                /* Should have been caught on the oid check above */
@@ -924,11 +942,12 @@ read_cipher_pkcs5_pbes2 (const gchar *password, gsize n_password, const guchar *
                goto done;
        }
 
-       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "keyDerivationFunc", "parameters", NULL), &n_params);
+       egg_bytes_unref (params);
+       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "keyDerivationFunc", "parameters", NULL));
        if (!params)
                goto done;
 
-       ret = setup_pkcs5_pbkdf2_params (password, n_password, params, n_params, algo, *cih);
+       ret = setup_pkcs5_pbkdf2_params (password, n_password, params, algo, *cih);
 
 done:
        if (ret != TRUE && *cih) {
@@ -936,20 +955,24 @@ done:
                *cih = NULL;
        }
 
+       if (params != NULL)
+               egg_bytes_unref (params);
        egg_asn1x_destroy (asn);
        return ret;
 }
 
 static gboolean
-read_cipher_pkcs12_pbe (int cipher_algo, int cipher_mode, const gchar *password,
-                        gsize n_password, const guchar *data, gsize n_data,
+read_cipher_pkcs12_pbe (int cipher_algo,
+                        int cipher_mode,
+                        const gchar *password,
+                        gsize n_password,
+                        EggBytes *data,
                         gcry_cipher_hd_t *cih)
 {
        GNode *asn = NULL;
        gcry_error_t gcry;
        gboolean ret;
-       const guchar *salt;
-       gsize n_salt;
+       EggBytes *salt = NULL;
        gsize n_block, n_key;
        gulong iterations;
        guchar *key = NULL;
@@ -957,7 +980,7 @@ read_cipher_pkcs12_pbe (int cipher_algo, int cipher_mode, const gchar *password,
 
        g_return_val_if_fail (cipher_algo != 0 && cipher_mode != 0, FALSE);
        g_return_val_if_fail (cih != NULL, FALSE);
-       g_return_val_if_fail (data != NULL && n_data != 0, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
        *cih = NULL;
        ret = FALSE;
@@ -966,11 +989,11 @@ read_cipher_pkcs12_pbe (int cipher_algo, int cipher_mode, const gchar *password,
        if (gcry_cipher_algo_info (cipher_algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0)
                goto done;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-PbeParams", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-PbeParams", data);
        if (!asn)
                goto done;
 
-       salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", NULL), &n_salt);
+       salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "salt", NULL));
        if (!salt)
                goto done;
        if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterations", NULL), &iterations))
@@ -980,9 +1003,9 @@ read_cipher_pkcs12_pbe (int cipher_algo, int cipher_mode, const gchar *password,
        n_key = gcry_cipher_get_algo_keylen (cipher_algo);
 
        /* Generate IV and key using salt read above */
-       if (!egg_symkey_generate_pkcs12 (cipher_algo, GCRY_MD_SHA1, password,
-                                               n_password, salt, n_salt, iterations, &key,
-                                               n_block > 1 ? &iv : NULL))
+       if (!egg_symkey_generate_pkcs12 (cipher_algo, GCRY_MD_SHA1, password, n_password,
+                                        egg_bytes_get_data (salt), egg_bytes_get_size (salt),
+                                        iterations, &key, n_block > 1 ? &iv : NULL))
                goto done;
 
        gcry = gcry_cipher_open (cih, cipher_algo, cipher_mode, 0);
@@ -1003,6 +1026,8 @@ done:
                *cih = NULL;
        }
 
+       if (salt != NULL)
+               egg_bytes_unref (salt);
        g_free (iv);
        egg_secure_free (key);
        egg_asn1x_destroy (asn);
@@ -1013,8 +1038,7 @@ static gboolean
 read_mac_pkcs12_pbe (int hash_algo,
                      const gchar *password,
                      gsize n_password,
-                     const guchar *data,
-                     gsize n_data,
+                     EggBytes *data,
                      gcry_md_hd_t *mdh,
                      gsize *digest_len)
 {
@@ -1022,14 +1046,13 @@ read_mac_pkcs12_pbe (int hash_algo,
        gcry_error_t gcry;
        gboolean ret;
        gsize n_key;
-       const guchar *salt;
-       gsize n_salt;
+       EggBytes *salt = NULL;
        gulong iterations;
        guchar *key = NULL;
 
        g_return_val_if_fail (hash_algo != 0, FALSE);
        g_return_val_if_fail (mdh != NULL, FALSE);
-       g_return_val_if_fail (data != NULL && n_data != 0, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
        *mdh = NULL;
        ret = FALSE;
@@ -1038,11 +1061,11 @@ read_mac_pkcs12_pbe (int hash_algo,
        if (gcry_md_algo_info (hash_algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0)
                goto done;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-MacData", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-12-MacData", data);
        if (!asn)
                goto done;
 
-       salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "macSalt", NULL), &n_salt);
+       salt = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "macSalt", NULL));
        if (!salt)
                goto done;
        if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterations", NULL), &iterations))
@@ -1052,7 +1075,8 @@ read_mac_pkcs12_pbe (int hash_algo,
 
        /* Generate IV and key using salt read above */
        if (!egg_symkey_generate_pkcs12_mac (hash_algo, password, n_password,
-                                            salt, n_salt, iterations, &key))
+                                            egg_bytes_get_data (salt), egg_bytes_get_size (salt),
+                                            iterations, &key))
                goto done;
 
        gcry = gcry_md_open (mdh, hash_algo, GCRY_MD_FLAG_HMAC);
@@ -1073,82 +1097,86 @@ done:
                *mdh = NULL;
        }
 
+       if (salt != NULL)
+               egg_bytes_unref (salt);
        egg_secure_free (key);
        egg_asn1x_destroy (asn);
        return ret;
 }
 
 gboolean
-egg_symkey_read_cipher (GQuark oid_scheme, const gchar *password, gsize n_password,
-                        const guchar *data, gsize n_data, gcry_cipher_hd_t *cih)
+egg_symkey_read_cipher (GQuark oid_scheme,
+                        const gchar *password,
+                        gsize n_password,
+                        EggBytes *data,
+                        gcry_cipher_hd_t *cih)
 {
        gboolean ret = FALSE;
 
        g_return_val_if_fail (oid_scheme != 0, FALSE);
        g_return_val_if_fail (cih != NULL, FALSE);
-       g_return_val_if_fail (data != NULL && n_data != 0, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
        init_quarks ();
 
        /* PKCS#5 PBE */
        if (oid_scheme == OID_PBE_MD2_DES_CBC)
                ret = read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
-                                            GCRY_MD_MD2, password, n_password, data, n_data, cih);
+                                            GCRY_MD_MD2, password, n_password, data, cih);
 
        else if (oid_scheme == OID_PBE_MD2_RC2_CBC)
                /* RC2-64 has no implementation in libgcrypt */;
 
        else if (oid_scheme == OID_PBE_MD5_DES_CBC)
                ret = read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
-                                            GCRY_MD_MD5, password, n_password, data, n_data, cih);
+                                            GCRY_MD_MD5, password, n_password, data, cih);
        else if (oid_scheme == OID_PBE_MD5_RC2_CBC)
                /* RC2-64 has no implementation in libgcrypt */;
 
        else if (oid_scheme == OID_PBE_SHA1_DES_CBC)
                ret = read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
-                                            GCRY_MD_SHA1, password, n_password, data, n_data, cih);
+                                            GCRY_MD_SHA1, password, n_password, data, cih);
        else if (oid_scheme == OID_PBE_SHA1_RC2_CBC)
                /* RC2-64 has no implementation in libgcrypt */;
 
 
        /* PKCS#5 PBES2 */
        else if (oid_scheme == OID_PBES2)
-               ret = read_cipher_pkcs5_pbes2 (password, n_password, data, n_data, cih);
+               ret = read_cipher_pkcs5_pbes2 (password, n_password, data, cih);
 
 
        /* PKCS#12 PBE */
        else if (oid_scheme == OID_PKCS12_PBE_ARCFOUR_SHA1)
                ret = read_cipher_pkcs12_pbe (GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM,
-                                             password, n_password, data, n_data, cih);
+                                             password, n_password, data, cih);
        else if (oid_scheme == OID_PKCS12_PBE_RC4_40_SHA1)
                /* RC4-40 has no implementation in libgcrypt */;
 
        else if (oid_scheme == OID_PKCS12_PBE_3DES_SHA1)
                ret = read_cipher_pkcs12_pbe (GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC,
-                                             password, n_password, data, n_data, cih);
+                                             password, n_password, data, cih);
        else if (oid_scheme == OID_PKCS12_PBE_2DES_SHA1)
                /* 2DES has no implementation in libgcrypt */;
 
        else if (oid_scheme == OID_PKCS12_PBE_RC2_128_SHA1)
                ret = read_cipher_pkcs12_pbe (GCRY_CIPHER_RFC2268_128, GCRY_CIPHER_MODE_CBC,
-                                             password, n_password, data, n_data, cih);
+                                             password, n_password, data, cih);
 
        else if (oid_scheme == OID_PKCS12_PBE_RC2_40_SHA1)
                ret = read_cipher_pkcs12_pbe (GCRY_CIPHER_RFC2268_40, GCRY_CIPHER_MODE_CBC,
-                                             password, n_password, data, n_data, cih);
+                                             password, n_password, data, cih);
 
        if (ret == FALSE)
-               g_message ("unsupported or invalid cipher: %s", g_quark_to_string (oid_scheme));
+               g_message ("unsupported or invalid cipher: %s", g_quark_to_string (oid_scheme));
 
-       return ret;
+       return ret;
 }
 
 gboolean
 egg_symkey_read_mac (GQuark oid_scheme,
                      const gchar *password,
                      gsize n_password,
-                     const guchar *data,
-                     gsize n_data,
+                     EggBytes *data,
                      gcry_md_hd_t *mdh,
                      gsize *digest_len)
 {
@@ -1156,17 +1184,18 @@ egg_symkey_read_mac (GQuark oid_scheme,
 
        g_return_val_if_fail (oid_scheme != 0, FALSE);
        g_return_val_if_fail (mdh != NULL, FALSE);
-       g_return_val_if_fail (data != NULL && n_data != 0, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
        init_quarks ();
 
        /* PKCS#12 MAC with SHA-1 */
        if (oid_scheme == OID_SHA1)
                ret = read_mac_pkcs12_pbe (GCRY_MD_SHA1, password, n_password,
-                                          data, n_data, mdh, digest_len);
+                                          data, mdh, digest_len);
 
        if (ret == FALSE)
                g_message ("unsupported or invalid mac: %s", g_quark_to_string (oid_scheme));
 
+       egg_bytes_unref (data);
        return ret;
 }
index feb1a25..b11d1dd 100644 (file)
@@ -26,6 +26,8 @@
 
 #include <gcrypt.h>
 
+#include <egg/egg-bytes.h>
+
 gboolean                 egg_symkey_generate_simple             (int cipher_algo,
                                                                  int hash_algo,
                                                                  const gchar *password,
@@ -77,15 +79,13 @@ gboolean                 egg_symkey_generate_pbkdf2             (int cipher_algo
 gboolean                 egg_symkey_read_cipher                 (GQuark oid_scheme,
                                                                  const gchar *password,
                                                                  gsize n_password,
-                                                                 const guchar *data,
-                                                                 gsize n_data,
+                                                                 EggBytes *data,
                                                                  gcry_cipher_hd_t *cih);
 
 gboolean                 egg_symkey_read_mac                    (GQuark oid_scheme,
                                                                  const gchar *password,
                                                                  gsize n_password,
-                                                                 const guchar *data,
-                                                                 gsize n_data,
+                                                                 EggBytes *data,
                                                                  gcry_md_hd_t *mdh,
                                                                  gsize *digest_len);
 
index 9403ebb..2ab9f52 100644 (file)
@@ -60,6 +60,7 @@ const gchar ENUM_THREE[] =           "\x0A\x01\x03";
 static void
 test_boolean (void)
 {
+       EggBytes *bytes;
        GNode *asn;
        gboolean value;
 
@@ -71,20 +72,24 @@ test_boolean (void)
                g_assert_not_reached ();
 
        /* Decode a false */
-       if (!egg_asn1x_decode (asn, BFALSE, XL (BFALSE)))
+       bytes = egg_bytes_new_static (BFALSE, XL (BFALSE));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
        value = TRUE;
        if (!egg_asn1x_get_boolean (asn, &value))
                g_assert_not_reached ();
        g_assert (value == FALSE);
+       egg_bytes_unref (bytes);
 
        /* Decode a true */
-       if (!egg_asn1x_decode (asn, BTRUE, XL (BTRUE)))
+       bytes = egg_bytes_new_static (BTRUE, XL (BTRUE));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
        value = FALSE;
        if (!egg_asn1x_get_boolean (asn, &value))
                g_assert_not_reached ();
        g_assert (value == TRUE);
+       egg_bytes_unref (bytes);
 
        egg_asn1x_clear (asn);
 
@@ -99,8 +104,7 @@ static void
 test_null (void)
 {
        GNode *asn;
-       gpointer data;
-       gsize n_data;
+       EggBytes *data;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestNull");
        g_assert (asn);
@@ -108,14 +112,14 @@ test_null (void)
        if (!egg_asn1x_set_null (asn))
                g_assert_not_reached ();
 
-       data = egg_asn1x_encode (asn, g_realloc, &n_data);
-       egg_assert_cmpmem (NULL_TEST, XL (NULL_TEST), ==, data, n_data);
+       data = egg_asn1x_encode (asn, g_realloc);
+       egg_assert_cmpmem (NULL_TEST, XL (NULL_TEST), ==, egg_bytes_get_data (data), egg_bytes_get_size (data));
 
-       if (!egg_asn1x_decode (asn, data, n_data))
+       if (!egg_asn1x_decode (asn, data))
                g_assert_not_reached ();
 
        egg_asn1x_destroy (asn);
-       g_free (data);
+       egg_bytes_unref (data);
 }
 
 static void
@@ -123,6 +127,7 @@ test_integer (void)
 {
        GNode *asn;
        gulong value;
+       EggBytes *bytes;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
        g_assert (asn);
@@ -132,11 +137,13 @@ test_integer (void)
                g_assert_not_reached ();
 
        /* Should suceed now */
-       if (!egg_asn1x_decode (asn, I33, XL (I33)))
+       bytes = egg_bytes_new_static (I33, XL (I33));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
        if (!egg_asn1x_get_integer_as_ulong (asn, &value))
                g_assert_not_reached ();
        g_assert (value == 42);
+       egg_bytes_unref (bytes);
 
        egg_asn1x_clear (asn);
 
@@ -152,50 +159,53 @@ test_unsigned (void)
 {
        GNode *asn;
        gulong value;
-       guchar *check;
-       gsize n_check;
+       EggBytes *check;
        guchar val;
-       gconstpointer usg;
-       gsize n_usg;
+       EggBytes *bytes;
+       EggBytes *usg;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
        g_assert (asn);
 
        /* Check with ulong */
-       if (!egg_asn1x_decode (asn, I253, XL (I253)))
+       bytes = egg_bytes_new_static (I253, XL (I253));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
        if (!egg_asn1x_get_integer_as_ulong (asn, &value))
                g_assert_not_reached ();
        g_assert (value == 253);
+       egg_bytes_unref (bytes);
 
        egg_asn1x_clear (asn);
 
        if (!egg_asn1x_set_integer_as_ulong (asn, 253))
                g_assert_not_reached ();
 
-       check = egg_asn1x_encode (asn, NULL, &n_check);
-       egg_assert_cmpmem (check, n_check, ==, I253, XL (I253));
+       check = egg_asn1x_encode (asn, NULL);
+       egg_assert_cmpmem (I253, XL (I253), ==, egg_bytes_get_data (check), egg_bytes_get_size (check));
+       egg_bytes_unref (check);
 
        /* Now check with usg */
-       if (!egg_asn1x_decode (asn, I253, XL (I253)))
+       bytes = egg_bytes_new_static (I253, XL (I253));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
-       g_free (check);
+       egg_bytes_unref (bytes);
 
        val = 0xFD; /* == 253 */
-       usg = egg_asn1x_get_integer_as_usg (asn, &n_usg);
-       egg_assert_cmpmem (&val, 1, ==, usg, n_usg);
+       usg = egg_asn1x_get_integer_as_usg (asn);
+       egg_assert_cmpmem (&val, 1, ==, egg_bytes_get_data (usg), egg_bytes_get_size (usg));
+       egg_bytes_unref (usg);
 
        egg_asn1x_clear (asn);
 
-       if (!egg_asn1x_set_integer_as_usg (asn, &val, 1, NULL))
-               g_assert_not_reached ();
+       egg_asn1x_take_integer_as_usg (asn, egg_bytes_new_static (&val, 1));
 
-       check = egg_asn1x_encode (asn, NULL, &n_check);
-       egg_assert_cmpsize (n_check, ==, XL (I253));
-       egg_assert_cmpmem (check, n_check, ==, I253, XL (I253));
+       check = egg_asn1x_encode (asn, NULL);
+       egg_assert_cmpsize (egg_bytes_get_size (check), ==, XL (I253));
+       egg_assert_cmpmem (I253, XL (I253), ==, egg_bytes_get_data (check), egg_bytes_get_size (check));
+       egg_bytes_unref (check);
 
        egg_asn1x_destroy (asn);
-       g_free (check);
 }
 
 static void
@@ -203,6 +213,7 @@ test_octet_string (void)
 {
        GNode *asn;
        gchar *value;
+       EggBytes *bytes;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestOctetString");
        g_assert (asn);
@@ -212,8 +223,11 @@ test_octet_string (void)
                g_assert_not_reached ();
 
        /* Should work */
-       if (!egg_asn1x_decode (asn, SFARNSWORTH, XL (SFARNSWORTH)))
+       bytes = egg_bytes_new_static (SFARNSWORTH, XL (SFARNSWORTH));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
+
        value = egg_asn1x_get_string_as_utf8 (asn, NULL);
        g_assert_cmpstr (value, ==, "farnsworth");
        g_free (value);
@@ -230,6 +244,7 @@ test_octet_string (void)
 static void
 test_generalized_time (void)
 {
+       EggBytes *bytes;
        GNode *asn;
        glong value;
 
@@ -241,8 +256,10 @@ test_generalized_time (void)
        g_assert (value == -1);
 
        /* Should work */
-       if (!egg_asn1x_decode (asn, TGENERALIZED, XL (TGENERALIZED)))
+       bytes = egg_bytes_new_static (TGENERALIZED, XL (TGENERALIZED));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
        value = egg_asn1x_get_time_as_long (asn);
        g_assert (value == 1185368728);
 
@@ -258,6 +275,7 @@ test_generalized_time (void)
 static void
 test_implicit (void)
 {
+       EggBytes *bytes;
        GNode *asn;
        gchar *value;
 
@@ -265,8 +283,10 @@ test_implicit (void)
        g_assert (asn);
 
        /* Should work */
-       if (!egg_asn1x_decode (asn, SIMPLICIT, XL (SIMPLICIT)))
+       bytes = egg_bytes_new_static (SIMPLICIT, XL (SIMPLICIT));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
        value = egg_asn1x_get_string_as_utf8 (asn, NULL);
        g_assert_cmpstr (value, ==, "implicit");
        g_free (value);
@@ -277,6 +297,7 @@ test_implicit (void)
 static void
 test_explicit (void)
 {
+       EggBytes *bytes;
        GNode *asn;
        gchar *value;
 
@@ -284,8 +305,11 @@ test_explicit (void)
        g_assert (asn);
 
        /* Should work */
-       if (!egg_asn1x_decode (asn, SEXPLICIT, XL (SEXPLICIT)))
+       bytes = egg_bytes_new_static (SEXPLICIT, XL (SEXPLICIT));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
+
        value = egg_asn1x_get_string_as_utf8 (asn, NULL);
        g_assert_cmpstr (value, ==, "explicit");
        g_free (value);
@@ -296,39 +320,47 @@ test_explicit (void)
 static void
 test_bit_string_decode (void)
 {
+       EggBytes *bytes;
        GNode *asn;
-       guchar *bits;
+       EggBytes *bits;
        guint n_bits;
+       const guchar *data;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
        g_assert (asn);
 
        /* Should work */
-       if (!egg_asn1x_decode (asn, BITS_TEST, XL (BITS_TEST)))
+       bytes = egg_bytes_new_static (BITS_TEST, XL (BITS_TEST));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 
-       bits = egg_asn1x_get_bits_as_raw (asn, NULL, &n_bits);
-       g_assert (bits);
+       bits = egg_asn1x_get_bits_as_raw (asn, &n_bits);
+       g_assert (bits != NULL);
        g_assert_cmpuint (n_bits, ==, 18);
-       g_assert_cmpint (bits[0], ==, 0x6e);
-       g_assert_cmpint (bits[1], ==, 0x5d);
-       g_assert_cmpint (bits[2], ==, 0xc0);
+       data = egg_bytes_get_data (bits);
+       g_assert_cmpint (data[0], ==, 0x6e);
+       g_assert_cmpint (data[1], ==, 0x5d);
+       g_assert_cmpint (data[2], ==, 0xc0);
 
-       g_free (bits);
+       egg_bytes_unref (bits);
        egg_asn1x_destroy (asn);
 }
 
 static void
 test_bit_string_decode_bad (void)
 {
+       EggBytes *bytes;
        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)))
+       bytes = egg_bytes_new_static (BITS_BAD, XL (BITS_BAD));
+       if (egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 
        egg_asn1x_destroy (asn);
 }
@@ -336,6 +368,7 @@ test_bit_string_decode_bad (void)
 static void
 test_bit_string_decode_ulong (void)
 {
+       EggBytes *bytes;
        GNode *asn;
        gulong bits;
        guint n_bits;
@@ -344,8 +377,10 @@ test_bit_string_decode_ulong (void)
        g_assert (asn);
 
        /* Should work */
-       if (!egg_asn1x_decode (asn, BITS_TEST, XL (BITS_TEST)))
+       bytes = egg_bytes_new_static (BITS_TEST, XL (BITS_TEST));
+       if (!egg_asn1x_decode (asn, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 
        if (!egg_asn1x_get_bits_as_ulong (asn, &bits, &n_bits))
                g_assert_not_reached ();
@@ -359,46 +394,46 @@ test_bit_string_decode_ulong (void)
 static void
 test_bit_string_encode_decode (void)
 {
+       EggBytes *data;
        GNode *asn;
        guchar bits[] = { 0x5d, 0x6e, 0x83 };
-       guchar *check;
-       guint n_check, n_bits = 17;
-       gpointer data;
-       gsize n_data;
+       EggBytes *check;
+       const guchar *ch;
+       guint n_bits = 17;
+       guint n_check;
 
        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 ();
+       egg_asn1x_set_bits_as_raw (asn, egg_bytes_new (bits, 3), n_bits);
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
+       data = egg_asn1x_encode (asn, NULL);
        g_assert (data);
 
-       if (!egg_asn1x_decode (asn, data, n_data))
+       if (!egg_asn1x_decode (asn, 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);
+       egg_bytes_unref (data);
 
-       g_free (check);
+       check = egg_asn1x_get_bits_as_raw (asn, &n_check);
+       g_assert (check != NULL);
+       g_assert_cmpuint (n_check, ==, 17);
+       ch = egg_bytes_get_data (check);
+       g_assert_cmpint (ch[0], ==, 0x5d);
+       g_assert_cmpint (ch[1], ==, 0x6e);
+       g_assert_cmpint (ch[2], ==, 0x80);
 
-       g_free (data);
+       egg_bytes_unref (check);
        egg_asn1x_destroy (asn);
 }
 
 static void
 test_bit_string_encode_decode_ulong (void)
 {
+       EggBytes *data;
        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);
@@ -406,51 +441,48 @@ test_bit_string_encode_decode_ulong (void)
        if (!egg_asn1x_set_bits_as_ulong (asn, bits, n_bits))
                g_assert_not_reached ();
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
+       data = egg_asn1x_encode (asn, NULL);
        g_assert (data);
 
-       if (!egg_asn1x_decode (asn, data, n_data))
+       if (!egg_asn1x_decode (asn, data))
                g_assert_not_reached ();
 
+       egg_bytes_unref (data);
+
        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);
 }
 
 static void
 test_bit_string_encode_decode_zero (void)
 {
+       EggBytes *data;
        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 ();
+       egg_asn1x_set_bits_as_raw (asn, egg_bytes_new_static ("", 0), 0);
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
+       data = egg_asn1x_encode (asn, NULL);
        g_assert (data);
 
-       egg_assert_cmpsize (n_data, ==, XL (BITS_ZERO));
-       g_assert (memcmp (data, BITS_ZERO, n_data) == 0);
+       egg_assert_cmpmem (egg_bytes_get_data (data), egg_bytes_get_size (data), ==, BITS_ZERO, XL (BITS_ZERO));
 
-       g_free (data);
+       egg_bytes_unref (data);
        egg_asn1x_destroy (asn);
 }
 
 static void
 test_have (void)
 {
+       EggBytes *data;
        GNode *asn;
-       guchar *data;
-       gsize n_data;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestBoolean");
        g_assert (asn);
@@ -462,12 +494,12 @@ test_have (void)
 
        g_assert (!egg_asn1x_have (asn));
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
+       data = egg_asn1x_encode (asn, NULL);
        g_assert (data);
 
        g_assert (egg_asn1x_have (asn));
 
-       g_free (data);
+       egg_bytes_unref (data);
        egg_asn1x_destroy (asn);
 }
 
@@ -483,10 +515,10 @@ test_is_freed (gpointer unused)
 static void
 test_any_set_raw (void)
 {
+       EggBytes *bytes;
        GNode *asn, *node;
-       guchar *data;
-       const guchar *check;
-       gsize n_data, n_check;
+       EggBytes *data;
+       EggBytes *check;
 
        /* ENCODED SEQUENCE ANY with OCTET STRING */
        const gchar SEQ_ENCODING[] =  "\x30\x0C\x04\x0A""farnsworth";
@@ -498,22 +530,24 @@ test_any_set_raw (void)
        node = egg_asn1x_node (asn, "contents", NULL);
        g_assert (node);
 
-       if (!egg_asn1x_set_raw_element (node, (guchar*)SFARNSWORTH, XL (SFARNSWORTH), test_is_freed))
+       bytes = egg_bytes_new_with_free_func (SFARNSWORTH, XL (SFARNSWORTH),
+                                             test_is_freed, NULL);
+       if (!egg_asn1x_set_raw_element (node, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       g_assert (data);
+       data = egg_asn1x_encode (asn, NULL);
+       g_assert (data != NULL);
 
-       egg_assert_cmpsize (n_data, ==, XL (SEQ_ENCODING));
-       g_assert (memcmp (data, SEQ_ENCODING, n_data) == 0);
+       egg_assert_equal_bytes (data, SEQ_ENCODING, XL (SEQ_ENCODING));
 
-       check = egg_asn1x_get_raw_element (node, &n_check);
+       check = egg_asn1x_get_raw_element (node);
        g_assert (check);
 
-       egg_assert_cmpsize (n_check, ==, XL (SFARNSWORTH));
-       g_assert (memcmp (check, SFARNSWORTH, n_check) == 0);
+       egg_assert_equal_bytes (check, SFARNSWORTH, XL (SFARNSWORTH));
 
-       g_free (data);
+       egg_bytes_unref (data);
+       egg_bytes_unref (check);
        egg_asn1x_destroy (asn);
        g_assert (is_freed);
 }
@@ -521,10 +555,10 @@ test_any_set_raw (void)
 static void
 test_any_set_raw_explicit (void)
 {
+       EggBytes *bytes;
        GNode *asn, *node;
-       guchar *data;
-       const guchar *check;
-       gsize n_data, n_check;
+       EggBytes *data;
+       EggBytes *check;
 
        /* ENCODED SEQUENCE [89] ANY with OCTET STRING */
        const gchar SEQ_ENCODING[] =  "\x30\x0F\xBF\x59\x0C\x04\x0A""farnsworth";
@@ -536,22 +570,23 @@ test_any_set_raw_explicit (void)
        node = egg_asn1x_node (asn, "contents", NULL);
        g_assert (node);
 
-       if (!egg_asn1x_set_raw_element (node, (guchar*)SFARNSWORTH, XL (SFARNSWORTH), test_is_freed))
+       bytes = egg_bytes_new_with_free_func (SFARNSWORTH, XL (SFARNSWORTH), test_is_freed, NULL);
+       if (!egg_asn1x_set_raw_element (node, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       g_assert (data);
+       data = egg_asn1x_encode (asn, NULL);
+       g_assert (data != NULL);
 
-       egg_assert_cmpsize (n_data, ==, XL (SEQ_ENCODING));
-       g_assert (memcmp (data, SEQ_ENCODING, n_data) == 0);
+       egg_assert_equal_bytes (data, SEQ_ENCODING, XL (SEQ_ENCODING));
 
-       check = egg_asn1x_get_raw_element (node, &n_check);
+       check = egg_asn1x_get_raw_element (node);
        g_assert (check);
 
-       g_assert (n_check == XL (SFARNSWORTH));
-       g_assert (memcmp (check, SFARNSWORTH, n_check) == 0);
+       egg_assert_equal_bytes (check, SFARNSWORTH, XL (SFARNSWORTH));
 
-       g_free (data);
+       egg_bytes_unref (data);
+       egg_bytes_unref (check);
        egg_asn1x_destroy (asn);
        g_assert (is_freed);
 }
@@ -559,9 +594,9 @@ test_any_set_raw_explicit (void)
 static void
 test_choice_not_chosen (void)
 {
+       EggBytes *bytes;
        GNode *asn, *node;
-       guchar *data;
-       gsize n_data;
+       EggBytes *data;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestAnyChoice");
        g_assert (asn);
@@ -569,12 +604,14 @@ test_choice_not_chosen (void)
        node = egg_asn1x_node (asn, "choiceShortTag", NULL);
        g_assert (node);
 
-       if (!egg_asn1x_set_raw_element (node, (guchar*)SFARNSWORTH, XL (SFARNSWORTH), NULL))
+       bytes = egg_bytes_new_static (SFARNSWORTH, XL (SFARNSWORTH));
+       if (!egg_asn1x_set_raw_element (node, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 
        /* egg_asn1x_set_choice() was not called */
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       g_assert (!data);
+       data = egg_asn1x_encode (asn, NULL);
+       g_assert (data == NULL);
        g_assert (egg_asn1x_message (asn));
        g_assert (strstr (egg_asn1x_message (asn), "TestAnyChoice") != NULL);
 
@@ -584,10 +621,10 @@ test_choice_not_chosen (void)
 static void
 perform_asn1_any_choice_set_raw (const gchar *choice, const gchar *encoding, gsize n_encoding)
 {
+       EggBytes *bytes;
        GNode *asn, *node;
-       guchar *data;
-       const guchar *check;
-       gsize n_data, n_check;
+       EggBytes *data;
+       EggBytes *check;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestAnyChoice");
        g_assert (asn);
@@ -599,26 +636,27 @@ perform_asn1_any_choice_set_raw (const gchar *choice, const gchar *encoding, gsi
        if (!egg_asn1x_set_choice (asn, node))
                g_assert_not_reached ();
 
-       if (!egg_asn1x_set_raw_element (node, (guchar*)SFARNSWORTH, XL (SFARNSWORTH), test_is_freed))
+       bytes = egg_bytes_new_with_free_func (SFARNSWORTH, XL (SFARNSWORTH), test_is_freed, NULL);
+       if (!egg_asn1x_set_raw_element (node, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       if (!data) {
+       data = egg_asn1x_encode (asn, NULL);
+       if (data == NULL) {
                g_printerr ("%s\n", egg_asn1x_message (asn));
                g_assert_not_reached ();
        }
-       g_assert (data);
+       g_assert (data != NULL);
 
-       egg_assert_cmpsize (n_data, ==, n_encoding);
-       g_assert (memcmp (data, encoding, n_data) == 0);
+       egg_assert_equal_bytes (data, encoding, n_encoding);
 
-       check = egg_asn1x_get_raw_element (node, &n_check);
-       g_assert (check);
+       check = egg_asn1x_get_raw_element (node);
+       g_assert (check != NULL);
 
-       g_assert (n_check == XL (SFARNSWORTH));
-       g_assert (memcmp (check, SFARNSWORTH, n_check) == 0);
+       egg_assert_equal_bytes (check, SFARNSWORTH, XL (SFARNSWORTH));
 
-       g_free (data);
+       egg_bytes_unref (data);
+       egg_bytes_unref (check);
        egg_asn1x_destroy (asn);
        g_assert (is_freed);
 }
@@ -640,10 +678,10 @@ test_any_choice_set_raw_long_tag (void)
 static void
 test_append (void)
 {
+       EggBytes *bytes;
        GNode *asn;
        GNode *child;
-       gpointer data;
-       gsize n_data;
+       EggBytes *data;
 
        /* SEQUENCE OF with one INTEGER = 1 */
        const gchar SEQOF_ONE[] =  "\x30\x03\x02\x01\x01";
@@ -651,8 +689,10 @@ test_append (void)
        /* SEQUENCE OF with two INTEGER = 1, 2 */
        const gchar SEQOF_TWO[] =  "\x30\x06\x02\x01\x01\x02\x01\x02";
 
-       asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestSeqOf", SEQOF_ONE, XL (SEQOF_ONE));
+       bytes = egg_bytes_new_static (SEQOF_ONE, XL (SEQOF_ONE));
+       asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestSeqOf", bytes);
        g_assert (asn);
+       egg_bytes_unref (bytes);
 
        child = egg_asn1x_append (asn);
        g_assert (child);
@@ -661,22 +701,20 @@ test_append (void)
        if (!egg_asn1x_set_integer_as_ulong (child, 2))
                g_assert_not_reached ();
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       g_assert (data);
+       data = egg_asn1x_encode (asn, NULL);
+       g_assert (data != NULL);
 
-       g_assert (n_data == XL (SEQOF_TWO));
-       g_assert (memcmp (data, SEQOF_TWO, n_data) == 0);
+       egg_assert_equal_bytes (data, SEQOF_TWO, XL (SEQOF_TWO));
 
-       g_free (data);
+       egg_bytes_unref (data);
        egg_asn1x_destroy (asn);
 }
 
 static void
 test_append_and_clear (void)
 {
+       EggBytes *data;
        GNode *asn;
-       gpointer data;
-       gsize n_data;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestSeqOf");
        g_assert (asn);
@@ -690,8 +728,8 @@ test_append_and_clear (void)
 
        g_assert_cmpuint (egg_asn1x_count (asn), ==, 0);
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       g_assert (data);
+       data = egg_asn1x_encode (asn, NULL);
+       g_assert (data != NULL);
 
        g_assert_cmpuint (egg_asn1x_count (asn), ==, 2);
 
@@ -699,15 +737,15 @@ test_append_and_clear (void)
        g_assert_cmpuint (egg_asn1x_count (asn), ==, 0);
 
        egg_asn1x_destroy (asn);
-       g_free (data);
+       egg_bytes_unref (data);
 }
 
 static void
 test_setof (void)
 {
+       EggBytes *bytes;
        GNode *asn;
-       gpointer data;
-       gsize n_data;
+       EggBytes *data;
 
        /* SEQUENCE OF with one INTEGER = 3 */
        const gchar SETOF_ONE[] =  "\x31\x03\x02\x01\x03";
@@ -715,8 +753,10 @@ test_setof (void)
        /* SET OF with two INTEGER = 1, 3, 8 */
        const gchar SETOF_THREE[] =  "\x31\x09\x02\x01\x01\x02\x01\x03\x02\x01\x08";
 
-       asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestSetOf", SETOF_ONE, XL (SETOF_ONE));
-       g_assert (asn);
+       bytes = egg_bytes_new_static (SETOF_ONE, XL (SETOF_ONE));
+       asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestSetOf", bytes);
+       g_assert (asn != NULL);
+       egg_bytes_unref (bytes);
 
        /* Add integer 1, in SET OF DER should sort to front */
        if (!egg_asn1x_set_integer_as_ulong (egg_asn1x_append (asn), 1))
@@ -726,25 +766,23 @@ test_setof (void)
        if (!egg_asn1x_set_integer_as_ulong (egg_asn1x_append (asn), 8))
                g_assert_not_reached ();
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       if (!data) {
+       data = egg_asn1x_encode (asn, NULL);
+       if (data == NULL) {
                g_printerr ("%s\n", egg_asn1x_message (asn));
                g_assert_not_reached ();
        }
 
-       g_assert (n_data == XL (SETOF_THREE));
-       g_assert (memcmp (data, SETOF_THREE, n_data) == 0);
+       egg_assert_equal_bytes (data, SETOF_THREE, XL (SETOF_THREE));
 
-       g_free (data);
+       egg_bytes_unref (data);
        egg_asn1x_destroy (asn);
 }
 
 static void
 test_setof_empty (void)
 {
+       EggBytes *data;
        GNode *asn;
-       gpointer data;
-       gsize n_data;
 
        /* SEQUENCE OF with nothing */
        const gchar SETOF_NONE[] =  "\x31\x00";
@@ -752,29 +790,30 @@ test_setof_empty (void)
        asn = egg_asn1x_create (test_asn1_tab, "TestSetOf");
        g_assert (asn);
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       if (!data) {
+       data = egg_asn1x_encode (asn, NULL);
+       if (data == NULL) {
                g_printerr ("%s\n", egg_asn1x_message (asn));
                g_assert_not_reached ();
        }
 
-       g_assert (n_data == XL (SETOF_NONE));
-       g_assert (memcmp (data, SETOF_NONE, n_data) == 0);
+       egg_assert_equal_bytes (data, SETOF_NONE, XL (SETOF_NONE));
 
-       g_free (data);
+       egg_bytes_unref (data);
        egg_asn1x_destroy (asn);
 }
 
 static void
 test_enumerated (void)
 {
+       EggBytes *bytes;
        GNode *asn;
-       gpointer data;
-       gsize n_data;
+       EggBytes *data;
        GQuark value;
 
-       asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestEnumerated", ENUM_TWO, XL (ENUM_TWO));
-       g_assert (asn);
+       bytes = egg_bytes_new_static (ENUM_TWO, XL (ENUM_TWO));
+       asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestEnumerated", bytes);
+       g_assert (asn != NULL);
+       egg_bytes_unref (bytes);
 
        value = egg_asn1x_get_enumerated (asn);
        g_assert (value);
@@ -783,13 +822,12 @@ test_enumerated (void)
        if (!egg_asn1x_set_enumerated (asn, g_quark_from_static_string ("valueThree")))
                g_assert_not_reached ();
 
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       g_assert (data);
+       data = egg_asn1x_encode (asn, NULL);
+       g_assert (data != NULL);
 
-       g_assert (n_data == XL (ENUM_THREE));
-       g_assert (memcmp (data, ENUM_THREE, n_data) == 0);
+       egg_assert_equal_bytes (data, ENUM_THREE, XL (ENUM_THREE));
 
-       g_free (data);
+       egg_bytes_unref (data);
        egg_asn1x_destroy (asn);
 }
 
@@ -802,6 +840,8 @@ typedef struct {
 static void
 setup (Test *test, gconstpointer unused)
 {
+       EggBytes *bytes;
+
        if (!g_file_get_contents (SRCDIR "/files/test-certificate-1.der",
                                  (gchar**)&test->data, &test->n_data, NULL))
                g_assert_not_reached ();
@@ -809,8 +849,10 @@ setup (Test *test, gconstpointer unused)
        test->asn1 = egg_asn1x_create (pkix_asn1_tab, "Certificate");
        g_assert (test->asn1 != NULL);
 
-       if (!egg_asn1x_decode (test->asn1, test->data, test->n_data))
+       bytes = egg_bytes_new_static (test->data, test->n_data);
+       if (!egg_asn1x_decode (test->asn1, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 }
 
 static void
@@ -829,9 +871,8 @@ test_node_name (Test* test, gconstpointer unused)
 static void
 test_asn1_integers (Test* test, gconstpointer unused)
 {
+       EggBytes *data;
        GNode *asn;
-       guchar *data;
-       gsize n_data;
        gboolean ret;
        gulong val;
 
@@ -848,13 +889,13 @@ test_asn1_integers (Test* test, gconstpointer unused)
        g_assert ("couldn't write integer" && ret);
 
        /* Now encode the whole caboodle */
-       data = egg_asn1x_encode (asn, NULL, &n_data);
+       data = egg_asn1x_encode (asn, NULL);
        g_assert ("encoding asn1 didn't work" && data != NULL);
 
        egg_asn1x_destroy (asn);
 
        /* Now decode it all nicely */
-       asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestIntegers", data, n_data);
+       asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestIntegers", data);
        g_return_if_fail (asn != NULL);
 
        /* And get out the values */
@@ -870,16 +911,15 @@ test_asn1_integers (Test* test, gconstpointer unused)
        g_assert ("couldn't read integer from asn1" && ret);
        g_assert_cmpuint (val, ==, 209384022);
 
-       g_free (data);
+       egg_bytes_unref (data);
 }
 
 static void
 test_boolean_seq (Test* test, gconstpointer unused)
 {
+       EggBytes *data;
        GNode *asn = NULL;
        gboolean value, ret;
-       gpointer data;
-       gsize n_data;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestBooleanSeq");
        g_assert ("asn test structure is null" && asn != NULL);
@@ -893,8 +933,8 @@ test_boolean_seq (Test* test, gconstpointer unused)
        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);
+       data = egg_asn1x_encode (asn, NULL);
+       g_assert (data != NULL);
 
        ret = egg_asn1x_get_boolean (egg_asn1x_node (asn, "boolean", NULL), &value);
        g_assert (ret);
@@ -903,26 +943,25 @@ test_boolean_seq (Test* test, gconstpointer unused)
        ret = egg_asn1x_set_boolean (egg_asn1x_node (asn, "boolean", NULL), FALSE);
        g_assert (ret == TRUE);
 
-       g_free (data);
-       data = egg_asn1x_encode (asn, NULL, &n_data);
-       g_assert (data);
+       egg_bytes_unref (data);
+       data = egg_asn1x_encode (asn, NULL);
+       g_assert (data != NULL);
 
        ret = egg_asn1x_get_boolean (egg_asn1x_node (asn, "boolean", NULL), &value);
        g_assert (ret);
        g_assert (value == FALSE);
 
-       g_free (data);
+       egg_bytes_unref (data);
        egg_asn1x_destroy (asn);
 }
 
 static void
 test_write_value (Test* test, gconstpointer unused)
 {
+       EggBytes *encoded;
        GNode *asn = NULL;
        guchar *data;
        gsize n_data;
-       guchar *encoded;
-       gsize n_encoded;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestData");
        g_assert ("asn test structure is null" && asn != NULL);
@@ -930,7 +969,7 @@ test_write_value (Test* test, gconstpointer unused)
        if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "data", NULL), (guchar*)"SOME DATA", 9, NULL))
                g_assert_not_reached ();
 
-       encoded = egg_asn1x_encode (asn, NULL, &n_encoded);
+       encoded = egg_asn1x_encode (asn, NULL);
        g_assert (encoded);
 
        data = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "data", NULL), NULL, &n_data);
@@ -939,18 +978,17 @@ test_write_value (Test* test, gconstpointer unused)
        g_assert (memcmp (data, "SOME DATA", 9) == 0);
        g_free (data);
 
-       g_free (encoded);
+       egg_bytes_unref (encoded);
        egg_asn1x_destroy (asn);
 }
 
 static void
 test_element_length_content (Test* test, gconstpointer unused)
 {
+       EggBytes *buffer;
        GNode *asn = NULL;
-       gchar *buffer;
        const guchar *content;
        gsize n_content;
-       gsize n_buffer;
        gssize length;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestData");
@@ -959,15 +997,17 @@ test_element_length_content (Test* test, gconstpointer unused)
        if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "data", NULL), (guchar*)"SOME DATA", 9, NULL))
                g_assert_not_reached ();
 
-       buffer = egg_asn1x_encode (asn, NULL, &n_buffer);
+       buffer = egg_asn1x_encode (asn, NULL);
        g_assert (buffer != NULL);
 
        /* Now the real test */
-       length = egg_asn1x_element_length (buffer, n_buffer + 1024);
+       length = egg_asn1x_element_length (egg_bytes_get_data (buffer),
+                                          egg_bytes_get_size (buffer) + 1024);
        g_assert_cmpint (length, ==, 13);
 
-       content = egg_asn1x_element_content (buffer, length, &n_content);
-       g_assert (content);
+       content = egg_asn1x_element_content (egg_bytes_get_data (buffer),
+                                            length, &n_content);
+       g_assert (content != NULL);
        g_assert_cmpuint (n_content, ==, 11);
 
        content = egg_asn1x_element_content (content, n_content, &n_content);
@@ -975,26 +1015,24 @@ test_element_length_content (Test* test, gconstpointer unused)
        g_assert_cmpuint (n_content, ==, 9);
        g_assert (memcmp (content, "SOME DATA", 9) == 0);
 
-       const char *BAD_ASN_TAG = "\x00";
+       const guchar *BAD_ASN_TAG = (guchar *)"\x00";
        content = egg_asn1x_element_content (BAD_ASN_TAG, 1, &n_content);
        g_assert (content == NULL);
 
-       const char *BAD_ASN_LENGTH = "\x30\x80";
+       const guchar *BAD_ASN_LENGTH = (guchar *)"\x30\x80";
        content = egg_asn1x_element_content (BAD_ASN_LENGTH, 2, &n_content);
        g_assert (content == NULL);
 
        egg_asn1x_destroy (asn);
-       g_free (buffer);
+       egg_bytes_unref (buffer);
 }
 
 static void
 test_read_element (Test* test, gconstpointer unused)
 {
+       EggBytes *buffer;
        GNode *asn = NULL;
-       guchar *buffer;
-       gconstpointer data;
-       gsize n_data;
-       gsize n_buffer;
+       EggBytes *data;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestData");
        g_assert ("asn test structure is null" && asn != NULL);
@@ -1002,30 +1040,29 @@ test_read_element (Test* test, gconstpointer unused)
        if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "data", NULL), (guchar*)"SOME DATA", 9, NULL))
                g_assert_not_reached ();
 
-       buffer = egg_asn1x_encode (asn, NULL, &n_buffer);
+       buffer = egg_asn1x_encode (asn, NULL);
        g_assert (buffer != NULL);
 
        /* Now the real test */
-       data = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "data", NULL), &n_data);
+       data = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "data", NULL));
        g_assert (data != NULL);
-       g_assert_cmpint (n_data, ==, 11);
+       g_assert_cmpint (egg_bytes_get_size (data), ==, 11);
 
-       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);
+       data = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "data", NULL));
+       g_assert (data != NULL);
+
+       egg_assert_equal_bytes (data, "SOME DATA", 9);
 
        egg_asn1x_destroy (asn);
-       g_free (buffer);
+       egg_bytes_unref (buffer);
 }
 
 static void
 test_oid (Test* test, gconstpointer unused)
 {
+       EggBytes *buffer;
        GNode *asn = NULL;
        GQuark oid, check;
-       guchar *buffer;
-       gsize n_buffer;
 
        asn = egg_asn1x_create (test_asn1_tab, "TestOid");
        g_assert ("asn test structure is null" && asn != NULL);
@@ -1033,7 +1070,7 @@ test_oid (Test* test, gconstpointer unused)
        if (!egg_asn1x_set_oid_as_string (egg_asn1x_node (asn, "oid", NULL), "1.2.34567.89"))
                g_assert_not_reached ();
 
-       buffer = egg_asn1x_encode (asn, NULL, &n_buffer);
+       buffer = egg_asn1x_encode (asn, NULL);
        g_assert (buffer != NULL);
 
        /* Now a quark has been defined */
@@ -1047,15 +1084,15 @@ test_oid (Test* test, gconstpointer unused)
        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 ();
 
-       g_free (buffer);
-       buffer = egg_asn1x_encode (asn, NULL, &n_buffer);
+       egg_bytes_unref (buffer);
+       buffer = egg_asn1x_encode (asn, NULL);
        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), ==, "5.4.3.2.1678");
 
-       g_free (buffer);
+       egg_bytes_unref (buffer);
        egg_asn1x_destroy (asn);
 }
 
index baeba55..cc60c7f 100644 (file)
@@ -67,29 +67,32 @@ static void
 test_some_asn1_stuff (const ASN1_ARRAY_TYPE *defs, const gchar *file, const gchar *identifier)
 {
        GNode *asn;
-       gpointer data, encoded;
-       gsize n_data, n_encoded;
+       EggBytes *encoded;
+       gpointer data;
+       gsize n_data;
+       EggBytes *bytes;
 
        if (!g_file_get_contents (file, (gchar**)&data, &n_data, NULL))
                g_assert_not_reached ();
+       bytes = egg_bytes_new_take (data, n_data);
        asn = egg_asn1x_create (defs, identifier);
        egg_asn1x_dump (asn);
 
-       if (!egg_asn1x_decode (asn, data, n_data))
+       if (!egg_asn1x_decode (asn, bytes))
                g_warning ("decode of %s failed: %s", identifier, egg_asn1x_message (asn));
 
-       encoded = egg_asn1x_encode (asn, NULL, &n_encoded);
+       encoded = egg_asn1x_encode (asn, NULL);
        if (encoded == NULL)
                g_warning ("encode of %s failed: %s", identifier, egg_asn1x_message (asn));
 
        /* Decode the encoding */
-       if (!egg_asn1x_decode (asn, encoded, n_encoded))
+       if (!egg_asn1x_decode (asn, encoded))
                g_warning ("decode of encoded %s failed: %s", identifier, egg_asn1x_message (asn));
 
        egg_asn1x_clear (asn);
        egg_asn1x_destroy (asn);
-       g_free (encoded);
-       g_free (data);
+       egg_bytes_unref (bytes);
+       egg_bytes_unref (encoded);
 }
 
 int
index 98f5a43..7f95439 100644 (file)
@@ -45,6 +45,8 @@ typedef struct {
 static void
 setup (Test *test, gconstpointer unused)
 {
+       EggBytes *bytes;
+
        if (!g_file_get_contents (SRCDIR "/files/test-certificate-1.der",
                                  (gchar**)&test->data, &test->n_data, NULL))
                g_assert_not_reached ();
@@ -52,8 +54,10 @@ setup (Test *test, gconstpointer unused)
        test->asn1 = egg_asn1x_create (pkix_asn1_tab, "Certificate");
        g_assert (test->asn1 != NULL);
 
-       if (!egg_asn1x_decode (test->asn1, test->data, test->n_data))
+       bytes = egg_bytes_new_static (test->data, test->n_data);
+       if (!egg_asn1x_decode (test->asn1, bytes))
                g_assert_not_reached ();
+       egg_bytes_unref (bytes);
 }
 
 static void
@@ -80,18 +84,23 @@ test_dn_value (Test* test, gconstpointer unused)
 {
        const guchar value[] = { 0x13, 0x1a, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x50, 0x72, 0x65, 0x6d, 0x69, 0x75, 0x6d, 0x20, 0x43, 0x41 };
        gsize n_value = 28;
+       EggBytes *bytes;
        GQuark oid;
        gchar *text;
 
        /* Some printable strings */
        oid = g_quark_from_static_string ("2.5.4.3");
-       text = egg_dn_print_value (oid, value, n_value);
+       bytes = egg_bytes_new_static (value, n_value);
+       text = egg_dn_print_value (oid, bytes);
+       egg_bytes_unref (bytes);
        g_assert_cmpstr (text, ==, "Thawte Personal Premium CA");
        g_free (text);
 
        /* Unknown oid */
        oid = g_quark_from_static_string ("1.1.1.1.1.1");
-       text = egg_dn_print_value (oid, value, n_value);
+       bytes = egg_bytes_new_static (value, n_value);
+       text = egg_dn_print_value (oid, bytes);
+       egg_bytes_unref (bytes);
        g_assert_cmpstr (text, ==, "#131A54686177746520506572736F6E616C205072656D69756D204341");
        g_free (text);
 }
@@ -99,14 +108,17 @@ test_dn_value (Test* test, gconstpointer unused)
 static int last_index = 0;
 
 static void
-concatenate_dn (guint index, GQuark oid, const guchar *value, gsize n_value, gpointer user_data)
+concatenate_dn (guint index,
+                GQuark oid,
+                EggBytes *value,
+                gpointer user_data)
 {
        GString *dn = user_data;
        gchar *text;
 
        g_assert (oid);
-       g_assert (value);
-       g_assert (n_value);
+       g_assert (value != NULL);
+       g_assert (egg_bytes_get_size (value) != 0);
 
        g_assert (index == last_index);
        ++last_index;
@@ -118,7 +130,7 @@ concatenate_dn (guint index, GQuark oid, const guchar *value, gsize n_value, gpo
        g_string_append (dn, egg_oid_get_name (oid));
        g_string_append_c (dn, '=');
 
-       text = egg_dn_print_value (oid, value, n_value);
+       text = egg_dn_print_value (oid, value);
        g_string_append (dn, text);
        g_free (text);
 }
index da5e457..d3d672e 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
+#include <egg/egg-bytes.h>
+
 EGG_SECURE_GLIB_DEFINITIONS ();
 
 typedef struct {
-       guchar *input;
-       gsize n_input;
+       EggBytes *input;
        GQuark reftype;
        guchar *refenc;
        guchar *refdata;
@@ -52,14 +53,19 @@ typedef struct {
 static void
 setup (Test *test, gconstpointer unused)
 {
-       if (!g_file_get_contents (SRCDIR "/files/pem-rsa-enc.key", (gchar**)&test->input, &test->n_input, NULL))
+       gchar *contents;
+       gsize length;
+
+       if (!g_file_get_contents (SRCDIR "/files/pem-rsa-enc.key", &contents, &length, NULL))
                g_assert_not_reached ();
+
+       test->input = egg_bytes_new_take (contents, length);
 }
 
 static void
 teardown (Test *test, gconstpointer unused)
 {
-       g_free (test->input);
+       egg_bytes_unref (test->input);
        g_free (test->refenc);
        egg_secure_free (test->refdata);
        g_hash_table_destroy (test->refheaders);
@@ -73,24 +79,21 @@ copy_each_key_value (gpointer key, gpointer value, gpointer user_data)
 
 static void
 parse_reference (GQuark type,
-                 const guchar *data,
-                 gsize n_data,
-                 const gchar *outer,
-                 gsize n_outer,
+                 EggBytes *data,
+                 EggBytes *outer,
                  GHashTable *headers,
                  gpointer user_data)
 {
        Test *test = user_data;
-       gboolean res;
        const gchar *dekinfo;
 
        g_assert (type);
        test->reftype = type;
 
        g_assert ("no data in PEM callback" && data != NULL);
-       g_assert ("no data in PEM callback" && n_data > 0);
-       test->refenc = g_memdup (data, n_data);
-       test->n_refenc = n_data;
+       g_assert ("no data in PEM callback" && egg_bytes_get_size (data) > 0);
+       test->refenc = g_memdup (egg_bytes_get_data (data), egg_bytes_get_size (data));
+       test->n_refenc = egg_bytes_get_size (data);
 
        g_assert ("no headers present in file" && headers != NULL);
        g_assert (!test->refheaders);
@@ -99,10 +102,9 @@ parse_reference (GQuark type,
        dekinfo = egg_openssl_get_dekinfo (headers);
        g_assert ("no dekinfo in headers" && dekinfo != NULL);
 
-       res = egg_openssl_decrypt_block (dekinfo, "booo", 4, data, n_data, &test->refdata, &test->n_refdata);
-       g_assert ("couldn't openssl decrypt block" && res == TRUE);
+       test->refdata = egg_openssl_decrypt_block (dekinfo, "booo", 4, data, &test->n_refdata);
        g_assert ("no data returned from openssl decrypt" && test->refdata != NULL);
-       g_assert ("invalid amount of data returned from openssl decrypt" && test->n_refdata == n_data);
+       g_assert ("invalid amount of data returned from openssl decrypt" && test->n_refdata == egg_bytes_get_size (data));
 }
 
 static void
@@ -110,7 +112,7 @@ test_parse_reference (Test *test, gconstpointer unused)
 {
        guint num;
 
-       num = egg_armor_parse (test->input, test->n_input, parse_reference, test);
+       num = egg_armor_parse (test->input, parse_reference, test);
        g_assert ("couldn't PEM block in reference data" && num == 1);
 
        g_assert ("parse_reference() wasn't called" && test->refdata != NULL);
@@ -122,17 +124,19 @@ test_write_reference (Test *test, gconstpointer unused)
        const gchar *dekinfo;
        guchar *encrypted;
        gsize n_encrypted;
-       gboolean ret;
+       EggBytes *data;
        guint num;
 
-       num = egg_armor_parse (test->input, test->n_input, parse_reference, test);
+       num = egg_armor_parse (test->input, parse_reference, test);
        g_assert ("couldn't PEM block in reference data" && num == 1);
 
        dekinfo = egg_openssl_get_dekinfo (test->refheaders);
        g_assert ("no dekinfo in headers" && dekinfo != NULL);
 
-       ret = egg_openssl_encrypt_block (dekinfo, "booo", 4, test->refdata, test->n_refdata, &encrypted, &n_encrypted);
-       g_assert ("couldn't openssl encrypt block" && ret == TRUE);
+       data = egg_bytes_new_static (test->refdata, test->n_refdata);
+       encrypted = egg_openssl_encrypt_block (dekinfo, "booo", 4, data, &n_encrypted);
+       egg_bytes_unref (data);
+
        g_assert ("no data returned from openssl encrypt" && encrypted != NULL);
        g_assert ("invalid amount of data returned from openssl encrypt" && test->n_refdata <= n_encrypted);
 
@@ -147,7 +151,7 @@ test_write_exactly_same (Test *test, gconstpointer unused)
        gsize n_result;
        guint num;
 
-       num = egg_armor_parse (test->input, test->n_input, parse_reference, test);
+       num = egg_armor_parse (test->input, parse_reference, test);
        g_assert ("couldn't PEM block in reference data" && num == 1);
 
        result = egg_armor_write (test->refenc, test->n_refenc, test->reftype,
@@ -159,7 +163,7 @@ test_write_exactly_same (Test *test, gconstpointer unused)
         * and line endings.
         */
 
-       egg_assert_cmpmem (test->input, test->n_input, ==, result, n_result);
+       egg_assert_equal_bytes (test->input, result, n_result);
        g_free (result);
 }
 
@@ -171,25 +175,28 @@ static void
 test_openssl_roundtrip (Test *test, gconstpointer unused)
 {
        const gchar *dekinfo;
-       gboolean res;
-       gboolean ret;
        guchar *encrypted, *decrypted;
        gsize n_encrypted, n_decrypted;
+       EggBytes *data;
        int i;
        guint num;
 
-       num = egg_armor_parse (test->input, test->n_input, parse_reference, test);
+       num = egg_armor_parse (test->input, parse_reference, test);
        g_assert ("couldn't PEM block in reference data" && num == 1);
 
        dekinfo = egg_openssl_prep_dekinfo (test->refheaders);
 
-       ret = egg_openssl_encrypt_block (dekinfo, "password", -1, TEST_DATA, TEST_DATA_L, &encrypted, &n_encrypted);
-       g_assert ("couldn't openssl encrypt block" && ret == TRUE);
+       data = egg_bytes_new_static (TEST_DATA, TEST_DATA_L);
+       encrypted = egg_openssl_encrypt_block (dekinfo, "password", -1, data, &n_encrypted);
+       egg_bytes_unref (data);
+
        g_assert ("no data returned from openssl encrypt" && encrypted != NULL);
        g_assert ("invalid amount of data returned from openssl encrypt" && TEST_DATA_L <= n_encrypted);
 
-       res = egg_openssl_decrypt_block (dekinfo, "password", 8, encrypted, n_encrypted, &decrypted, &n_decrypted);
-       g_assert ("couldn't openssl decrypt block" && res == TRUE);
+       data = egg_bytes_new_with_free_func (encrypted, n_encrypted, egg_secure_free, encrypted);
+       decrypted = egg_openssl_decrypt_block (dekinfo, "password", 8, data, &n_decrypted);
+       egg_bytes_unref (data);
+
        g_assert ("no data returned from openssl decrypt" && decrypted != NULL);
 
        /* Check that the data was decrypted properly */
index 8256da2..f130225 100644 (file)
 #include <glib/gi18n-lib.h>
 
 gboolean
-_gcr_certificate_extension_basic_constraints (gconstpointer data, gsize n_data,
-                                              gboolean *is_ca, gint *path_len)
+_gcr_certificate_extension_basic_constraints (EggBytes *data,
+                                              gboolean *is_ca,
+                                              gint *path_len)
 {
        gboolean ret = TRUE;
        GNode *asn = NULL;
        GNode *node;
        gulong value;
 
-       g_return_val_if_fail (data, FALSE);
-       g_return_val_if_fail (n_data, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "BasicConstraints", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "BasicConstraints", data);
        if (asn == NULL)
                return FALSE;
 
@@ -69,8 +69,8 @@ _gcr_certificate_extension_basic_constraints (gconstpointer data, gsize n_data,
        return ret;
 }
 
-GQuark*
-_gcr_certificate_extension_extended_key_usage (gconstpointer data, gsize n_data)
+GQuark *
+_gcr_certificate_extension_extended_key_usage (EggBytes *data)
 {
        GNode *asn = NULL;
        GNode *node;
@@ -78,7 +78,9 @@ _gcr_certificate_extension_extended_key_usage (gconstpointer data, gsize n_data)
        GQuark oid;
        int i;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "ExtKeyUsageSyntax", data, n_data);
+       g_return_val_if_fail (data != NULL, NULL);
+
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "ExtKeyUsageSyntax", data);
        if (asn == NULL)
                return NULL;
 
@@ -96,13 +98,15 @@ _gcr_certificate_extension_extended_key_usage (gconstpointer data, gsize n_data)
 }
 
 gpointer
-_gcr_certificate_extension_subject_key_identifier (gconstpointer data, gsize n_data,
+_gcr_certificate_extension_subject_key_identifier (EggBytes *data,
                                                    gsize *n_keyid)
 {
        GNode *asn = NULL;
        gpointer result;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectKeyIdentifier", data, n_data);
+       g_return_val_if_fail (data != NULL, NULL);
+
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectKeyIdentifier", data);
        if (asn == NULL)
                return NULL;
 
@@ -113,14 +117,16 @@ _gcr_certificate_extension_subject_key_identifier (gconstpointer data, gsize n_d
 }
 
 gboolean
-_gcr_certificate_extension_key_usage (gconstpointer data, gsize n_data,
+_gcr_certificate_extension_key_usage (EggBytes *data,
                                       gulong *key_usage)
 {
        GNode *asn = NULL;
        gboolean ret = TRUE;
        guint n_bits;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "KeyUsage", data, n_data);
+       g_return_val_if_fail (data != NULL, FALSE);
+
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "KeyUsage", data);
        if (asn == NULL)
                return FALSE;
 
@@ -134,28 +140,28 @@ general_name_parse_other (GNode *node, GcrGeneralName *general)
 {
        GNode *decode = NULL;
        GQuark oid;
-       gconstpointer value;
-       gsize n_value;
+       EggBytes *value;
 
        general->type = GCR_GENERAL_NAME_OTHER;
        general->description = _("Other Name");
 
        oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (node, "type-id", NULL));
-       value = egg_asn1x_get_raw_element (egg_asn1x_node (node, "value", NULL), &n_value);
+       value = egg_asn1x_get_raw_element (egg_asn1x_node (node, "value", NULL));
 
        if (value == NULL)
                return;
 
        if (oid == GCR_OID_ALT_NAME_XMPP_ADDR) {
                general->description = _("XMPP Addr");
-               decode = egg_asn1x_create_and_decode (pkix_asn1_tab, "UTF8String", value, n_value);
+               decode = egg_asn1x_create_and_decode (pkix_asn1_tab, "UTF8String", value);
                general->display = egg_asn1x_get_string_as_utf8 (decode, g_realloc);
        } else if (oid == GCR_OID_ALT_NAME_DNS_SRV) {
                general->description = _("DNS SRV");
-               decode = egg_asn1x_create_and_decode (pkix_asn1_tab, "IA5String", value, n_value);
+               decode = egg_asn1x_create_and_decode (pkix_asn1_tab, "IA5String", value);
                general->display = egg_asn1x_get_string_as_utf8 (decode, g_realloc);
        }
 
+       egg_bytes_unref (value);
        egg_asn1x_destroy (decode);
 }
 
@@ -222,7 +228,7 @@ general_name_parse_registered (GNode *node, GcrGeneralName *general)
 }
 
 GArray*
-_gcr_certificate_extension_subject_alt_name (gconstpointer data, gsize n_data)
+_gcr_certificate_extension_subject_alt_name (EggBytes *data)
 {
        GNode *asn = NULL;
        guint count, i;
@@ -233,7 +239,7 @@ _gcr_certificate_extension_subject_alt_name (gconstpointer data, gsize n_data)
 
        _gcr_oids_init ();
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectAltName", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectAltName", data);
        if (asn == NULL)
                return NULL;
 
@@ -276,7 +282,7 @@ _gcr_certificate_extension_subject_alt_name (gconstpointer data, gsize n_data)
                else if (g_str_equal (node_name, "registeredID"))
                        general_name_parse_registered (choice, &general);
 
-               general.raw = egg_asn1x_get_raw_element (choice, &general.n_raw);
+               general.raw = egg_asn1x_get_raw_element (choice);
                g_array_append_val (names, general);
        }
 
@@ -287,9 +293,13 @@ _gcr_certificate_extension_subject_alt_name (gconstpointer data, gsize n_data)
 void
 _gcr_general_names_free (GArray *names)
 {
+       GcrGeneralName *name;
        guint i;
 
-       for (i = 0; names && i < names->len; i++)
-               g_free (g_array_index (names, GcrGeneralName, i).display);
+       for (i = 0; names && i < names->len; i++) {
+               name = &g_array_index (names, GcrGeneralName, i);
+               g_free (name->display);
+               egg_bytes_unref (name->raw);
+       }
        g_array_free (names, TRUE);
 }
index 9101008..ea5792f 100644 (file)
 
 #include <glib.h>
 
+#include <egg/egg-bytes.h>
+
 G_BEGIN_DECLS
 
-gboolean   _gcr_certificate_extension_basic_constraints       (gconstpointer data,
-                                                               gsize n_data,
+gboolean   _gcr_certificate_extension_basic_constraints       (EggBytes *data,
                                                                gboolean *is_ca,
                                                                gint *path_len);
 
-GQuark*    _gcr_certificate_extension_extended_key_usage      (gconstpointer data,
-                                                               gsize n_data);
+GQuark *   _gcr_certificate_extension_extended_key_usage      (EggBytes *data);
 
-gpointer   _gcr_certificate_extension_subject_key_identifier  (gconstpointer data,
-                                                               gsize n_data,
+gpointer   _gcr_certificate_extension_subject_key_identifier  (EggBytes *data,
                                                                gsize *n_keyid);
 
 typedef enum {
@@ -54,8 +53,7 @@ typedef enum {
        GCR_KEY_USAGE_CRL_SIGN = 1 << 6,
 } GcrCertificateExtensionKeyUsage;
 
-gboolean   _gcr_certificate_extension_key_usage               (gconstpointer data,
-                                                               gsize n_data,
+gboolean   _gcr_certificate_extension_key_usage               (EggBytes *data,
                                                                gulong *key_usage);
 
 typedef enum {
@@ -74,12 +72,10 @@ typedef struct {
        GcrGeneralNameType type;
        const gchar *description;
        gchar *display;
-       gconstpointer raw;
-       gsize n_raw;
+       EggBytes *raw;
 } GcrGeneralName;
 
-GArray *   _gcr_certificate_extension_subject_alt_name        (gconstpointer data,
-                                                               gsize n_data);
+GArray *   _gcr_certificate_extension_subject_alt_name        (EggBytes *data);
 
 void       _gcr_general_names_free                            (GArray *names);
 
index 7995917..a350d3e 100644 (file)
@@ -102,15 +102,16 @@ calculate_label (GcrCertificateRenderer *self)
 }
 
 static gboolean
-append_extension_basic_constraints (GcrCertificateRenderer *self, GcrDisplayView *view,
-                                    gconstpointer data, gsize n_data)
+append_extension_basic_constraints (GcrCertificateRenderer *self,
+                                    GcrDisplayView *view,
+                                    EggBytes *data)
 {
        GcrRenderer *renderer = GCR_RENDERER (self);
        gboolean is_ca = FALSE;
        gint path_len = -1;
        gchar *number;
 
-       if (!_gcr_certificate_extension_basic_constraints (data, n_data, &is_ca, &path_len))
+       if (!_gcr_certificate_extension_basic_constraints (data, &is_ca, &path_len))
                return FALSE;
 
        _gcr_display_view_append_heading (view, renderer, _("Basic Constraints"));
@@ -127,15 +128,16 @@ append_extension_basic_constraints (GcrCertificateRenderer *self, GcrDisplayView
 }
 
 static gboolean
-append_extension_extended_key_usage (GcrCertificateRenderer *self, GcrDisplayView *view,
-                                     gconstpointer data, gsize n_data)
+append_extension_extended_key_usage (GcrCertificateRenderer *self,
+                                     GcrDisplayView *view,
+                                     EggBytes *data)
 {
        GcrRenderer *renderer = GCR_RENDERER (self);
        GQuark *oids;
        GString *text;
        guint i;
 
-       oids = _gcr_certificate_extension_extended_key_usage (data, n_data);
+       oids = _gcr_certificate_extension_extended_key_usage (data);
        if (oids == NULL)
                return FALSE;
 
@@ -159,14 +161,15 @@ append_extension_extended_key_usage (GcrCertificateRenderer *self, GcrDisplayVie
 }
 
 static gboolean
-append_extension_subject_key_identifier (GcrCertificateRenderer *self, GcrDisplayView *view,
-                                         gconstpointer data, gsize n_data)
+append_extension_subject_key_identifier (GcrCertificateRenderer *self,
+                                         GcrDisplayView *view,
+                                         EggBytes *data)
 {
        GcrRenderer *renderer = GCR_RENDERER (self);
        gpointer keyid;
        gsize n_keyid;
 
-       keyid = _gcr_certificate_extension_subject_key_identifier (data, n_data, &n_keyid);
+       keyid = _gcr_certificate_extension_subject_key_identifier (data, &n_keyid);
        if (keyid == NULL)
                return FALSE;
 
@@ -191,15 +194,16 @@ static const struct {
 };
 
 static gboolean
-append_extension_key_usage (GcrCertificateRenderer *self, GcrDisplayView *view,
-                            gconstpointer data, gsize n_data)
+append_extension_key_usage (GcrCertificateRenderer *self,
+                            GcrDisplayView *view,
+                            EggBytes *data)
 {
        GcrRenderer *renderer = GCR_RENDERER (self);
        gulong key_usage;
        GString *text;
        guint i;
 
-       if (!_gcr_certificate_extension_key_usage (data, n_data, &key_usage))
+       if (!_gcr_certificate_extension_key_usage (data, &key_usage))
                return FALSE;
 
        text = g_string_new ("");
@@ -221,15 +225,16 @@ append_extension_key_usage (GcrCertificateRenderer *self, GcrDisplayView *view,
 }
 
 static gboolean
-append_extension_subject_alt_name (GcrCertificateRenderer *self, GcrDisplayView *view,
-                                   gconstpointer data, gsize n_data)
+append_extension_subject_alt_name (GcrCertificateRenderer *self,
+                                   GcrDisplayView *view,
+                                   EggBytes *data)
 {
        GcrRenderer *renderer = GCR_RENDERER (self);
        GArray *general_names;
        GcrGeneralName *general;
        guint i;
 
-       general_names = _gcr_certificate_extension_subject_alt_name (data, n_data);
+       general_names = _gcr_certificate_extension_subject_alt_name (data);
        if (general_names == NULL)
                return FALSE;
 
@@ -239,7 +244,8 @@ append_extension_subject_alt_name (GcrCertificateRenderer *self, GcrDisplayView
                general = &g_array_index (general_names, GcrGeneralName, i);
                if (general->display == NULL)
                        _gcr_display_view_append_hex (view, renderer, general->description,
-                                                     general->raw, general->n_raw);
+                                                     egg_bytes_get_data (general->raw),
+                                                     egg_bytes_get_size (general->raw));
                else
                        _gcr_display_view_append_value (view, renderer, general->description,
                                                        general->display, FALSE);
@@ -269,14 +275,15 @@ append_extension_hex (GcrCertificateRenderer *self, GcrDisplayView *view,
 }
 
 static gboolean
-append_extension (GcrCertificateRenderer *self, GcrDisplayView *view,
-                  GNode *asn, const guchar *data, gsize n_data, gint index)
+append_extension (GcrCertificateRenderer *self,
+                  GcrDisplayView *view,
+                  GNode *asn,
+                  gint index)
 {
        GcrRenderer *renderer = GCR_RENDERER (self);
        GNode *node;
        GQuark oid;
-       gsize n_value;
-       const guchar *value;
+       EggBytes *value;
        gboolean critical;
        gboolean ret = FALSE;
 
@@ -290,23 +297,25 @@ append_extension (GcrCertificateRenderer *self, GcrDisplayView *view,
        g_return_val_if_fail (oid, FALSE);
 
        /* Extension value */
-       value = egg_asn1x_get_raw_value (egg_asn1x_node (node, "extnValue", NULL), &n_value);
+       value = egg_asn1x_get_raw_value (egg_asn1x_node (node, "extnValue", NULL));
 
        /* The custom parsers */
        if (oid == GCR_OID_BASIC_CONSTRAINTS)
-               ret = append_extension_basic_constraints (self, view, value, n_value);
+               ret = append_extension_basic_constraints (self, view, value);
        else if (oid == GCR_OID_EXTENDED_KEY_USAGE)
-               ret = append_extension_extended_key_usage (self, view, value, n_value);
+               ret = append_extension_extended_key_usage (self, view, value);
        else if (oid == GCR_OID_SUBJECT_KEY_IDENTIFIER)
-               ret = append_extension_subject_key_identifier (self, view, value, n_value);
+               ret = append_extension_subject_key_identifier (self, view, value);
        else if (oid == GCR_OID_KEY_USAGE)
-               ret = append_extension_key_usage (self, view, value, n_value);
+               ret = append_extension_key_usage (self, view, value);
        else if (oid == GCR_OID_SUBJECT_ALT_NAME)
-               ret = append_extension_subject_alt_name (self, view, value, n_value);
+               ret = append_extension_subject_alt_name (self, view, value);
 
        /* Otherwise the default raw display */
        if (ret == FALSE)
-               ret = append_extension_hex (self, view, oid, value, n_value);
+               ret = append_extension_hex (self, view, oid,
+                                           egg_bytes_get_data (value),
+                                           egg_bytes_get_size (value));
 
        /* Critical */
        if (ret == TRUE && egg_asn1x_get_boolean (egg_asn1x_node (node, "critical", NULL), &critical)) {
@@ -314,6 +323,7 @@ append_extension (GcrCertificateRenderer *self, GcrDisplayView *view,
                                                critical ? _("Yes") : _("No"), FALSE);
        }
 
+       egg_bytes_unref (value);
        return ret;
 }
 
@@ -323,8 +333,10 @@ typedef struct _on_parsed_dn_args {
 } on_parsed_dn_args;
 
 static void
-on_parsed_dn_part (guint index, GQuark oid, const guchar *value,
-                   gsize n_value, gpointer user_data)
+on_parsed_dn_part (guint index,
+                   GQuark oid,
+                   EggBytes *value,
+                   gpointer user_data)
 {
        GcrCertificateRenderer *self = ((on_parsed_dn_args*)user_data)->renderer;
        GcrDisplayView *view = ((on_parsed_dn_args*)user_data)->view;
@@ -354,7 +366,7 @@ on_parsed_dn_part (guint index, GQuark oid, const guchar *value,
                g_assert_not_reached ();
        }
 
-       display = egg_dn_print_value (oid, value, n_value);
+       display = egg_dn_print_value (oid, value);
        if (display == NULL)
                display = g_strdup ("");
 
@@ -562,17 +574,19 @@ static void
 gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
 {
        GcrCertificateRenderer *self;
-       gconstpointer data, value;
-       gsize n_data, n_value, n_raw;
+       gconstpointer data;
+       gsize n_data, n_raw;
        GcrDisplayView *view;
        on_parsed_dn_args args;
        const gchar *text;
        GcrCertificate *cert;
        gpointer raw;
-       gconstpointer number;
+       EggBytes *number;
        gulong version;
        guint bits, index;
        gchar *display;
+       EggBytes *bytes;
+       EggBytes *value;
        GNode *asn;
        GQuark oid;
        GDate date;
@@ -602,8 +616,10 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
        _gcr_display_view_set_icon (view, GCR_RENDERER (self), icon);
        g_object_unref (icon);
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data);
-       g_return_if_fail (asn);
+       bytes = egg_bytes_new_static (data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", bytes);
+       g_return_if_fail (asn != NULL);
+       egg_bytes_unref (bytes);
 
        display = calculate_label (self);
        _gcr_display_view_append_title (view, renderer, display);
@@ -647,9 +663,12 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
        _gcr_display_view_append_value (view, renderer, _("Version"), display, FALSE);
        g_free (display);
 
-       number = egg_asn1x_get_integer_as_raw (egg_asn1x_node (asn, "tbsCertificate", "serialNumber", NULL), &n_raw);
+       number = egg_asn1x_get_integer_as_raw (egg_asn1x_node (asn, "tbsCertificate", "serialNumber", NULL));
        g_return_if_fail (number != NULL);
-       _gcr_display_view_append_hex (view, renderer, _("Serial Number"), number, n_raw);
+       _gcr_display_view_append_hex (view, renderer, _("Serial Number"),
+                                     egg_bytes_get_data (number),
+                                     egg_bytes_get_size (number));
+       egg_bytes_unref (number);
 
        display = g_malloc0 (128);
        if (egg_asn1x_get_time_as_date (egg_asn1x_node (asn, "tbsCertificate", "validity", "notBefore", NULL), &date)) {
@@ -677,14 +696,19 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
        text = egg_oid_get_description (oid);
        _gcr_display_view_append_value (view, renderer, _("Signature Algorithm"), text, FALSE);
 
-       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "signatureAlgorithm", "parameters", NULL), &n_value);
-       if (value && n_value)
-               _gcr_display_view_append_hex (view, renderer, _("Signature Parameters"), value, n_value);
+       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "signatureAlgorithm", "parameters", NULL));
+       if (value) {
+               _gcr_display_view_append_hex (view, renderer, _("Signature Parameters"),
+                                             egg_bytes_get_data (value),
+                                             egg_bytes_get_size (value));
+               egg_bytes_unref (value);
+       }
 
-       raw = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "signature", NULL), NULL, &bits);
-       g_return_if_fail (raw);
-       _gcr_display_view_append_hex (view, renderer, _("Signature"), raw, bits / 8);
-       g_free (raw);
+       value = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "signature", NULL), &bits);
+       g_return_if_fail (value != NULL);
+       _gcr_display_view_append_hex (view, renderer, _("Signature"),
+                                     egg_bytes_get_data (value), bits / 8);
+       egg_bytes_unref (value);
 
        /* Public Key Info */
        _gcr_display_view_append_heading (view, renderer, _("Public Key Info"));
@@ -695,9 +719,13 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
        _gcr_display_view_append_value (view, renderer, _("Key Algorithm"), text, FALSE);
 
        value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo",
-                                                          "algorithm", "parameters", NULL), &n_value);
-       if (value && n_value)
-               _gcr_display_view_append_hex (view, renderer, _("Key Parameters"), value, n_value);
+                                                          "algorithm", "parameters", NULL));
+       if (value) {
+               _gcr_display_view_append_hex (view, renderer, _("Key Parameters"),
+                                             egg_bytes_get_data (value),
+                                             egg_bytes_get_size (value));
+               egg_bytes_unref (value);
+       }
 
        bits = gcr_certificate_get_key_size (cert);
        if (bits > 0) {
@@ -707,20 +735,23 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
        }
 
        value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "tbsCertificate",
-                                                          "subjectPublicKeyInfo", NULL), &n_value);
-       raw = gcr_fingerprint_from_subject_public_key_info (value, n_value, G_CHECKSUM_SHA1, &n_raw);
+                                                          "subjectPublicKeyInfo", NULL));
+       raw = gcr_fingerprint_from_subject_public_key_info (egg_bytes_get_data (bytes),
+                                                           egg_bytes_get_size (bytes),
+                                                           G_CHECKSUM_SHA1, &n_raw);
        _gcr_display_view_append_hex (view, renderer, _("Key SHA1 Fingerprint"), raw, n_raw);
        g_free (raw);
 
-       raw = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo",
-                                                        "subjectPublicKey", NULL), NULL, &bits);
-       g_return_if_fail (raw);
-       _gcr_display_view_append_hex (view, renderer, _("Public Key"), raw, bits / 8);
-       g_free (raw);
+       value = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo",
+                                                          "subjectPublicKey", NULL), &bits);
+       g_return_if_fail (value != NULL);
+       _gcr_display_view_append_hex (view, renderer, _("Public Key"),
+                                     egg_bytes_get_data (value), bits / 8);
+       egg_bytes_unref (value);
 
        /* Extensions */
        for (index = 1; TRUE; ++index) {
-               if (!append_extension (self, view, asn, data, n_data, index))
+               if (!append_extension (self, view, asn, index))
                        break;
        }
 
index 5dd16ab..889c67a 100644 (file)
@@ -104,8 +104,8 @@ typedef struct _GcrCertificateInfo {
 
 /* Forward declarations */
 
-static gconstpointer _gcr_certificate_get_subject_const (GcrCertificate *self, gsize *n_data);
-static gconstpointer _gcr_certificate_get_issuer_const (GcrCertificate *self, gsize *n_data);
+static EggBytes * _gcr_certificate_get_subject_const (GcrCertificate *self);
+static EggBytes * _gcr_certificate_get_issuer_const (GcrCertificate *self);
 
 enum {
        PROP_FIRST = 0x0007000,
@@ -139,6 +139,7 @@ static GcrCertificateInfo*
 certificate_info_load (GcrCertificate *cert)
 {
        GcrCertificateInfo *info;
+       EggBytes *bytes;
        GNode *asn1;
        gconstpointer der;
        gsize n_der;
@@ -154,8 +155,14 @@ certificate_info_load (GcrCertificate *cert)
                        return info;
        }
 
+       /* TODO: Once GBytes is public, add to GcrCertificate interface */
+       bytes = egg_bytes_new_static (der, n_der);
+
        /* Cache is invalid or non existent */
-       asn1 = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", der, n_der);
+       asn1 = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", bytes);
+
+       egg_bytes_unref (bytes);
+
        if (asn1 == NULL) {
                g_warning ("a derived class provided an invalid or unparseable X.509 DER certificate data.");
                return NULL;
@@ -171,56 +178,67 @@ certificate_info_load (GcrCertificate *cert)
 }
 
 static guint
-calculate_rsa_key_size (gconstpointer data, gsize n_data)
+calculate_rsa_key_size (EggBytes *data)
 {
+       EggBytes *content;
+       guint key_size;
        GNode *asn;
-       gsize n_content;
 
-       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data, n_data);
-       g_return_val_if_fail (asn, 0);
+       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data);
+       g_return_val_if_fail (asn != NULL, 0);
 
-       if (!egg_asn1x_get_raw_value (egg_asn1x_node (asn, "modulus", NULL), &n_content))
+       content = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "modulus", NULL));
+       if (!content)
                g_return_val_if_reached (0);
 
        egg_asn1x_destroy (asn);
 
        /* Removes the complement */
-       return (n_content / 2) * 2 * 8;
+       key_size = (egg_bytes_get_size (content) / 2) * 2 * 8;
+
+       egg_bytes_unref (content);
+       return key_size;
 }
 
 static guint
-calculate_dsa_params_size (gconstpointer data, gsize n_data)
+calculate_dsa_params_size (EggBytes *data)
 {
+       EggBytes *content;
+       gsize params_size;
        GNode *asn;
-       gsize n_content;
 
-       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", data, n_data);
-       g_return_val_if_fail (asn, 0);
+       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", data);
+       g_return_val_if_fail (asn != NULL, 0);
 
-       if (!egg_asn1x_get_raw_value (egg_asn1x_node (asn, "p", NULL), &n_content))
+       content = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "p", NULL));
+       if (!content)
                g_return_val_if_reached (0);
 
        egg_asn1x_destroy (asn);
 
        /* Removes the complement */
-       return (n_content / 2) * 2 * 8;
+       params_size = (egg_bytes_get_size (content) / 2) * 2 * 8;
+
+       egg_bytes_unref (content);
+       return params_size;
 }
 
 static guint
 calculate_key_size (GcrCertificateInfo *info)
 {
        GNode *asn;
-       gconstpointer data, params;
-       gsize n_data, n_params;
+       EggBytes *data;
        guint key_size = 0, n_bits;
-       guchar *key = NULL;
+       EggBytes *key;
        GQuark oid;
 
-       data = egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL), &n_data);
+       data = egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL));
        g_return_val_if_fail (data != NULL, 0);
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data, n_data);
-       g_return_val_if_fail (asn, 0);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data);
+       g_return_val_if_fail (asn != NULL, 0);
+
+       egg_bytes_unref (data);
 
        /* Figure out the algorithm */
        oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "algorithm", "algorithm", NULL));
@@ -230,15 +248,16 @@ calculate_key_size (GcrCertificateInfo *info)
        if (oid == GCR_OID_PKIX1_RSA) {
 
                /* A bit string so we cannot process in place */
-               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_bits / 8);
-               g_free (key);
+               key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "subjectPublicKey", NULL), &n_bits);
+               g_return_val_if_fail (key != NULL, 0);
+               key_size = calculate_rsa_key_size (key);
+               egg_bytes_unref (key);
 
        /* The DSA key size is discovered by the prime in params */
        } else if (oid == GCR_OID_PKIX1_DSA) {
-               params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "algorithm", "parameters", NULL), &n_params);
-               key_size = calculate_dsa_params_size (params, n_params);
+               key = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "algorithm", "parameters", NULL));
+               key_size = calculate_dsa_params_size (key);
+               egg_bytes_unref (key);
 
        } else {
                g_message ("unsupported key algorithm in certificate: %s", g_quark_to_string (oid));
@@ -495,18 +514,17 @@ gcr_certificate_get_issuer_part (GcrCertificate *self, const char *part)
        return egg_dn_read_part (egg_asn1x_node (info->asn1, "tbsCertificate", "issuer", "rdnSequence", NULL), part);
 }
 
-static gconstpointer
-_gcr_certificate_get_issuer_const (GcrCertificate *self, gsize *n_data)
+static EggBytes *
+_gcr_certificate_get_issuer_const (GcrCertificate *self)
 {
        GcrCertificateInfo *info;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
-       g_return_val_if_fail (n_data != NULL, NULL);
 
        info = certificate_info_load (self);
        g_return_val_if_fail (info, NULL);
 
-       return egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "issuer", NULL), n_data);
+       return egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "issuer", NULL));
 }
 
 /**
@@ -525,13 +543,21 @@ guchar *
 gcr_certificate_get_issuer_raw (GcrCertificate *self,
                                 gsize *n_data)
 {
-       gconstpointer data;
+       EggBytes *bytes;
+       guchar *result;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
        g_return_val_if_fail (n_data != NULL, NULL);
 
-       data = _gcr_certificate_get_issuer_const (self, n_data);
-       return g_memdup (data, data ? *n_data : 0);
+       bytes = _gcr_certificate_get_issuer_const (self);
+       if (bytes == NULL)
+               return NULL;
+
+       *n_data = egg_bytes_get_size (bytes);
+       result = g_memdup (egg_bytes_get_data (bytes), *n_data);
+       egg_bytes_unref (bytes);
+
+       return result;
 }
 
 /**
@@ -549,20 +575,25 @@ gcr_certificate_get_issuer_raw (GcrCertificate *self,
 gboolean
 gcr_certificate_is_issuer (GcrCertificate *self, GcrCertificate *issuer)
 {
-       gconstpointer subject_dn, issuer_dn;
-       gsize n_subject_dn, n_issuer_dn;
+       EggBytes *subject_dn;
+       EggBytes *issuer_dn;
+       gboolean ret;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), FALSE);
        g_return_val_if_fail (GCR_IS_CERTIFICATE (issuer), FALSE);
 
-       subject_dn = _gcr_certificate_get_subject_const (issuer, &n_subject_dn);
+       subject_dn = _gcr_certificate_get_subject_const (issuer);
        g_return_val_if_fail (subject_dn, FALSE);
 
-       issuer_dn = _gcr_certificate_get_issuer_const (self, &n_issuer_dn);
+       issuer_dn = _gcr_certificate_get_issuer_const (self);
        g_return_val_if_fail (issuer_dn, FALSE);
 
-       return (n_issuer_dn == n_subject_dn &&
-               memcmp (issuer_dn, subject_dn, n_issuer_dn) == 0);
+       ret = egg_bytes_equal (subject_dn, issuer_dn);
+
+       egg_bytes_unref (subject_dn);
+       egg_bytes_unref (issuer_dn);
+
+       return ret;
 }
 
 /**
@@ -663,18 +694,17 @@ gcr_certificate_get_subject_dn (GcrCertificate *self)
        return egg_dn_read (egg_asn1x_node (info->asn1, "tbsCertificate", "subject", "rdnSequence", NULL));
 }
 
-static gconstpointer
-_gcr_certificate_get_subject_const (GcrCertificate *self, gsize *n_data)
+static EggBytes *
+_gcr_certificate_get_subject_const (GcrCertificate *self)
 {
        GcrCertificateInfo *info;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
-       g_return_val_if_fail (n_data != NULL, NULL);
 
        info = certificate_info_load (self);
        g_return_val_if_fail (info, NULL);
 
-       return egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "subject", NULL), n_data);
+       return egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "subject", NULL));
 }
 
 /**
@@ -692,17 +722,22 @@ _gcr_certificate_get_subject_const (GcrCertificate *self, gsize *n_data)
 guchar *
 gcr_certificate_get_subject_raw (GcrCertificate *self, gsize *n_data)
 {
-       GcrCertificateInfo *info;
-       gconstpointer data;
+       EggBytes *bytes;
+       guchar *result;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
        g_return_val_if_fail (n_data != NULL, NULL);
 
-       info = certificate_info_load (self);
-       g_return_val_if_fail (info, NULL);
+       bytes = _gcr_certificate_get_subject_const (self);
+       if (bytes == NULL)
+               return NULL;
+
+       *n_data = egg_bytes_get_size (bytes);
+       result = g_memdup (egg_bytes_get_data (bytes), *n_data);
+
+       egg_bytes_unref (bytes);
 
-       data = _gcr_certificate_get_subject_const (self, n_data);
-       return g_memdup (data, data ? *n_data : 0);
+       return result;
 }
 
 /**
@@ -886,7 +921,8 @@ guchar *
 gcr_certificate_get_serial_number (GcrCertificate *self, gsize *n_length)
 {
        GcrCertificateInfo *info;
-       const guchar *serial;
+       EggBytes *bytes;
+       guchar *result;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
        g_return_val_if_fail (n_length != NULL, NULL);
@@ -894,8 +930,14 @@ gcr_certificate_get_serial_number (GcrCertificate *self, gsize *n_length)
        info = certificate_info_load (self);
        g_return_val_if_fail (info, NULL);
 
-       serial = egg_asn1x_get_integer_as_raw (egg_asn1x_node (info->asn1, "tbsCertificate", "serialNumber", NULL), n_length);
-       return g_memdup (serial, *n_length);
+       bytes = egg_asn1x_get_integer_as_raw (egg_asn1x_node (info->asn1, "tbsCertificate", "serialNumber", NULL));
+       g_return_val_if_fail (bytes != NULL, NULL);
+
+       *n_length = egg_bytes_get_size (bytes);
+       result = g_memdup (egg_bytes_get_data (bytes), *n_length);
+
+       egg_bytes_unref (bytes);
+       return result;
 }
 
 /**
index 39d9319..c84b977 100644 (file)
@@ -91,10 +91,11 @@ rsa_subject_public_key_from_attributes (GckAttributes *attrs, GNode *info_asn)
 {
        GckAttribute *modulus;
        GckAttribute *exponent;
+       EggBytes *key;
+       EggBytes *params;
        GNode *key_asn;
        GNode *params_asn;
-       gpointer key, params;
-       gsize n_key, n_params;
+       EggBytes *usg;
 
        _gcr_oids_init ();
 
@@ -109,27 +110,34 @@ rsa_subject_public_key_from_attributes (GckAttributes *attrs, GNode *info_asn)
        params_asn = egg_asn1x_create (pk_asn1_tab, "RSAParameters");
        g_return_val_if_fail (params_asn, FALSE);
 
-       egg_asn1x_set_integer_as_usg (egg_asn1x_node (key_asn, "modulus", NULL),
-                                     modulus->value, modulus->length, NULL);
+       usg = egg_bytes_new_with_free_func (modulus->value, modulus->length,
+                                           gck_attributes_unref,
+                                           gck_attributes_ref (attrs));
+       egg_asn1x_set_integer_as_usg (egg_asn1x_node (key_asn, "modulus", NULL), usg);
+       egg_bytes_unref (usg);
 
-       egg_asn1x_set_integer_as_usg (egg_asn1x_node (key_asn, "publicExponent", NULL),
-                                     exponent->value, exponent->length, NULL);
+       usg = egg_bytes_new_with_free_func (exponent->value, exponent->length,
+                                           gck_attributes_unref,
+                                           gck_attributes_ref (attrs));
+       egg_asn1x_set_integer_as_usg (egg_asn1x_node (key_asn, "publicExponent", NULL), usg);
+       egg_bytes_unref (usg);
 
-       key = egg_asn1x_encode (key_asn, g_realloc, &n_key);
+       key = egg_asn1x_encode (key_asn, NULL);
        egg_asn1x_destroy (key_asn);
 
        egg_asn1x_set_null (params_asn);
 
-       params = egg_asn1x_encode (params_asn, g_realloc, &n_params);
+       params = egg_asn1x_encode (params_asn, g_realloc);
        egg_asn1x_destroy (params_asn);
 
        egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
-                                  key, n_key * 8, g_free);
+                                  key, egg_bytes_get_size (key) * 8);
 
        egg_asn1x_set_oid_as_quark (egg_asn1x_node (info_asn, "algorithm", "algorithm", NULL), GCR_OID_PKIX1_RSA);
-       egg_asn1x_set_raw_element (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL),
-                                  params, n_params, g_free);
+       egg_asn1x_set_raw_element (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL), params);
 
+       egg_bytes_unref (key);
+       egg_bytes_unref (params);
        return TRUE;
 }
 
@@ -161,7 +169,8 @@ dsa_subject_public_key_from_private (GNode *key_asn, GckAttribute *ap,
 
        gcry = gcry_mpi_aprint (GCRYMPI_FMT_STD, &buffer, &n_buffer, my);
        g_return_val_if_fail (gcry == 0, FALSE);
-       egg_asn1x_set_integer_as_raw (key_asn, buffer, n_buffer, gcry_free);
+       egg_asn1x_take_integer_as_raw (key_asn, egg_bytes_new_with_free_func (buffer, n_buffer,
+                                                                             gcry_free, buffer));
 
        gcry_mpi_release (mp);
        gcry_mpi_release (mq);
@@ -179,8 +188,8 @@ dsa_subject_public_key_from_attributes (GckAttributes *attrs,
 {
        GckAttribute *value, *g, *q, *p;
        GNode *key_asn, *params_asn;
-       gpointer key, params;
-       gsize n_key, n_params;
+       EggBytes *key;
+       EggBytes *params;
 
        _gcr_oids_init ();
 
@@ -198,9 +207,18 @@ dsa_subject_public_key_from_attributes (GckAttributes *attrs,
        params_asn = egg_asn1x_create (pk_asn1_tab, "DSAParameters");
        g_return_val_if_fail (params_asn, FALSE);
 
-       egg_asn1x_set_integer_as_usg (egg_asn1x_node (params_asn, "p", NULL), p->value, p->length, NULL);
-       egg_asn1x_set_integer_as_usg (egg_asn1x_node (params_asn, "q", NULL), q->value, q->length, NULL);
-       egg_asn1x_set_integer_as_usg (egg_asn1x_node (params_asn, "g", NULL), g->value, g->length, NULL);
+       egg_asn1x_take_integer_as_usg (egg_asn1x_node (params_asn, "p", NULL),
+                                      egg_bytes_new_with_free_func (p->value, p->length,
+                                                                    gck_attributes_unref,
+                                                                    gck_attributes_ref (attrs)));
+       egg_asn1x_take_integer_as_usg (egg_asn1x_node (params_asn, "q", NULL),
+                                      egg_bytes_new_with_free_func (q->value, q->length,
+                                                                    gck_attributes_unref,
+                                                                    gck_attributes_ref (attrs)));
+       egg_asn1x_take_integer_as_usg (egg_asn1x_node (params_asn, "g", NULL),
+                                      egg_bytes_new_with_free_func (g->value, g->length,
+                                                                    gck_attributes_unref,
+                                                                    gck_attributes_ref (attrs)));
 
        /* Are these attributes for a public or private key? */
        if (klass == CKO_PRIVATE_KEY) {
@@ -210,25 +228,29 @@ dsa_subject_public_key_from_attributes (GckAttributes *attrs,
                        g_return_val_if_reached (FALSE);
 
        } else if (klass == CKO_PUBLIC_KEY) {
-               egg_asn1x_set_integer_as_usg (key_asn, value->value, value->length, NULL);
+               egg_asn1x_take_integer_as_usg (key_asn,
+                                              egg_bytes_new_with_free_func (value->value, value->length,
+                                                                            gck_attributes_unref,
+                                                                            gck_attributes_ref (attrs)));
 
        } else {
                g_assert_not_reached ();
        }
 
-       key = egg_asn1x_encode (key_asn, g_realloc, &n_key);
+       key = egg_asn1x_encode (key_asn, NULL);
        egg_asn1x_destroy (key_asn);
 
-       params = egg_asn1x_encode (params_asn, g_realloc, &n_params);
+       params = egg_asn1x_encode (params_asn, NULL);
        egg_asn1x_destroy (params_asn);
 
-       egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
-                                  key, n_key * 8, g_free);
-       egg_asn1x_set_raw_element (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL),
-                                  params, n_params, g_free);
+       egg_asn1x_take_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
+                                   key, egg_bytes_get_size (key) * 8);
+       egg_asn1x_set_raw_element (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL), params);
 
        egg_asn1x_set_oid_as_quark (egg_asn1x_node (info_asn, "algorithm", "algorithm", NULL), GCR_OID_PKIX1_DSA);
 
+       egg_bytes_unref (key);
+       egg_bytes_unref (params);
        return TRUE;
 }
 
@@ -241,9 +263,8 @@ fingerprint_from_key_attributes (GckAttributes *attrs,
        gpointer fingerprint = NULL;
        gboolean ret = FALSE;
        GNode *info_asn;
-       gpointer info;
+       EggBytes *info;
        gulong key_type;
-       gsize n_info;
 
        if (!gck_attributes_find_ulong (attrs, CKA_KEY_TYPE, &key_type))
                return NULL;
@@ -261,11 +282,12 @@ fingerprint_from_key_attributes (GckAttributes *attrs,
                ret = FALSE;
 
        if (ret) {
-               info = egg_asn1x_encode (info_asn, g_realloc, &n_info);
-               fingerprint = gcr_fingerprint_from_subject_public_key_info (info, n_info,
+               info = egg_asn1x_encode (info_asn, NULL);
+               fingerprint = gcr_fingerprint_from_subject_public_key_info (egg_bytes_get_data (info),
+                                                                           egg_bytes_get_size (info),
                                                                            checksum_type,
                                                                            n_fingerprint);
-               g_free (info);
+               egg_bytes_unref (info);
        }
 
        egg_asn1x_destroy (info_asn);
@@ -273,25 +295,23 @@ fingerprint_from_key_attributes (GckAttributes *attrs,
 }
 
 static guchar *
-fingerprint_from_cert_value (const guchar *der_data,
-                             gsize n_der_data,
+fingerprint_from_cert_value (EggBytes *der_data,
                              GChecksumType checksum_type,
                              gsize *n_fingerprint)
 {
        guchar *fingerprint;
        GNode *cert_asn;
-       gconstpointer info;
-       gsize n_info;
+       EggBytes *info;
 
-       cert_asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate",
-                                               der_data, n_der_data);
+       cert_asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", der_data);
        if (cert_asn == NULL)
                return NULL;
 
-       info = egg_asn1x_get_raw_element (egg_asn1x_node (cert_asn, "tbsCertificate", "subjectPublicKeyInfo", NULL), &n_info);
+       info = egg_asn1x_get_raw_element (egg_asn1x_node (cert_asn, "tbsCertificate", "subjectPublicKeyInfo", NULL));
        g_return_val_if_fail (info != NULL, NULL);
 
-       fingerprint = gcr_fingerprint_from_subject_public_key_info (info, n_info,
+       fingerprint = gcr_fingerprint_from_subject_public_key_info (egg_bytes_get_data (info),
+                                                                   egg_bytes_get_size (info),
                                                                    checksum_type,
                                                                    n_fingerprint);
 
@@ -305,13 +325,20 @@ fingerprint_from_cert_attributes (GckAttributes *attrs,
                                   gsize *n_fingerprint)
 {
        GckAttribute *attr;
+       EggBytes *bytes;
+       guchar *fingerprint;
 
        attr = gck_attributes_find (attrs, CKA_VALUE);
        if (attr == NULL)
                return NULL;
 
-       return fingerprint_from_cert_value (attr->value, attr->length, checksum_type,
-                                           n_fingerprint);
+       bytes = egg_bytes_new_with_free_func (attr->value, attr->length,
+                                             gck_attributes_unref,
+                                             gck_attributes_ref (attrs));
+       fingerprint = fingerprint_from_cert_value (bytes, checksum_type, n_fingerprint);
+
+       egg_bytes_unref (bytes);
+       return fingerprint;
 }
 
 /**
@@ -373,12 +400,18 @@ gcr_fingerprint_from_certificate_public_key (GcrCertificate *certificate,
 {
        const guchar *der_data;
        gsize n_der_data;
+       EggBytes *bytes;
+       guchar *fingerprint;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), NULL);
 
        der_data = gcr_certificate_get_der_data (certificate, &n_der_data);
        g_return_val_if_fail (der_data != NULL, NULL);
 
-       return fingerprint_from_cert_value (der_data, n_der_data, checksum_type,
-                                           n_fingerprint);
+       bytes = egg_bytes_new_with_free_func (der_data, n_der_data, g_object_unref,
+                                             g_object_ref (certificate));
+       fingerprint = fingerprint_from_cert_value (bytes, checksum_type, n_fingerprint);
+       egg_bytes_unref (bytes);
+
+       return fingerprint;
 }
index 3bd41bb..b80f560 100644 (file)
@@ -1197,6 +1197,7 @@ typedef struct {
        GcrOpenpgpCallback callback;
        gpointer user_data;
        guint count;
+       EggBytes *backing;
        GPtrArray *records;
 } openpgp_parse_closure;
 
@@ -1205,6 +1206,7 @@ openpgp_parse_free (gpointer data)
 {
        openpgp_parse_closure *closure = data;
        g_ptr_array_unref (closure->records);
+       egg_bytes_unref (closure->backing);
        g_free (closure);
 }
 
@@ -1213,6 +1215,7 @@ maybe_emit_openpgp_block (openpgp_parse_closure *closure,
                           const guchar *block,
                           const guchar *end)
 {
+       EggBytes *outer;
        gsize length;
        GPtrArray *records;
 
@@ -1228,15 +1231,17 @@ maybe_emit_openpgp_block (openpgp_parse_closure *closure,
        records = closure->records;
        closure->records = g_ptr_array_new_with_free_func (_gcr_record_free);
 
+       outer = egg_bytes_new_with_free_func (block, length, egg_bytes_unref,
+                                             egg_bytes_ref (closure->backing));
        if (closure->callback)
-               (closure->callback) (records, block, length, closure->user_data);
+               (closure->callback) (records, outer, closure->user_data);
+       egg_bytes_unref (outer);
 
        g_ptr_array_unref (records);
 }
 
 guint
-_gcr_openpgp_parse (gconstpointer data,
-                    gsize n_data,
+_gcr_openpgp_parse (EggBytes *data,
                     GcrOpenpgpParseFlags flags,
                     GcrOpenpgpCallback callback,
                     gpointer user_data)
@@ -1257,13 +1262,14 @@ _gcr_openpgp_parse (gconstpointer data,
        /* For libgcrypt */
        _gcr_initialize_library ();
 
-       at = data;
-       end = at + n_data;
+       at = egg_bytes_get_data (data);
+       end = at + egg_bytes_get_size (data);
        block = NULL;
 
        closure = g_new0 (openpgp_parse_closure, 1);
        closure->callback = callback;
        closure->user_data = user_data;
+       closure->backing = egg_bytes_ref (data);
        closure->records = g_ptr_array_new_with_free_func (_gcr_record_free);
 
        while (at != NULL && at != end) {
index 31fd295..aed7d8d 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <glib.h>
 
+#include <egg/egg-bytes.h>
+
 #include <gck/gck.h>
 
 typedef enum {
@@ -51,12 +53,10 @@ typedef enum {
 G_BEGIN_DECLS
 
 typedef void             (*GcrOpenpgpCallback)             (GPtrArray *records,
-                                                            const guchar *outer,
-                                                            gsize n_outer,
+                                                            EggBytes *outer,
                                                             gpointer user_data);
 
-guint                    _gcr_openpgp_parse                (gconstpointer data,
-                                                            gsize n_data,
+guint                    _gcr_openpgp_parse                (EggBytes *data,
                                                             GcrOpenpgpParseFlags flags,
                                                             GcrOpenpgpCallback callback,
                                                             gpointer user_data);
index 3a35c60..e8eef4a 100644 (file)
@@ -154,6 +154,7 @@ atoin (const char *p, gint digits)
 static GcrDataError
 parse_v1_public_line (const gchar *line,
                       gsize length,
+                      EggBytes *backing,
                       GcrOpensshPubCallback callback,
                       gpointer user_data)
 {
@@ -161,6 +162,7 @@ parse_v1_public_line (const gchar *line,
        gsize len_bits, len_exponent, len_modulus, len_options, n_outer;
        GckAttributes *attrs;
        gchar *label, *options;
+       EggBytes *bytes;
        gint bits;
 
        g_assert (line);
@@ -224,8 +226,13 @@ parse_v1_public_line (const gchar *line,
        if (word_options)
                options = g_strndup (word_options, len_options);
 
-       if (callback != NULL)
-               (callback) (attrs, label, options, outer, n_outer, user_data);
+       if (callback != NULL) {
+               bytes = egg_bytes_new_with_free_func (outer, n_outer,
+                                                     egg_bytes_unref,
+                                                     egg_bytes_ref (backing));
+               (callback) (attrs, label, options, bytes, user_data);
+               egg_bytes_unref (bytes);
+       }
 
        gck_attributes_unref (attrs);
        g_free (options);
@@ -367,6 +374,7 @@ decode_v2_public_key (gulong algo,
 static GcrDataError
 parse_v2_public_line (const gchar *line,
                       gsize length,
+                      EggBytes *backing,
                       GcrOpensshPubCallback callback,
                       gpointer user_data)
 {
@@ -377,6 +385,7 @@ parse_v2_public_line (const gchar *line,
        gchar *label = NULL;
        const gchar *outer = line;
        gsize n_outer = length;
+       EggBytes *bytes;
        gulong algo;
 
        g_assert (line);
@@ -435,8 +444,13 @@ parse_v2_public_line (const gchar *line,
                gck_attributes_add_string (attrs, CKA_LABEL, label);
        }
 
-       if (callback != NULL)
-               (callback) (attrs, label, options, outer, n_outer, user_data);
+       if (callback != NULL) {
+               bytes = egg_bytes_new_with_free_func (outer, n_outer,
+                                                     egg_bytes_unref,
+                                                     egg_bytes_ref (backing));
+               (callback) (attrs, label, options, bytes, user_data);
+               egg_bytes_unref (bytes);
+       }
 
        gck_attributes_unref (attrs);
        g_free (options);
@@ -445,8 +459,7 @@ parse_v2_public_line (const gchar *line,
 }
 
 guint
-_gcr_openssh_pub_parse (gconstpointer data,
-                        gsize n_data,
+_gcr_openssh_pub_parse (EggBytes *data,
                         GcrOpensshPubCallback callback,
                         gpointer user_data)
 {
@@ -457,10 +470,10 @@ _gcr_openssh_pub_parse (gconstpointer data,
        GcrDataError res;
        guint num_parsed;
 
-       g_return_val_if_fail (data, FALSE);
+       g_return_val_if_fail (data != NULL, FALSE);
 
-       line = data;
-       length = n_data;
+       line = egg_bytes_get_data (data);
+       length = egg_bytes_get_size (data);
        last = FALSE;
        num_parsed = 0;
 
@@ -472,9 +485,9 @@ _gcr_openssh_pub_parse (gconstpointer data,
                }
 
                if (line != end) {
-                       res = parse_v2_public_line (line, end - line, callback, user_data);
+                       res = parse_v2_public_line (line, end - line, data, callback, user_data);
                        if (res == GCR_ERROR_UNRECOGNIZED)
-                               res = parse_v1_public_line (line, end - line, callback, user_data);
+                               res = parse_v1_public_line (line, end - line, data, callback, user_data);
                        if (res == GCR_SUCCESS)
                                num_parsed++;
                }
index 2fdac2a..4f4fe9e 100644 (file)
 
 #include <gck/gck.h>
 
+#include <egg/egg-bytes.h>
+
 G_BEGIN_DECLS
 
 typedef void             (*GcrOpensshPubCallback)          (GckAttributes *attrs,
                                                             const gchar *label,
                                                             const gchar *options,
-                                                            const gchar *outer,
-                                                            gsize n_outer,
+                                                            EggBytes *outer,
                                                             gpointer user_data);
 
-guint                    _gcr_openssh_pub_parse            (gconstpointer data,
-                                                            gsize n_data,
+guint                    _gcr_openssh_pub_parse            (EggBytes *data,
                                                             GcrOpensshPubCallback callback,
                                                             gpointer user_data);
 
index 096bbfe..ebdc8a3 100644 (file)
@@ -123,10 +123,8 @@ struct _GcrParsed {
        GckAttributes *attrs;
        const gchar *description;
        gchar *label;
-       gpointer data;
-       gsize n_data;
+       EggBytes *data;
        gboolean sensitive;
-       GDestroyNotify destroy_func;
        GcrDataFormat format;
        struct _GcrParsed *next;
 };
@@ -149,7 +147,7 @@ typedef struct {
 
 typedef struct _ParserFormat {
        gint format_id;
-       gint (*function) (GcrParser *self, const guchar *data, gsize n_data);
+       gint (*function) (GcrParser *self, EggBytes *data);
 } ParserFormat;
 
 /* Forward declarations */
@@ -224,23 +222,35 @@ parsed_attribute (GcrParsed *parsed,
        gck_attributes_add_data (parsed->attrs, type, data, n_data);
 }
 
+static void
+parsed_attribute_bytes (GcrParsed *parsed,
+                        CK_ATTRIBUTE_TYPE type,
+                        EggBytes *data)
+{
+       g_assert (parsed != NULL);
+       g_assert (parsed->attrs != NULL);
+       gck_attributes_add_data (parsed->attrs, type,
+                                egg_bytes_get_data (data),
+                                egg_bytes_get_size (data));
+}
+
 static gboolean
 parsed_asn1_number (GcrParsed *parsed,
                     GNode *asn,
                     const gchar *part,
                     CK_ATTRIBUTE_TYPE type)
 {
-       const guchar *value;
-       gsize n_value;
+       EggBytes *value;
 
        g_assert (asn);
        g_assert (parsed);
 
-       value = egg_asn1x_get_integer_as_usg (egg_asn1x_node (asn, part, NULL), &n_value);
+       value = egg_asn1x_get_integer_as_usg (egg_asn1x_node (asn, part, NULL));
        if (value == NULL)
                return FALSE;
 
-       parsed_attribute (parsed, type, value, n_value);
+       parsed_attribute_bytes (parsed, type, value);
+       egg_bytes_unref (value);
        return TRUE;
 }
 
@@ -250,17 +260,17 @@ parsed_asn1_element (GcrParsed *parsed,
                      const gchar *part,
                      CK_ATTRIBUTE_TYPE type)
 {
-       const guchar *value;
-       gsize n_value;
+       EggBytes *value;
 
        g_assert (asn);
        g_assert (parsed);
 
-       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, part, NULL), &n_value);
+       value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, part, NULL));
        if (value == NULL)
                return FALSE;
 
-       parsed_attribute (parsed, type, value, n_value);
+       parsed_attribute_bytes (parsed, type, value);
+       egg_bytes_unref (value);
        return TRUE;
 }
 
@@ -288,19 +298,15 @@ parsed_boolean_attribute (GcrParsed *parsed,
 static void
 parsing_block (GcrParsed *parsed,
                gint format,
-               gconstpointer data,
-               gsize n_data)
+               EggBytes *data)
 {
        g_assert (parsed != NULL);
        g_assert (data != NULL);
-       g_assert (n_data != 0);
-       g_assert (format);
+       g_assert (format != 0);
        g_assert (parsed->data == NULL);
-       g_assert (parsed->destroy_func == NULL);
 
        parsed->format = format;
-       parsed->data = (gpointer)data;
-       parsed->n_data = n_data;
+       parsed->data = egg_bytes_ref (data);
 }
 
 static void
@@ -457,7 +463,8 @@ parsed_fire (GcrParser *self,
  */
 
 static gint
-parse_der_private_key_rsa (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_private_key_rsa (GcrParser *self,
+                           EggBytes *data)
 {
        gint res = GCR_ERROR_UNRECOGNIZED;
        GNode *asn = NULL;
@@ -466,11 +473,11 @@ parse_der_private_key_rsa (GcrParser *self, const guchar *data, gsize n_data)
 
        parsed = push_parsed (self, TRUE);
 
-       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data, n_data);
+       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data);
        if (!asn)
                goto done;
 
-       parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data, n_data);
+       parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data);
        parsing_object (parsed, CKO_PRIVATE_KEY);
        parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_RSA);
        parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
@@ -511,7 +518,8 @@ done:
  */
 
 static gint
-parse_der_private_key_dsa (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_private_key_dsa (GcrParser *self,
+                           EggBytes *data)
 {
        gint ret = GCR_ERROR_UNRECOGNIZED;
        GNode *asn = NULL;
@@ -519,11 +527,11 @@ parse_der_private_key_dsa (GcrParser *self, const guchar *data, gsize n_data)
 
        parsed = push_parsed (self, TRUE);
 
-       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data, n_data);
+       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data);
        if (!asn)
                goto done;
 
-       parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data, n_data);
+       parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data);
        parsing_object (parsed, CKO_PRIVATE_KEY);
        parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
        parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
@@ -548,8 +556,9 @@ done:
 }
 
 static gint
-parse_der_private_key_dsa_parts (GcrParser *self, const guchar *keydata, gsize n_keydata,
-                                 const guchar *params, gsize n_params)
+parse_der_private_key_dsa_parts (GcrParser *self,
+                                 EggBytes *keydata,
+                                 EggBytes *params)
 {
        gint ret = GCR_ERROR_UNRECOGNIZED;
        GNode *asn_params = NULL;
@@ -558,8 +567,8 @@ parse_der_private_key_dsa_parts (GcrParser *self, const guchar *keydata, gsize n
 
        parsed = push_parsed (self, TRUE);
 
-       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);
+       asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params);
+       asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata);
        if (!asn_params || !asn_key)
                goto done;
 
@@ -592,13 +601,14 @@ done:
  */
 
 static gint
-parse_der_private_key (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_private_key (GcrParser *self,
+                       EggBytes *data)
 {
        gint res;
 
-       res = parse_der_private_key_rsa (self, data, n_data);
+       res = parse_der_private_key_rsa (self, data);
        if (res == GCR_ERROR_UNRECOGNIZED)
-               res = parse_der_private_key_dsa (self, data, n_data);
+               res = parse_der_private_key_dsa (self, data);
 
        return res;
 }
@@ -608,26 +618,25 @@ parse_der_private_key (GcrParser *self, const guchar *data, gsize n_data)
  */
 
 static gint
-parse_der_pkcs8_plain (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_pkcs8_plain (GcrParser *self,
+                       EggBytes *data)
 {
        gint ret;
        CK_KEY_TYPE key_type;
        GQuark key_algo;
-       const guchar *keydata;
-       gsize n_keydata;
-       const guchar *params;
-       gsize n_params;
+       EggBytes *keydata = NULL;
+       EggBytes *params = NULL;
        GNode *asn = NULL;
        GcrParsed *parsed;
 
        parsed = push_parsed (self, TRUE);
        ret = GCR_ERROR_UNRECOGNIZED;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data);
        if (!asn)
                goto done;
 
-       parsing_block (parsed, GCR_FORMAT_DER_PKCS8_PLAIN, data, n_data);
+       parsing_block (parsed, GCR_FORMAT_DER_PKCS8_PLAIN, data);
        ret = GCR_ERROR_FAILURE;
        key_type = GCK_INVALID;
 
@@ -644,11 +653,11 @@ parse_der_pkcs8_plain (GcrParser *self, const guchar *data, gsize n_data)
                goto done;
        }
 
-       keydata = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "privateKey", NULL), &n_keydata);
+       keydata = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "privateKey", NULL));
        if (!keydata)
                goto done;
 
-       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL), &n_params);
+       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL));
 
        ret = SUCCESS;
 
@@ -656,16 +665,15 @@ done:
        if (ret == SUCCESS) {
                switch (key_type) {
                case CKK_RSA:
-                       ret = parse_der_private_key_rsa (self, keydata, n_keydata);
+                       ret = parse_der_private_key_rsa (self, keydata);
                        break;
                case CKK_DSA:
                        /* Try the normal sane format */
-                       ret = parse_der_private_key_dsa (self, keydata, n_keydata);
+                       ret = parse_der_private_key_dsa (self, keydata);
 
                        /* Otherwise try the two part format that everyone seems to like */
-                       if (ret == GCR_ERROR_UNRECOGNIZED && params && n_params)
-                               ret = parse_der_private_key_dsa_parts (self, keydata, n_keydata,
-                                                                      params, n_params);
+                       if (ret == GCR_ERROR_UNRECOGNIZED && params)
+                               ret = parse_der_private_key_dsa_parts (self, keydata, params);
                        break;
                default:
                        g_message ("invalid or unsupported key type in PKCS#8 key");
@@ -677,13 +685,18 @@ done:
                g_message ("invalid PKCS#8 key");
        }
 
+       if (keydata)
+               egg_bytes_unref (keydata);
+       if (params)
+               egg_bytes_unref (params);
        egg_asn1x_destroy (asn);
        pop_parsed (self, parsed);
        return ret;
 }
 
 static gint
-parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_pkcs8_encrypted (GcrParser *self,
+                           EggBytes *data)
 {
        PasswordState pstate = PASSWORD_STATE_INIT;
        GNode *asn = NULL;
@@ -692,8 +705,9 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
        gint ret, r;
        GQuark scheme;
        guchar *crypted = NULL;
-       const guchar *params;
-       gsize n_crypted, n_params;
+       EggBytes *params = NULL;
+       EggBytes *cbytes;
+       gsize n_crypted;
        const gchar *password;
        GcrParsed *parsed;
        gint l;
@@ -701,11 +715,11 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
        parsed = push_parsed (self, FALSE);
        ret = GCR_ERROR_UNRECOGNIZED;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data);
        if (!asn)
                goto done;
 
-       parsing_block (parsed, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data, n_data);
+       parsing_block (parsed, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data);
        ret = GCR_ERROR_FAILURE;
 
        /* Figure out the type of encryption */
@@ -713,7 +727,7 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
        if (!scheme)
                goto done;
 
-       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), &n_params);
+       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL));
 
        /* Loop to try different passwords */
        for (;;) {
@@ -727,7 +741,7 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
                }
 
                /* Parse the encryption stuff into a cipher. */
-               if (!egg_symkey_read_cipher (scheme, password, -1, params, n_params, &cih))
+               if (!egg_symkey_read_cipher (scheme, password, -1, params, &cih))
                        break;
 
                crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedData", NULL), egg_secure_realloc, &n_crypted);
@@ -748,11 +762,14 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
                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);
+               cbytes = egg_bytes_new_with_free_func (crypted, n_crypted,
+                                                      egg_secure_free, crypted);
                crypted = NULL;
 
+               /* Try to parse the resulting key */
+               r = parse_der_pkcs8_plain (self, cbytes);
+               egg_bytes_unref (cbytes);
+
                if (r != GCR_ERROR_UNRECOGNIZED) {
                        ret = r;
                        break;
@@ -762,6 +779,8 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
        }
 
 done:
+       if (params)
+               egg_bytes_unref (params);
        if (cih)
                gcry_cipher_close (cih);
        egg_asn1x_destroy (asn);
@@ -772,13 +791,14 @@ done:
 }
 
 static gint
-parse_der_pkcs8 (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_pkcs8 (GcrParser *self,
+                 EggBytes *data)
 {
        gint ret;
 
-       ret = parse_der_pkcs8_plain (self, data, n_data);
+       ret = parse_der_pkcs8_plain (self, data);
        if (ret == GCR_ERROR_UNRECOGNIZED)
-               ret = parse_der_pkcs8_encrypted (self, data, n_data);
+               ret = parse_der_pkcs8_encrypted (self, data);
 
        return ret;
 }
@@ -788,20 +808,21 @@ parse_der_pkcs8 (GcrParser *self, const guchar *data, gsize n_data)
  */
 
 static gint
-parse_der_certificate (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_certificate (GcrParser *self,
+                       EggBytes *data)
 {
        gchar *name = NULL;
        GcrParsed *parsed;
        GNode *node;
        GNode *asn;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data);
        if (asn == NULL)
                return GCR_ERROR_UNRECOGNIZED;
 
        parsed = push_parsed (self, FALSE);
 
-       parsing_block (parsed, GCR_FORMAT_DER_CERTIFICATE_X509, data, n_data);
+       parsing_block (parsed, GCR_FORMAT_DER_CERTIFICATE_X509, data);
        parsing_object (parsed, CKO_CERTIFICATE);
        parsed_ulong_attribute (parsed, CKA_CERTIFICATE_TYPE, CKC_X_509);
 
@@ -816,7 +837,7 @@ parse_der_certificate (GcrParser *self, const guchar *data, gsize n_data)
                g_free (name);
        }
 
-       parsed_attribute (parsed, CKA_VALUE, data, n_data);
+       parsed_attribute_bytes (parsed, CKA_VALUE, data);
        parsed_asn1_element (parsed, node, "subject", CKA_SUBJECT);
        parsed_asn1_element (parsed, node, "issuer", CKA_ISSUER);
        parsed_asn1_number (parsed, node, "serialNumber", CKA_SERIAL_NUMBER);
@@ -833,18 +854,18 @@ parse_der_certificate (GcrParser *self, const guchar *data, gsize n_data)
  */
 
 static gint
-handle_pkcs7_signed_data (GcrParser *self, const guchar *data, gsize n_data)
+handle_pkcs7_signed_data (GcrParser *self,
+                          EggBytes *data)
 {
        GNode *asn = NULL;
        GNode *node;
        gint ret;
-       const guchar *certificate;
-       gsize n_certificate;
+       EggBytes *certificate;
        int i;
 
        ret = GCR_ERROR_UNRECOGNIZED;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-SignedData", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-SignedData", data);
        if (!asn)
                goto done;
 
@@ -858,9 +879,10 @@ handle_pkcs7_signed_data (GcrParser *self, const guchar *data, gsize n_data)
                if (node == NULL)
                        break;
 
-               certificate = egg_asn1x_get_raw_element (node, &n_certificate);
+               certificate = egg_asn1x_get_raw_element (node);
+               ret = parse_der_certificate (self, certificate);
+               egg_bytes_unref (certificate);
 
-               ret = parse_der_certificate (self, certificate, n_certificate);
                if (ret != SUCCESS)
                        goto done;
        }
@@ -875,24 +897,24 @@ done:
 }
 
 static gint
-parse_der_pkcs7 (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_pkcs7 (GcrParser *self,
+                 EggBytes *data)
 {
        GNode *asn = NULL;
        GNode *node;
        gint ret;
-       const guchar* content = NULL;
-       gsize n_content;
+       EggBytes *content = NULL;
        GQuark oid;
        GcrParsed *parsed;
 
        parsed = push_parsed (self, FALSE);
        ret = GCR_ERROR_UNRECOGNIZED;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-ContentInfo", data, n_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-ContentInfo", data);
        if (!asn)
                goto done;
 
-       parsing_block (parsed, GCR_FORMAT_DER_PKCS7, data, n_data);
+       parsing_block (parsed, GCR_FORMAT_DER_PKCS7, data);
        ret = GCR_ERROR_FAILURE;
 
        node = egg_asn1x_node (asn, "contentType", NULL);
@@ -908,13 +930,15 @@ parse_der_pkcs7 (GcrParser *self, const guchar *data, gsize n_data)
                goto done;
        }
 
-       content = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "content", NULL), &n_content);
+       content = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "content", NULL));
        if (!content)
                goto done;
 
-       ret = handle_pkcs7_signed_data (self, content, n_content);
+       ret = handle_pkcs7_signed_data (self, content);
 
 done:
+       if (content)
+               egg_bytes_unref (content);
        egg_asn1x_destroy (asn);
        pop_parsed (self, parsed);
        return ret;
@@ -927,8 +951,7 @@ done:
 static GNode *
 decode_pkcs12_asn1_accepting_invalid_crap (const ASN1_ARRAY_TYPE *defs,
                                            const gchar *identifier,
-                                           gconstpointer data,
-                                           gsize n_data)
+                                           EggBytes *data)
 {
        GNode *asn;
 
@@ -947,7 +970,7 @@ decode_pkcs12_asn1_accepting_invalid_crap (const ASN1_ARRAY_TYPE *defs,
        g_return_val_if_fail (asn != NULL, NULL);
 
        /* Passing FALSE as the strictness argument */
-       if (!egg_asn1x_decode_no_validate (asn, data, n_data) ||
+       if (!egg_asn1x_decode_no_validate (asn, data) ||
            !egg_asn1x_validate (asn, FALSE)) {
                egg_asn1x_destroy (asn);
                asn = NULL;
@@ -957,29 +980,31 @@ decode_pkcs12_asn1_accepting_invalid_crap (const ASN1_ARRAY_TYPE *defs,
 }
 
 static gint
-handle_pkcs12_cert_bag (GcrParser *self, const guchar *data, gsize n_data)
+handle_pkcs12_cert_bag (GcrParser *self,
+                        EggBytes *data)
 {
        GNode *asn = NULL;
        GNode *asn_content = NULL;
        guchar *certificate = NULL;
-       const guchar *element;
-       gsize n_certificate, n_element;
+       EggBytes *element = NULL;
+       gsize n_certificate;
+       EggBytes *bytes;
        gint ret;
 
        ret = GCR_ERROR_UNRECOGNIZED;
        asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab,
                                                         "pkcs-12-CertBag",
-                                                        data, n_data);
+                                                        data);
        if (!asn)
                goto done;
 
        ret = GCR_ERROR_FAILURE;
 
-       element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "certValue", NULL), &n_element);
+       element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "certValue", NULL));
        if (!element)
                goto done;
 
-       asn_content = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-Data", element, n_element);
+       asn_content = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-Data", element);
        if (!asn_content)
                goto done;
 
@@ -987,12 +1012,15 @@ handle_pkcs12_cert_bag (GcrParser *self, const guchar *data, gsize n_data)
        if (!certificate)
                goto done;
 
-       ret = parse_der_certificate (self, certificate, n_certificate);
+       bytes = egg_bytes_new_take (certificate, n_certificate);
+       ret = parse_der_certificate (self, bytes);
+       egg_bytes_unref (bytes);
 
 done:
+       if (element)
+               egg_bytes_unref (element);
        egg_asn1x_destroy (asn_content);
        egg_asn1x_destroy (asn);
-       g_free (certificate);
        return ret;
 }
 
@@ -1002,8 +1030,7 @@ parse_pkcs12_bag_friendly_name (GNode *asn)
        guint count, i;
        GQuark oid;
        GNode *node;
-       gconstpointer element;
-       gsize n_element;
+       EggBytes *element;
        GNode *asn_str;
        gchar *result;
 
@@ -1016,9 +1043,10 @@ parse_pkcs12_bag_friendly_name (GNode *asn)
                if (oid == GCR_OID_PKCS9_ATTRIBUTE_FRIENDLY) {
                        node = egg_asn1x_node (asn, i, "values", 1, NULL);
                        if (node != NULL) {
-                               element = egg_asn1x_get_raw_element (node, &n_element);
+                               element = egg_asn1x_get_raw_element (node);
                                asn_str = egg_asn1x_create_and_decode (pkix_asn1_tab, "BMPString",
-                                                                      element, n_element);
+                                                                      element);
+                               egg_bytes_unref (element);
                                if (asn_str) {
                                        result = egg_asn1x_get_bmpstring_as_utf8 (asn_str);
                                        egg_asn1x_destroy (asn_str);
@@ -1032,15 +1060,15 @@ parse_pkcs12_bag_friendly_name (GNode *asn)
 }
 
 static gint
-handle_pkcs12_bag (GcrParser *self, const guchar *data, gsize n_data)
+handle_pkcs12_bag (GcrParser *self,
+                   EggBytes *data)
 {
        GNode *asn = NULL;
        gint ret, r;
        guint count = 0;
        GQuark oid;
-       const guchar *element;
+       EggBytes *element = NULL;
        gchar *friendly;
-       gsize n_element;
        guint i;
        GcrParsed *parsed;
 
@@ -1048,7 +1076,7 @@ handle_pkcs12_bag (GcrParser *self, const guchar *data, gsize n_data)
 
        asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab,
                                                         "pkcs-12-SafeContents",
-                                                        data, n_data);
+                                                        data);
        if (!asn)
                goto done;
 
@@ -1067,7 +1095,7 @@ handle_pkcs12_bag (GcrParser *self, const guchar *data, gsize n_data)
                if (!oid)
                        goto done;
 
-               element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, i, "bagValue", NULL), &n_element);
+               element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, i, "bagValue", NULL));
                if (!element)
                        goto done;
 
@@ -1079,21 +1107,24 @@ handle_pkcs12_bag (GcrParser *self, const guchar *data, gsize n_data)
 
                /* A normal unencrypted key */
                if (oid == GCR_OID_PKCS12_BAG_PKCS8_KEY) {
-                       r = parse_der_pkcs8_plain (self, element, n_element);
+                       r = parse_der_pkcs8_plain (self, element);
 
                /* A properly encrypted key */
                } else if (oid == GCR_OID_PKCS12_BAG_PKCS8_ENCRYPTED_KEY) {
-                       r = parse_der_pkcs8_encrypted (self, element, n_element);
+                       r = parse_der_pkcs8_encrypted (self, element);
 
                /* A certificate */
                } else if (oid == GCR_OID_PKCS12_BAG_CERTIFICATE) {
-                       r = handle_pkcs12_cert_bag (self, element, n_element);
+                       r = handle_pkcs12_cert_bag (self, element);
 
                /* TODO: GCR_OID_PKCS12_BAG_CRL */
                } else {
                        r = GCR_ERROR_UNRECOGNIZED;
                }
 
+               if (element != NULL)
+                       egg_bytes_unref (element);
+
                pop_parsed (self, parsed);
 
                if (r == GCR_ERROR_FAILURE ||
@@ -1112,16 +1143,18 @@ done:
 }
 
 static gint
-handle_pkcs12_encrypted_bag (GcrParser *self, const guchar *data, gsize n_data)
+handle_pkcs12_encrypted_bag (GcrParser *self,
+                             EggBytes *data)
 {
        PasswordState pstate = PASSWORD_STATE_INIT;
        GNode *asn = NULL;
        gcry_cipher_hd_t cih = NULL;
        gcry_error_t gcry;
        guchar *crypted = NULL;
-       const guchar *params;
-       gsize n_params, n_crypted;
+       EggBytes *params = NULL;
+       gsize n_crypted;
        const gchar *password;
+       EggBytes *cbytes;
        GQuark scheme;
        gint ret, r;
        gint l;
@@ -1130,7 +1163,7 @@ handle_pkcs12_encrypted_bag (GcrParser *self, const guchar *data, gsize n_data)
 
        asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab,
                                                         "pkcs-7-EncryptedData",
-                                                        data, n_data);
+                                                        data);
        if (!asn)
                goto done;
 
@@ -1141,7 +1174,7 @@ handle_pkcs12_encrypted_bag (GcrParser *self, const guchar *data, gsize n_data)
        if (!scheme)
                goto done;
 
-       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptedContentInfo", "contentEncryptionAlgorithm", "parameters", NULL), &n_params);
+       params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptedContentInfo", "contentEncryptionAlgorithm", "parameters", NULL));
        if (!params)
                goto done;
 
@@ -1157,7 +1190,7 @@ handle_pkcs12_encrypted_bag (GcrParser *self, const guchar *data, gsize n_data)
                }
 
                /* Parse the encryption stuff into a cipher. */
-               if (!egg_symkey_read_cipher (scheme, password, -1, params, n_params, &cih)) {
+               if (!egg_symkey_read_cipher (scheme, password, -1, params, &cih)) {
                        ret = GCR_ERROR_FAILURE;
                        goto done;
                }
@@ -1181,11 +1214,13 @@ handle_pkcs12_encrypted_bag (GcrParser *self, const guchar *data, gsize n_data)
                if (l > 0)
                        n_crypted = l;
 
-               /* Try to parse the resulting key */
-               r = handle_pkcs12_bag (self, crypted, n_crypted);
-               egg_secure_free (crypted);
+               cbytes = egg_bytes_new_with_free_func (crypted, n_crypted, egg_secure_free, crypted);
                crypted = NULL;
 
+               /* Try to parse the resulting key */
+               r = handle_pkcs12_bag (self, cbytes);
+               egg_bytes_unref (cbytes);
+
                if (r != GCR_ERROR_UNRECOGNIZED) {
                        ret = r;
                        break;
@@ -1195,6 +1230,8 @@ handle_pkcs12_encrypted_bag (GcrParser *self, const guchar *data, gsize n_data)
        }
 
 done:
+       if (params)
+               egg_bytes_unref (params);
        if (cih)
                gcry_cipher_close (cih);
        egg_asn1x_destroy (asn);
@@ -1203,14 +1240,14 @@ done:
 }
 
 static gint
-handle_pkcs12_safe (GcrParser *self, const guchar *data, gsize n_data)
+handle_pkcs12_safe (GcrParser *self,
+                    EggBytes *data)
 {
        GNode *asn = NULL;
        GNode *asn_content = NULL;
        gint ret, r;
-       const guchar *bag;
-       guchar *content = NULL;
-       gsize n_bag, n_content;
+       EggBytes *bag;
+       EggBytes *content;
        GQuark oid;
        guint i;
        GNode *node;
@@ -1219,7 +1256,7 @@ handle_pkcs12_safe (GcrParser *self, const guchar *data, gsize n_data)
 
        asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab,
                                                         "pkcs-12-AuthenticatedSafe",
-                                                        data, n_data);
+                                                        data);
        if (!asn)
                goto done;
 
@@ -1241,8 +1278,8 @@ handle_pkcs12_safe (GcrParser *self, const guchar *data, gsize n_data)
                if (!node)
                        goto done;
 
-               bag = egg_asn1x_get_raw_element (node, &n_bag);
-               g_return_val_if_fail (bag, ret);
+               bag = egg_asn1x_get_raw_element (node);
+               g_return_val_if_fail (bag != NULL, ret);
 
                /* A non encrypted bag, just parse */
                if (oid == GCR_OID_PKCS7_DATA) {
@@ -1250,20 +1287,20 @@ handle_pkcs12_safe (GcrParser *self, const guchar *data, gsize n_data)
                        egg_asn1x_destroy (asn_content);
                        asn_content = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab,
                                                                                 "pkcs-7-Data",
-                                                                                bag, n_bag);
+                                                                                bag);
                        if (!asn_content)
                                goto done;
 
-                       g_free (content);
-                       content = egg_asn1x_get_string_as_raw (asn_content, NULL, &n_content);
+                       content = egg_asn1x_get_string_as_bytes (asn_content);
                        if (!content)
                                goto done;
 
-                       r = handle_pkcs12_bag (self, content, n_content);
+                       r = handle_pkcs12_bag (self, content);
+                       egg_bytes_unref (content);
 
                /* Encrypted data first needs decryption */
                } else if (oid == GCR_OID_PKCS7_ENCRYPTED_DATA) {
-                       r = handle_pkcs12_encrypted_bag (self, bag, n_bag);
+                       r = handle_pkcs12_encrypted_bag (self, bag);
 
                /* Hmmmm, not sure what this is */
                } else {
@@ -1271,6 +1308,9 @@ handle_pkcs12_safe (GcrParser *self, const guchar *data, gsize n_data)
                        r = GCR_ERROR_UNRECOGNIZED;
                }
 
+               egg_bytes_unref (bag);
+               bag = NULL;
+
                if (r == GCR_ERROR_FAILURE ||
                    r == GCR_ERROR_CANCELLED ||
                    r == GCR_ERROR_LOCKED) {
@@ -1282,17 +1322,17 @@ handle_pkcs12_safe (GcrParser *self, const guchar *data, gsize n_data)
        ret = SUCCESS;
 
 done:
+       if (bag != NULL)
+               egg_bytes_unref (bag);
        egg_asn1x_destroy (asn);
        egg_asn1x_destroy (asn_content);
-       g_free (content);
        return ret;
 }
 
 static gint
 verify_pkcs12_safe (GcrParser *self,
                     GNode *asn,
-                    gconstpointer content,
-                    gsize n_content)
+                    EggBytes *content)
 {
        PasswordState pstate = PASSWORD_STATE_INIT;
        const gchar *password;
@@ -1303,8 +1343,7 @@ verify_pkcs12_safe (GcrParser *self,
        gsize n_digest;
        GQuark algorithm;
        GNode *mac_data;
-       gconstpointer params;
-       gsize n_params;
+       EggBytes *params = NULL;
        int ret, r;
 
        ret = GCR_ERROR_FAILURE;
@@ -1323,7 +1362,7 @@ verify_pkcs12_safe (GcrParser *self,
        if (!algorithm)
                goto done;
 
-       params = egg_asn1x_get_raw_element (mac_data, &n_params);
+       params = egg_asn1x_get_raw_element (mac_data);
        if (!params)
                goto done;
 
@@ -1342,8 +1381,7 @@ verify_pkcs12_safe (GcrParser *self,
                }
 
                /* Parse the encryption stuff into a cipher. */
-               if (!egg_symkey_read_mac (algorithm, password, -1, params, n_params,
-                                         &mdh, &mac_len)) {
+               if (!egg_symkey_read_mac (algorithm, password, -1, params, &mdh, &mac_len)) {
                        ret = GCR_ERROR_FAILURE;
                        goto done;
                }
@@ -1353,7 +1391,7 @@ verify_pkcs12_safe (GcrParser *self,
                        r = GCR_ERROR_FAILURE;
 
                } else {
-                       gcry_md_write (mdh, content, n_content);
+                       gcry_md_write (mdh, egg_bytes_get_data (content), egg_bytes_get_size (content));
                        mac_digest = gcry_md_read (mdh, 0);
                        g_return_val_if_fail (mac_digest, GCR_ERROR_FAILURE);
                        r = memcmp (mac_digest, digest, n_digest) == 0 ? SUCCESS : GCR_ERROR_LOCKED;
@@ -1369,6 +1407,8 @@ verify_pkcs12_safe (GcrParser *self,
        }
 
 done:
+       if (params)
+               egg_bytes_unref (params);
        if (mdh)
                gcry_md_close (mdh);
        g_free (digest);
@@ -1377,26 +1417,25 @@ done:
 }
 
 static gint
-parse_der_pkcs12 (GcrParser *self, const guchar *data, gsize n_data)
+parse_der_pkcs12 (GcrParser *self,
+                  EggBytes *data)
 {
        GNode *asn = NULL;
        GNode *asn_content = NULL;
        gint ret;
-       const guchar* element = NULL;
-       guchar *content = NULL;
-       gsize n_element, n_content;
+       EggBytes *element = NULL;
+       EggBytes *content = NULL;
        GQuark oid;
        GcrParsed *parsed;
 
        parsed = push_parsed (self, FALSE);
        ret = GCR_ERROR_UNRECOGNIZED;
 
-       asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab, "pkcs-12-PFX",
-                                                        data, n_data);
+       asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab, "pkcs-12-PFX", data);
        if (!asn)
                goto done;
 
-       parsing_block (parsed, GCR_FORMAT_DER_PKCS12, data, n_data);
+       parsing_block (parsed, GCR_FORMAT_DER_PKCS12, data);
 
        oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "authSafe", "contentType", NULL));
        if (!oid)
@@ -1408,25 +1447,27 @@ parse_der_pkcs12 (GcrParser *self, const guchar *data, gsize n_data)
                goto done;
        }
 
-       element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "authSafe", "content", NULL), &n_element);
+       element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "authSafe", "content", NULL));
        if (!element)
                goto done;
 
-       asn_content = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab, "pkcs-7-Data",
-                                                                element, n_element);
+       asn_content = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab, "pkcs-7-Data", element);
        if (!asn_content)
                goto done;
 
-       content = egg_asn1x_get_string_as_raw (asn_content, g_realloc, &n_content);
+       content = egg_asn1x_get_string_as_bytes (asn_content);
        if (!content)
                goto done;
 
-       ret = verify_pkcs12_safe (self, asn, content, n_content);
+       ret = verify_pkcs12_safe (self, asn, content);
        if (ret == SUCCESS)
-               ret = handle_pkcs12_safe (self, content, n_content);
+               ret = handle_pkcs12_safe (self, content);
 
 done:
-       g_free (content);
+       if (element)
+               egg_bytes_unref (element);
+       if (content)
+               egg_bytes_unref (content);
        egg_asn1x_destroy (asn_content);
        egg_asn1x_destroy (asn);
        pop_parsed (self, parsed);
@@ -1440,8 +1481,7 @@ done:
 
 static void
 on_openpgp_packet (GPtrArray *records,
-                   const guchar *outer,
-                   gsize n_outer,
+                   EggBytes *outer,
                    gpointer user_data)
 {
        GcrParser *self = GCR_PARSER (user_data);
@@ -1458,7 +1498,7 @@ on_openpgp_packet (GPtrArray *records,
        parsed = push_parsed (self, FALSE);
 
        /* All we can do is the packet bounds */
-       parsing_block (parsed, GCR_FORMAT_OPENPGP_PACKET, outer, n_outer);
+       parsing_block (parsed, GCR_FORMAT_OPENPGP_PACKET, outer);
        parsing_object (parsed, CKO_GCR_GNUPG_RECORDS);
        string = _gcr_records_format (records);
        parsed_attribute (parsed, CKA_VALUE, string, strlen (string));
@@ -1470,12 +1510,11 @@ on_openpgp_packet (GPtrArray *records,
 
 static gint
 parse_openpgp_packets (GcrParser *self,
-                       const guchar *data,
-                       gsize n_data)
+                       EggBytes *data)
 {
        gint num_parsed;
 
-       num_parsed = _gcr_openpgp_parse (data, n_data,
+       num_parsed = _gcr_openpgp_parse (data,
                                         GCR_OPENPGP_PARSE_KEYS |
                                         GCR_OPENPGP_PARSE_ATTRIBUTES |
                                         GCR_OPENPGP_PARSE_SIGNATURES,
@@ -1542,8 +1581,7 @@ static gint
 handle_plain_pem (GcrParser *self,
                   gint format_id,
                   gint want_format,
-                  const guchar *data,
-                  gsize n_data)
+                  EggBytes *data)
 {
        ParserFormat *format;
 
@@ -1554,7 +1592,7 @@ handle_plain_pem (GcrParser *self,
        if (format == NULL)
                return GCR_ERROR_UNRECOGNIZED;
 
-       return (format->function) (self, data, n_data);
+       return (format->function) (self, data);
 }
 
 static gint
@@ -1562,15 +1600,14 @@ handle_encrypted_pem (GcrParser *self,
                       gint format_id,
                       gint want_format,
                       GHashTable *headers,
-                      const guchar *data,
-                      gsize n_data)
+                      EggBytes *data)
 {
        PasswordState pstate = PASSWORD_STATE_INIT;
        const gchar *password;
        guchar *decrypted;
        gsize n_decrypted;
        const gchar *val;
-       gboolean ret;
+       EggBytes *dbytes;
        gint res;
        gint l;
 
@@ -1590,28 +1627,25 @@ handle_encrypted_pem (GcrParser *self,
                if (res != SUCCESS)
                        break;
 
-               decrypted = NULL;
-               n_decrypted = 0;
-
                /* Decrypt, this will result in garble if invalid password */
-               ret = egg_openssl_decrypt_block (val, password, -1, data, n_data,
-                                                &decrypted, &n_decrypted);
-               if (!ret) {
+               decrypted = egg_openssl_decrypt_block (val, password, -1, data, &n_decrypted);
+               if (!decrypted) {
                        res = GCR_ERROR_FAILURE;
                        break;
                }
 
-               g_assert (decrypted);
-
                /* Unpad the DER data */
                l = egg_asn1x_element_length (decrypted, n_decrypted);
                if (l > 0)
                        n_decrypted = l;
 
+               dbytes = egg_bytes_new_with_free_func (decrypted, n_decrypted,
+                                                      egg_secure_free, decrypted);
+               decrypted = NULL;
+
                /* Try to parse */
-               res = handle_plain_pem (self, format_id, want_format,
-                                       decrypted, n_decrypted);
-               egg_secure_free (decrypted);
+               res = handle_plain_pem (self, format_id, want_format, dbytes);
+               egg_bytes_unref (dbytes);
 
                /* Unrecognized is a bad password */
                if (res != GCR_ERROR_UNRECOGNIZED)
@@ -1629,10 +1663,8 @@ typedef struct {
 
 static void
 handle_pem_data (GQuark type,
-                 const guchar *data,
-                 gsize n_data,
-                 const gchar *outer,
-                 gsize n_outer,
+                 EggBytes *data,
+                 EggBytes *outer,
                  GHashTable *headers,
                  gpointer user_data)
 {
@@ -1654,7 +1686,7 @@ handle_pem_data (GQuark type,
        parsed = push_parsed (args->parser, FALSE);
 
        /* Fill in information necessary for prompting */
-       parsing_block (parsed, outer_format, outer, n_outer);
+       parsing_block (parsed, outer_format, outer);
 
        /* See if it's encrypted PEM all openssl like*/
        if (headers) {
@@ -1666,10 +1698,10 @@ handle_pem_data (GQuark type,
        if (encrypted)
                res = handle_encrypted_pem (args->parser, inner_format,
                                            args->want_format, headers,
-                                           data, n_data);
+                                           data);
        else
                res = handle_plain_pem (args->parser, inner_format,
-                                       args->want_format, data, n_data);
+                                       args->want_format, data);
 
        pop_parsed (args->parser, parsed);
 
@@ -1682,15 +1714,17 @@ handle_pem_data (GQuark type,
 }
 
 static gint
-handle_pem_format (GcrParser *self, gint subformat, const guchar *data, gsize n_data)
+handle_pem_format (GcrParser *self,
+                   gint subformat,
+                   EggBytes *data)
 {
        HandlePemArgs ctx = { self, GCR_ERROR_UNRECOGNIZED, subformat };
        guint found;
 
-       if (n_data == 0)
+       if (egg_bytes_get_size (data) == 0)
                return GCR_ERROR_UNRECOGNIZED;
 
-       found = egg_armor_parse (data, n_data, handle_pem_data, &ctx);
+       found = egg_armor_parse (data, handle_pem_data, &ctx);
 
        if (found == 0)
                return GCR_ERROR_UNRECOGNIZED;
@@ -1700,59 +1734,66 @@ handle_pem_format (GcrParser *self, gint subformat, const guchar *data, gsize n_
 
 
 static gint
-parse_pem (GcrParser *self, const guchar *data, gsize n_data)
+parse_pem (GcrParser *self,
+           EggBytes *data)
 {
-       return handle_pem_format (self, 0, data, n_data);
+       return handle_pem_format (self, 0, data);
 }
 
 static gint
-parse_pem_private_key_rsa (GcrParser *self, const guchar *data, gsize n_data)
+parse_pem_private_key_rsa (GcrParser *self,
+                           EggBytes *data)
 {
-       return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data, n_data);
+       return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data);
 }
 
 static gint
-parse_pem_private_key_dsa (GcrParser *self, const guchar *data, gsize n_data)
+parse_pem_private_key_dsa (GcrParser *self,
+                           EggBytes *data)
 {
-       return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data, n_data);
+       return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data);
 }
 
 static gint
-parse_pem_certificate (GcrParser *self, const guchar *data, gsize n_data)
+parse_pem_certificate (GcrParser *self,
+                       EggBytes *data)
 {
-       return handle_pem_format (self, GCR_FORMAT_DER_CERTIFICATE_X509, data, n_data);
+       return handle_pem_format (self, GCR_FORMAT_DER_CERTIFICATE_X509, data);
 }
 
 static gint
-parse_pem_pkcs8_plain (GcrParser *self, const guchar *data, gsize n_data)
+parse_pem_pkcs8_plain (GcrParser *self,
+                       EggBytes *data)
 {
-       return handle_pem_format (self, GCR_FORMAT_DER_PKCS8_PLAIN, data, n_data);
+       return handle_pem_format (self, GCR_FORMAT_DER_PKCS8_PLAIN, data);
 }
 
 static gint
-parse_pem_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
+parse_pem_pkcs8_encrypted (GcrParser *self,
+                           EggBytes *data)
 {
-       return handle_pem_format (self, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data, n_data);
+       return handle_pem_format (self, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data);
 }
 
 static gint
-parse_pem_pkcs7 (GcrParser *self, const guchar *data, gsize n_data)
+parse_pem_pkcs7 (GcrParser *self,
+                 EggBytes *data)
 {
-       return handle_pem_format (self, GCR_FORMAT_DER_PKCS7, data, n_data);
+       return handle_pem_format (self, GCR_FORMAT_DER_PKCS7, data);
 }
 
 static gint
-parse_pem_pkcs12 (GcrParser *self, const guchar *data, gsize n_data)
+parse_pem_pkcs12 (GcrParser *self,
+                  EggBytes *data)
 {
-       return handle_pem_format (self, GCR_FORMAT_DER_PKCS12, data, n_data);
+       return handle_pem_format (self, GCR_FORMAT_DER_PKCS12, data);
 }
 
 static gint
 parse_openpgp_armor (GcrParser *self,
-                     const guchar *data,
-                     gsize n_data)
+                     EggBytes *data)
 {
-       return handle_pem_format (self, GCR_FORMAT_OPENPGP_PACKET, data, n_data);
+       return handle_pem_format (self, GCR_FORMAT_OPENPGP_PACKET, data);
 }
 
 /* -----------------------------------------------------------------------------
@@ -1763,15 +1804,14 @@ static void
 on_openssh_public_key_parsed (GckAttributes *attrs,
                               const gchar *label,
                               const gchar *options,
-                              const gchar *outer,
-                              gsize n_outer,
+                              EggBytes *outer,
                               gpointer user_data)
 {
        GcrParser *self = GCR_PARSER (user_data);
        GcrParsed *parsed;
 
        parsed = push_parsed (self, FALSE);
-       parsing_block (parsed, GCR_FORMAT_OPENSSH_PUBLIC, outer, n_outer);
+       parsing_block (parsed, GCR_FORMAT_OPENSSH_PUBLIC, outer);
        parsed_attributes (parsed, attrs);
        parsed_label (parsed, label);
        parsed_fire (self, parsed);
@@ -1780,13 +1820,11 @@ on_openssh_public_key_parsed (GckAttributes *attrs,
 
 static gint
 parse_openssh_public (GcrParser *self,
-                      const guchar *data,
-                      gsize n_data)
+                      EggBytes *data)
 {
        guint num_parsed;
 
-       num_parsed = _gcr_openssh_pub_parse (data, n_data,
-                                            on_openssh_public_key_parsed, self);
+       num_parsed = _gcr_openssh_pub_parse (data, on_openssh_public_key_parsed, self);
 
        if (num_parsed == 0)
                return GCR_ERROR_UNRECOGNIZED;
@@ -1896,8 +1934,7 @@ compare_pointers (gconstpointer a, gconstpointer b)
 
 typedef struct _ForeachArgs {
        GcrParser *parser;
-       const guchar *data;
-       gsize n_data;
+       EggBytes *data;
        gint result;
 } ForeachArgs;
 
@@ -1912,7 +1949,7 @@ parser_format_foreach (gpointer key, gpointer value, gpointer data)
        g_assert (format->function);
        g_assert (GCR_IS_PARSER (args->parser));
 
-       result = (format->function) (args->parser, args->data, args->n_data);
+       result = (format->function) (args->parser, args->data);
        if (result != GCR_ERROR_UNRECOGNIZED) {
                args->result = result;
                return TRUE;
@@ -2147,7 +2184,7 @@ gcr_parser_parse_data (GcrParser *self,
                        gsize n_data,
                        GError **error)
 {
-       ForeachArgs args = { self, data, n_data, GCR_ERROR_UNRECOGNIZED };
+       ForeachArgs args = { self, NULL, GCR_ERROR_UNRECOGNIZED };
        const gchar *message = NULL;
        gint i;
 
@@ -2156,6 +2193,9 @@ gcr_parser_parse_data (GcrParser *self,
        g_return_val_if_fail (!error || !*error, FALSE);
 
        if (data && n_data) {
+               /* TODO: Once GBytes is in the API, copy here */
+               args.data = egg_bytes_new_static (data, n_data);
+
                /* Just the specific formats requested */
                if (self->pv->specific_formats) {
                        g_tree_foreach (self->pv->specific_formats, parser_format_foreach, &args);
@@ -2343,15 +2383,7 @@ gcr_parsed_ref (GcrParsed *parsed)
        /* Find the block of data to copy */
        while (parsed != NULL) {
                if (parsed->data != NULL) {
-                       if (parsed->sensitive) {
-                               copy->data = egg_secure_alloc (parsed->n_data);
-                               memcpy (copy->data, parsed->data, parsed->n_data);
-                               copy->destroy_func = egg_secure_free;
-                       } else {
-                               copy->data = g_memdup (parsed->data, parsed->n_data);
-                               copy->destroy_func = g_free;
-                       }
-                       copy->n_data = parsed->n_data;
+                       copy->data = egg_bytes_ref (parsed->data);
                        break;
                }
                parsed = parsed->next;
@@ -2377,8 +2409,8 @@ gcr_parsed_unref (gpointer parsed)
                if (par->attrs)
                        gck_attributes_unref (par->attrs);
                g_free (par->label);
-               if (par->destroy_func)
-                       (par->destroy_func) (par->data);
+               if (par->data)
+                       egg_bytes_unref (par->data);
                g_free (par);
        }
 }
@@ -2542,8 +2574,8 @@ gcr_parsed_get_data (GcrParsed *parsed,
 
        while (parsed != NULL) {
                if (parsed->data != NULL) {
-                       *n_data = parsed->n_data;
-                       return parsed->data;
+                       *n_data = egg_bytes_get_size (parsed->data);
+                       return egg_bytes_get_data (parsed->data);
                }
                parsed = parsed->next;
        }
index b83305a..46748f6 100644 (file)
@@ -31,8 +31,7 @@
 
 static void
 on_packet_print_records (GPtrArray *records,
-                         const guchar *packet,
-                         gsize n_packet,
+                         EggBytes *packet,
                          gpointer user_data)
 {
        gchar *string;
@@ -46,12 +45,11 @@ on_packet_print_records (GPtrArray *records,
 }
 
 static gboolean
-parse_binary (gconstpointer contents,
-              gsize length)
+parse_binary (EggBytes *contents)
 {
        guint packets;
 
-       packets = _gcr_openpgp_parse (contents, length,
+       packets = _gcr_openpgp_parse (contents,
                                      GCR_OPENPGP_PARSE_KEYS |
                                      GCR_OPENPGP_PARSE_ATTRIBUTES,
                                      on_packet_print_records, NULL);
@@ -61,10 +59,8 @@ parse_binary (gconstpointer contents,
 
 static void
 on_armor_parsed (GQuark type,
-                 const guchar *data,
-                 gsize n_data,
-                 const gchar *outer,
-                 gsize n_outer,
+                 EggBytes *data,
+                 EggBytes *outer,
                  GHashTable *headers,
                  gpointer user_data)
 {
@@ -74,19 +70,18 @@ on_armor_parsed (GQuark type,
        value = g_hash_table_lookup (headers, "Version");
        g_assert_cmpstr (value, ==, "GnuPG v1.4.11 (GNU/Linux)");
 
-       *result = parse_binary (data, n_data);
+       *result = parse_binary (data);
 }
 
 static gboolean
-parse_armor_or_binary (gconstpointer contents,
-                       gsize length)
+parse_armor_or_binary (EggBytes *contents)
 {
        gboolean result;
        guint parts;
 
-       parts = egg_armor_parse (contents, length, on_armor_parsed, &result);
+       parts = egg_armor_parse (contents, on_armor_parsed, &result);
        if (parts == 0)
-               result = parse_binary (contents, length);
+               result = parse_binary (contents);
        return result;
 }
 
@@ -96,6 +91,7 @@ main(int argc, char *argv[])
        GError *error = NULL;
        gchar *contents;
        gsize length;
+       EggBytes *bytes;
        int ret;
 
        g_set_prgname ("frob-openpgp");
@@ -111,12 +107,13 @@ main(int argc, char *argv[])
                return 1;
        }
 
+       bytes = egg_bytes_new_take (contents, length);
        ret = 0;
-       if (!parse_armor_or_binary (contents, length)) {
+       if (!parse_armor_or_binary (bytes)) {
                g_printerr ("frob-openpgp: no openpgp data found in data");
                ret = 1;
        }
 
-       g_free (contents);
+       egg_bytes_unref (bytes);
        return ret;
 }
index d17208b..94564f8 100644 (file)
 #include <errno.h>
 
 typedef struct {
-       gpointer cert_rsa;
-       gsize n_cert_rsa;
-       gpointer key_rsa;
-       gsize n_key_rsa;
-       gpointer cert_dsa;
-       gsize n_cert_dsa;
-       gpointer key_dsa;
-       gsize n_key_dsa;
+       EggBytes *cert_rsa;
+       EggBytes *key_rsa;
+       EggBytes *cert_dsa;
+       EggBytes *key_dsa;
 } Test;
 
 static void
 setup (Test *test, gconstpointer unused)
 {
        GError *error = NULL;
+       gchar *contents;
+       gsize length;
 
-       g_file_get_contents (SRCDIR "/files/client.crt", (gchar**)&test->cert_rsa,
-                            &test->n_cert_rsa, &error);
+       g_file_get_contents (SRCDIR "/files/client.crt", &contents, &length, &error);
        g_assert_no_error (error);
-       g_assert (test->cert_rsa);
+       test->cert_rsa = egg_bytes_new_take (contents, length);
 
-       g_file_get_contents (SRCDIR "/files/client.key", (gchar**)&test->key_rsa,
-                            &test->n_key_rsa, &error);
+       g_file_get_contents (SRCDIR "/files/client.key", &contents, &length, &error);
        g_assert_no_error (error);
-       g_assert (test->key_rsa);
+       test->key_rsa = egg_bytes_new_take (contents, length);
 
-       g_file_get_contents (SRCDIR "/files/generic-dsa.crt", (gchar**)&test->cert_dsa,
-                            &test->n_cert_dsa, &error);
+       g_file_get_contents (SRCDIR "/files/generic-dsa.crt", &contents, &length, &error);
        g_assert_no_error (error);
-       g_assert (test->cert_dsa);
+       test->cert_dsa = egg_bytes_new_take (contents, length);
 
-       g_file_get_contents (SRCDIR "/files/generic-dsa.key", (gchar**)&test->key_dsa,
-                            &test->n_key_dsa, &error);
+       g_file_get_contents (SRCDIR "/files/generic-dsa.key", &contents, &length, &error);
        g_assert_no_error (error);
-       g_assert (test->key_dsa);
+       test->key_dsa = egg_bytes_new_take (contents, length);
 }
 
 static void
 teardown (Test *test, gconstpointer unused)
 {
-       g_free (test->cert_rsa);
-       g_free (test->key_rsa);
-       g_free (test->cert_dsa);
-       g_free (test->key_dsa);
+       egg_bytes_unref (test->cert_rsa);
+       egg_bytes_unref (test->key_rsa);
+       egg_bytes_unref (test->cert_dsa);
+       egg_bytes_unref (test->key_dsa);
 }
 
 static void
@@ -96,7 +90,7 @@ on_parser_parsed (GcrParser *parser,
 }
 
 static GckAttributes*
-parse_attributes_for_key (gpointer data, gsize n_data)
+parse_attributes_for_key (EggBytes *data)
 {
        GcrParser *parser;
        GckAttributes *attrs = NULL;
@@ -104,7 +98,8 @@ parse_attributes_for_key (gpointer data, gsize n_data)
 
        parser = gcr_parser_new ();
        g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), &attrs);
-       gcr_parser_parse_data (parser, data, n_data, &error);
+       gcr_parser_parse_data (parser, egg_bytes_get_data (data),
+                              egg_bytes_get_size (data), &error);
        g_assert_no_error (error);
        g_object_unref (parser);
 
@@ -113,30 +108,30 @@ parse_attributes_for_key (gpointer data, gsize n_data)
 }
 
 static GckAttributes *
-build_attributes_for_cert (guchar *data,
-                           gsize n_data)
+build_attributes_for_cert (EggBytes *data)
 {
        GckAttributes *attrs;
 
        attrs = gck_attributes_new ();
-       gck_attributes_add_data (attrs, CKA_VALUE, data, n_data);
+       gck_attributes_add_data (attrs, CKA_VALUE, egg_bytes_get_data (data),
+                                egg_bytes_get_size (data));
        gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_CERTIFICATE);
        gck_attributes_add_ulong (attrs, CKA_CERTIFICATE_TYPE, CKC_X_509);
 
        return attrs;
 }
 
-static gconstpointer
-parse_subject_public_key_info_for_cert (gpointer data, gsize n_data, gsize *n_info)
+static EggBytes *
+parse_subject_public_key_info_for_cert (EggBytes *data)
 {
-       gconstpointer info;
+       EggBytes *info;
        GNode *asn;
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data);
-       g_assert (asn);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data);
+       g_assert (asn != NULL);
 
-       info = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", NULL), n_info);
-       g_assert (info);
+       info = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", NULL));
+       g_assert (info != NULL);
 
        egg_asn1x_destroy (asn);
        return info;
@@ -146,16 +141,17 @@ static void
 test_rsa (Test *test, gconstpointer unused)
 {
        GckAttributes *key, *cert;
-       gconstpointer info;
-       gsize n_info;
+       EggBytes *info;
        guchar *fingerprint1, *fingerprint2, *fingerprint3;
        gsize n_fingerprint1, n_fingerprint2, n_fingerprint3;
 
-       key = parse_attributes_for_key (test->key_rsa, test->n_key_rsa);
-       info = parse_subject_public_key_info_for_cert (test->cert_rsa, test->n_cert_rsa, &n_info);
-       cert = build_attributes_for_cert (test->cert_rsa, test->n_cert_rsa);
+       key = parse_attributes_for_key (test->key_rsa);
+       info = parse_subject_public_key_info_for_cert (test->cert_rsa);
+       cert = build_attributes_for_cert (test->cert_rsa);
 
-       fingerprint1 = gcr_fingerprint_from_subject_public_key_info (info, n_info, G_CHECKSUM_SHA1, &n_fingerprint1);
+       fingerprint1 = gcr_fingerprint_from_subject_public_key_info (egg_bytes_get_data (info),
+                                                                    egg_bytes_get_size (info),
+                                                                    G_CHECKSUM_SHA1, &n_fingerprint1);
        fingerprint2 = gcr_fingerprint_from_attributes (key, G_CHECKSUM_SHA1, &n_fingerprint2);
        fingerprint3 = gcr_fingerprint_from_attributes (cert, G_CHECKSUM_SHA1, &n_fingerprint3);
 
@@ -166,6 +162,7 @@ test_rsa (Test *test, gconstpointer unused)
        g_free (fingerprint2);
        g_free (fingerprint3);
 
+       egg_bytes_unref (info);
        gck_attributes_unref (key);
        gck_attributes_unref (cert);
 }
@@ -174,16 +171,17 @@ static void
 test_dsa (Test *test, gconstpointer unused)
 {
        GckAttributes *key, *cert;
-       gconstpointer info;
-       gsize n_info;
+       EggBytes *info;
        guchar *fingerprint1, *fingerprint2, *fingerprint3;
        gsize n_fingerprint1, n_fingerprint2, n_fingerprint3;
 
-       key = parse_attributes_for_key (test->key_dsa, test->n_key_dsa);
-       info = parse_subject_public_key_info_for_cert (test->cert_dsa, test->n_cert_dsa, &n_info);
-       cert = build_attributes_for_cert (test->cert_dsa, test->n_cert_dsa);
+       key = parse_attributes_for_key (test->key_dsa);
+       info = parse_subject_public_key_info_for_cert (test->cert_dsa);
+       cert = build_attributes_for_cert (test->cert_dsa);
 
-       fingerprint1 = gcr_fingerprint_from_subject_public_key_info (info, n_info, G_CHECKSUM_SHA1, &n_fingerprint1);
+       fingerprint1 = gcr_fingerprint_from_subject_public_key_info (egg_bytes_get_data (info),
+                                                                    egg_bytes_get_size (info),
+                                                                    G_CHECKSUM_SHA1, &n_fingerprint1);
        fingerprint2 = gcr_fingerprint_from_attributes (key, G_CHECKSUM_SHA1, &n_fingerprint2);
        fingerprint3 = gcr_fingerprint_from_attributes (cert, G_CHECKSUM_SHA1, &n_fingerprint3);
 
@@ -194,6 +192,7 @@ test_dsa (Test *test, gconstpointer unused)
        g_free (fingerprint2);
        g_free (fingerprint3);
 
+       egg_bytes_unref (info);
        gck_attributes_unref (key);
        gck_attributes_unref (cert);
 }
index be41f40..cfc1dad 100644 (file)
@@ -240,15 +240,14 @@ compare_fixture_with_records (const gchar *fixture,
 
 static void
 on_openpgp_packet  (GPtrArray *records,
-                    const guchar *outer,
-                    gsize n_outer,
+                    EggBytes *outer,
                     gpointer user_data)
 {
        Test *test = user_data;
        guint seen;
 
        /* Should be parseable again */
-       seen = _gcr_openpgp_parse (outer, n_outer, test->fixture->flags |
+       seen = _gcr_openpgp_parse (outer, test->fixture->flags |
                                   GCR_OPENPGP_PARSE_NO_RECORDS, NULL, NULL);
        g_assert_cmpuint (seen, ==, 1);
 
@@ -263,10 +262,8 @@ on_openpgp_packet  (GPtrArray *records,
 
 static void
 on_armor_parsed (GQuark type,
-                 const guchar *data,
-                 gsize n_data,
-                 const gchar *outer,
-                 gsize n_outer,
+                 EggBytes *data,
+                 EggBytes *outer,
                  GHashTable *headers,
                  gpointer user_data)
 {
@@ -279,7 +276,7 @@ on_armor_parsed (GQuark type,
                g_assert_cmpstr (value, ==, test->fixture->version);
        }
 
-       seen = _gcr_openpgp_parse (data, n_data, test->fixture->flags,
+       seen = _gcr_openpgp_parse (data, test->fixture->flags,
                                   on_openpgp_packet, test);
        g_assert_cmpuint (seen, >, 0);
 
@@ -294,6 +291,7 @@ test_openpgp_armor (Test *test,
                     gconstpointer data)
 {
        GError *error = NULL;
+       EggBytes *bytes;
        gchar *armor;
        gsize length;
        guint parts;
@@ -301,10 +299,11 @@ test_openpgp_armor (Test *test,
        g_file_get_contents (test->fixture->filename, &armor, &length, &error);
        g_assert_no_error (error);
 
-       parts = egg_armor_parse (armor, length, on_armor_parsed, test);
+       bytes = egg_bytes_new_take (armor, length);
+       parts = egg_armor_parse (bytes, on_armor_parsed, test);
        g_assert_cmpuint (parts, ==, 1);
 
-       g_free (armor);
+       egg_bytes_unref (bytes);
 }
 
 static void
@@ -312,6 +311,7 @@ test_openpgp_binary (Test *test,
                      gconstpointer data)
 {
        GError *error = NULL;
+       EggBytes *bytes;
        gchar *binary;
        gsize length;
        guint seen;
@@ -319,8 +319,8 @@ test_openpgp_binary (Test *test,
        g_file_get_contents (test->fixture->filename, &binary, &length, &error);
        g_assert_no_error (error);
 
-       seen = _gcr_openpgp_parse (binary, length, test->fixture->flags,
-                                  on_openpgp_packet, test);
+       bytes = egg_bytes_new_take (binary, length);
+       seen = _gcr_openpgp_parse (bytes, test->fixture->flags, on_openpgp_packet, test);
        g_assert_cmpuint (seen, >, 0);
 
        if (*(test->at) != NULL) {
@@ -328,7 +328,7 @@ test_openpgp_binary (Test *test,
                g_assert_not_reached ();
        }
 
-       g_free (binary);
+       egg_bytes_unref (binary);
 }
 
 int
index 81634da..b7742d9 100644 (file)
@@ -91,8 +91,7 @@ static void
 on_openssh_pub_parse (GckAttributes *attrs,
                       const gchar *label,
                       const gchar *options,
-                      const gchar *outer,
-                      gsize n_outer,
+                      EggBytes *outer,
                       gpointer user_data)
 {
        Test *test = user_data;
@@ -104,7 +103,7 @@ on_openssh_pub_parse (GckAttributes *attrs,
                g_assert_cmpstr (options, ==, test->expected_options);
 
        /* The block should parse properly */
-       keys = _gcr_openssh_pub_parse (outer, n_outer, NULL, NULL);
+       keys = _gcr_openssh_pub_parse (outer, NULL, NULL);
        g_assert_cmpuint (keys, ==, 1);
 }
 
@@ -113,14 +112,16 @@ test_parse_v1_rsa (Test *test,
                    gconstpointer unused)
 {
        const gchar *data = OPENSSH_PUBLIC_RSA1 EXTRA_LINES_WITHOUT_KEY;
+       EggBytes *bytes;
        gint keys;
 
        test->expected_label = "rsa-key@example.com";
 
-       keys = _gcr_openssh_pub_parse (data, strlen (data),
-                                      on_openssh_pub_parse, test);
+       bytes = egg_bytes_new_static (data, strlen (data));
+       keys = _gcr_openssh_pub_parse (bytes, on_openssh_pub_parse, test);
        g_assert_cmpint (keys, ==, 1);
 
+       egg_bytes_unref (bytes);
 }
 
 static void
@@ -128,13 +129,16 @@ test_parse_v2_rsa (Test *test,
                    gconstpointer unused)
 {
        const gchar *data = OPENSSH_PUBLIC_RSA2 EXTRA_LINES_WITHOUT_KEY;
+       EggBytes *bytes;
        gint keys;
 
        test->expected_label = "rsa-key@example.com";
 
-       keys = _gcr_openssh_pub_parse (data, strlen (data),
-                                      on_openssh_pub_parse, test);
+       bytes = egg_bytes_new_static (data, strlen (data));
+       keys = _gcr_openssh_pub_parse (bytes, on_openssh_pub_parse, test);
        g_assert_cmpint (keys, ==, 1);
+
+       egg_bytes_unref (bytes);
 }
 
 static void
@@ -142,13 +146,16 @@ test_parse_v2_dsa (Test *test,
                gconstpointer unused)
 {
        const gchar *data = OPENSSH_PUBLIC_DSA2 EXTRA_LINES_WITHOUT_KEY;
+       EggBytes *bytes;
        gint keys;
 
        test->expected_label = "dsa-key@example.com";
 
-       keys = _gcr_openssh_pub_parse (data, strlen (data),
-                                      on_openssh_pub_parse, test);
+       bytes = egg_bytes_new_static (data, strlen (data));
+       keys = _gcr_openssh_pub_parse (bytes, on_openssh_pub_parse, test);
        g_assert_cmpint (keys, ==, 1);
+
+       egg_bytes_unref (bytes);
 }
 
 static void
@@ -156,13 +163,16 @@ test_parse_v1_options (Test *test,
                        gconstpointer unused)
 {
        const gchar *data = "option1,option2=\"value 2\",option3 " OPENSSH_PUBLIC_RSA1;
+       EggBytes *bytes;
        gint keys;
 
        test->expected_options = "option1,option2=\"value 2\",option3";
 
-       keys = _gcr_openssh_pub_parse (data, strlen (data),
-                                      on_openssh_pub_parse, test);
+       bytes = egg_bytes_new_static (data, strlen (data));
+       keys = _gcr_openssh_pub_parse (bytes, on_openssh_pub_parse, test);
        g_assert_cmpint (keys, ==, 1);
+
+       egg_bytes_unref (bytes);
 }
 
 static void
@@ -170,13 +180,16 @@ test_parse_v2_options (Test *test,
                        gconstpointer unused)
 {
        const gchar *data = "option1,option2=\"value 2\",option3 " OPENSSH_PUBLIC_RSA2;
+       EggBytes *bytes;
        gint keys;
 
        test->expected_options = "option1,option2=\"value 2\",option3";
 
-       keys = _gcr_openssh_pub_parse (data, strlen (data),
-                                      on_openssh_pub_parse, test);
+       bytes = egg_bytes_new_static (data, strlen (data));
+       keys = _gcr_openssh_pub_parse (bytes, on_openssh_pub_parse, test);
        g_assert_cmpint (keys, ==, 1);
+
+       egg_bytes_unref (bytes);
 }
 
 int
index 7c04c07..daf97e1 100644 (file)
@@ -53,8 +53,8 @@ setup (Test *test, gconstpointer unused)
        GckAttributes *attrs;
        CK_FUNCTION_LIST_PTR f;
        GckModule *module;
-       gconstpointer subject;
-       gsize n_subject;
+       EggBytes *subject;
+       EggBytes *bytes;
        GNode *asn, *node;
        CK_RV rv;
 
@@ -82,20 +82,24 @@ setup (Test *test, gconstpointer unused)
        gcr_pkcs11_set_modules (modules);
        gck_list_unref_free (modules);
 
-       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate",
-                                          test->cert_data, test->n_cert_data);
+       bytes = egg_bytes_new_static (test->cert_data, test->n_cert_data);
+       asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", bytes);
        g_assert (asn);
        node = egg_asn1x_node (asn, "tbsCertificate", "subject", NULL);
-       subject = egg_asn1x_get_raw_element (node, &n_subject);
+       subject = egg_asn1x_get_raw_element (node);
 
        /* Add a certificate to the module */
        attrs = gck_attributes_new ();
        gck_attributes_add_data (attrs, CKA_VALUE, test->cert_data, test->n_cert_data);
        gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_CERTIFICATE);
        gck_attributes_add_ulong (attrs, CKA_CERTIFICATE_TYPE, CKC_X_509);
-       gck_attributes_add_data (attrs, CKA_SUBJECT, subject, n_subject);
+       gck_attributes_add_data (attrs, CKA_SUBJECT,
+                                egg_bytes_get_data (subject),
+                                egg_bytes_get_size (subject));
        gck_mock_module_take_object (attrs);
 
+       egg_bytes_unref (bytes);
+       egg_bytes_unref (subject);
        egg_asn1x_destroy (asn);
 }