*/
/**
- * GcrDataFormat:
- * @GCR_FORMAT_INVALID: Not a valid format
- * @GCR_FORMAT_DER_PRIVATE_KEY: DER encoded private key
- * @GCR_FORMAT_DER_PRIVATE_KEY_RSA: DER encoded RSA private key
- * @GCR_FORMAT_DER_PRIVATE_KEY_DSA: DER encoded DSA private key
- * @GCR_FORMAT_DER_CERTIFICATE_X509: DER encoded X.509 certificate
- * @GCR_FORMAT_DER_PKCS7: DER encoded PKCS\#7 container file which can contain certificates
- * @GCR_FORMAT_DER_PKCS8: DER encoded PKCS\#8 file which can contain a key
- * @GCR_FORMAT_DER_PKCS8_PLAIN: Unencrypted DER encoded PKCS\#8 file which can contain a key
- * @GCR_FORMAT_DER_PKCS8_ENCRYPTED: Encrypted DER encoded PKCS\#8 file which can contain a key
- * @GCR_FORMAT_DER_PKCS12: DER encoded PKCS\#12 file which can contain certificates and/or keys
- * @GCR_FORMAT_OPENSSH_PUBLIC: OpenSSH v1 or v2 public key
- * @GCR_FORMAT_OPENPGP_PACKET: OpenPGP key packet(s)
- * @GCR_FORMAT_OPENPGP_ARMOR: OpenPGP public or private key armor encoded data
- * @GCR_FORMAT_PEM: An OpenSSL style PEM file with unspecified contents
- * @GCR_FORMAT_PEM_PRIVATE_KEY_RSA: An OpenSSL style PEM file with a private RSA key
- * @GCR_FORMAT_PEM_PRIVATE_KEY_DSA: An OpenSSL style PEM file with a private DSA key
- * @GCR_FORMAT_PEM_CERTIFICATE_X509: An OpenSSL style PEM file with an X.509 certificate
- * @GCR_FORMAT_PEM_PKCS7: An OpenSSL style PEM file containing PKCS\#7
- * @GCR_FORMAT_PEM_PKCS8_PLAIN: Unencrypted OpenSSL style PEM file containing PKCS\#8
- * @GCR_FORMAT_PEM_PKCS8_ENCRYPTED: Encrypted OpenSSL style PEM file containing PKCS\#8
- * @GCR_FORMAT_PEM_PKCS12: An OpenSSL style PEM file containing PKCS\#12
- *
- * The various format identifiers.
- */
-
-/**
* GCR_DATA_ERROR:
*
* A domain for data errors with codes from #GcrDataError
static guint signals[LAST_SIGNAL] = { 0 };
+typedef struct _GcrParsed {
+ GckAttributes *attrs;
+ const gchar *description;
+ gchar *label;
+ gconstpointer block;
+ gsize n_block;
+ GcrDataFormat format;
+ struct _GcrParsed *next;
+} GcrParsed;
+
struct _GcrParserPrivate {
GTree *specific_formats;
gboolean normal_formats;
GPtrArray *passwords;
-
- GckAttributes *parsed_attrs;
- const gchar *parsed_desc;
- gchar *parsed_label;
- gconstpointer parsing_block;
- gsize parsing_n_block;
+ GcrParsed *parsed;
};
G_DEFINE_TYPE (GcrParser, gcr_parser, G_TYPE_OBJECT);
* INTERNAL
*/
+static void
+parsed_attribute (GcrParsed *parsed,
+ CK_ATTRIBUTE_TYPE type,
+ gconstpointer data,
+ gsize n_data)
+{
+ g_assert (parsed);
+ g_assert (parsed->attrs);
+ gck_attributes_add_data (parsed->attrs, type, data, n_data);
+}
+
static gboolean
-parsed_asn1_attribute (GcrParser *self, GNode *asn, const guchar *data, gsize n_data,
- const gchar *part, CK_ATTRIBUTE_TYPE type)
+parsed_asn1_attribute (GcrParsed *parsed,
+ GNode *asn,
+ const guchar *data,
+ gsize n_data,
+ const gchar *part,
+ CK_ATTRIBUTE_TYPE type)
{
const guchar *value;
gsize n_value;
- g_assert (GCR_IS_PARSER (self));
g_assert (asn);
g_assert (data);
- g_assert (self->pv->parsed_attrs);
+ g_assert (parsed);
value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, part, NULL), &n_value);
if (value == NULL)
return FALSE;
/* TODO: Convert to USG FROM STD */
- gck_attributes_add_data (self->pv->parsed_attrs, type, value, n_value);
+ parsed_attribute (parsed, type, value, n_value);
return TRUE;
}
static void
-parsing_begin (GcrParser *self,
+parsed_ulong_attribute (GcrParsed *parsed,
+ CK_ATTRIBUTE_TYPE type,
+ gulong value)
+{
+ g_assert (parsed);
+ g_assert (parsed->attrs);
+ gck_attributes_add_ulong (parsed->attrs, type, value);
+}
+
+static void
+parsed_boolean_attribute (GcrParsed *parsed,
+ CK_ATTRIBUTE_TYPE type,
+ gboolean value)
+{
+ g_assert (parsed);
+ g_assert (parsed->attrs);
+ gck_attributes_add_boolean (parsed->attrs, type, value);
+}
+
+
+static void
+parsing_block (GcrParsed *parsed,
+ gint format,
gconstpointer block,
gsize n_block)
{
- g_assert (GCR_IS_PARSER (self));
+ g_assert (parsed);
g_assert (block);
g_assert (n_block);
+ g_assert (format);
+ g_assert (!parsed->block);
- if (self->pv->parsed_attrs)
- gck_attributes_unref (self->pv->parsed_attrs);
- self->pv->parsed_attrs = NULL;
-
- self->pv->parsing_block = block;
- self->pv->parsing_n_block = n_block;
+ parsed->format = format;
+ parsed->block = block;
+ parsed->n_block = n_block;
}
static void
-parsed_description (GcrParser *self,
+parsed_description (GcrParsed *parsed,
CK_OBJECT_CLASS klass)
{
+ g_assert (parsed);
switch (klass) {
case CKO_PRIVATE_KEY:
- self->pv->parsed_desc = _("Private Key");
+ parsed->description = _("Private Key");
break;
case CKO_CERTIFICATE:
- self->pv->parsed_desc = _("Certificate");
+ parsed->description = _("Certificate");
break;
case CKO_PUBLIC_KEY:
- self->pv->parsed_desc = _("Public Key");
+ parsed->description = _("Public Key");
break;
default:
- self->pv->parsed_desc = NULL;
+ parsed->description = NULL;
break;
}
}
static void
-parsing_object (GcrParser *self,
+parsing_object (GcrParsed *parsed,
CK_OBJECT_CLASS klass)
{
- g_return_if_fail (self->pv->parsed_attrs == NULL);
+ g_assert (parsed);
+ g_assert (!parsed->attrs);
if (klass == CKO_PRIVATE_KEY)
- self->pv->parsed_attrs = gck_attributes_new_full ((GckAllocator)egg_secure_realloc);
+ parsed->attrs = gck_attributes_new_full ((GckAllocator)egg_secure_realloc);
else
- self->pv->parsed_attrs = gck_attributes_new ();
- gck_attributes_add_ulong (self->pv->parsed_attrs, CKA_CLASS, klass);
- parsed_description (self, klass);
+ parsed->attrs = gck_attributes_new ();
+ gck_attributes_add_ulong (parsed->attrs, CKA_CLASS, klass);
+ parsed_description (parsed, klass);
}
static void
-parsed_attributes (GcrParser *self,
+parsed_attributes (GcrParsed *parsed,
GckAttributes *attrs)
{
gulong klass;
- g_return_if_fail (self->pv->parsed_attrs == NULL);
- g_return_if_fail (attrs != NULL);
+ g_assert (parsed);
+ g_assert (attrs);
+ g_assert (!parsed->attrs);
- self->pv->parsed_attrs = gck_attributes_ref (attrs);
+ parsed->attrs = gck_attributes_ref (attrs);
if (gck_attributes_find_ulong (attrs, CKA_CLASS, &klass))
- parsed_description (self, klass);
+ parsed_description (parsed, klass);
}
static void
-parsed_label (GcrParser *self, const gchar *label)
+parsed_label (GcrParsed *parsed,
+ const gchar *label)
{
- g_free (self->pv->parsed_label);
- self->pv->parsed_label = g_strdup (label);
+ g_assert (parsed);
+ g_assert (!parsed->label);
+ parsed->label = g_strdup (label);
}
-static void
-parsed_attribute (GcrParser *self, CK_ATTRIBUTE_TYPE type, gconstpointer data, gsize n_data)
+static GcrParsed *
+push_parsed (GcrParser *self)
{
- g_assert (GCR_IS_PARSER (self));
- g_assert (self->pv->parsed_attrs);
- gck_attributes_add_data (self->pv->parsed_attrs, type, data, n_data);
+ GcrParsed *parsed = g_new0 (GcrParsed, 1);
+ parsed->next = self->pv->parsed;
+ self->pv->parsed = parsed;
+ return parsed;
}
static void
-parsing_end (GcrParser *self)
+pop_parsed (GcrParser *self,
+ GcrParsed *parsed)
{
- g_assert (GCR_IS_PARSER (self));
- self->pv->parsing_block = NULL;
- self->pv->parsing_n_block = 0;
- if (self->pv->parsed_attrs)
- gck_attributes_unref (self->pv->parsed_attrs);
- self->pv->parsed_attrs = NULL;
- g_free (self->pv->parsed_label);
- self->pv->parsed_label = NULL;
- self->pv->parsed_desc = NULL;
-}
+ g_assert (parsed == self->pv->parsed);
-static void
-parsed_ulong (GcrParser *self, CK_ATTRIBUTE_TYPE type, gulong value)
-{
- g_assert (GCR_IS_PARSER (self));
- g_assert (self->pv->parsed_attrs);
- gck_attributes_add_ulong (self->pv->parsed_attrs, type, value);
-}
+ self->pv->parsed = parsed->next;
-static void
-parsed_boolean (GcrParser *self, CK_ATTRIBUTE_TYPE type, gboolean value)
-{
- g_assert (GCR_IS_PARSER (self));
- g_assert (self->pv->parsed_attrs);
- gck_attributes_add_boolean (self->pv->parsed_attrs, type, value);
+ gck_attributes_unref (parsed->attrs);
+ g_free (parsed->label);
+ g_free (parsed);
}
static gint
}
static void
-parsed_fire (GcrParser *self)
+parsed_fire (GcrParser *self,
+ GcrParsed *parsed)
{
+ g_assert (GCR_IS_PARSER (self));
+ g_assert (parsed);
+ g_assert (parsed == self->pv->parsed);
+
g_object_notify (G_OBJECT (self), "parsed-description");
g_object_notify (G_OBJECT (self), "parsed-attributes");
g_object_notify (G_OBJECT (self), "parsed-label");
gint res = GCR_ERROR_UNRECOGNIZED;
GNode *asn = NULL;
gulong version;
+ GcrParsed *parsed;
+
+ parsed = push_parsed (self);
asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data, n_data);
if (!asn)
goto done;
- parsing_begin (self, data, n_data);
- parsing_object (self, CKO_PRIVATE_KEY);
- parsed_ulong (self, CKA_KEY_TYPE, CKK_RSA);
- parsed_boolean (self, CKA_PRIVATE, CK_TRUE);
+ parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data, n_data);
+ parsing_object (parsed, CKO_PRIVATE_KEY);
+ parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_RSA);
+ parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
res = GCR_ERROR_FAILURE;
if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version))
goto done;
}
- if (!parsed_asn1_attribute (self, asn, data, n_data, "modulus", CKA_MODULUS) ||
- !parsed_asn1_attribute (self, asn, data, n_data, "publicExponent", CKA_PUBLIC_EXPONENT) ||
- !parsed_asn1_attribute (self, asn, data, n_data, "privateExponent", CKA_PRIVATE_EXPONENT) ||
- !parsed_asn1_attribute (self, asn, data, n_data, "prime1", CKA_PRIME_1) ||
- !parsed_asn1_attribute (self, asn, data, n_data, "prime2", CKA_PRIME_2) ||
- !parsed_asn1_attribute (self, asn, data, n_data, "coefficient", CKA_COEFFICIENT))
+ if (!parsed_asn1_attribute (parsed, asn, data, n_data, "modulus", CKA_MODULUS) ||
+ !parsed_asn1_attribute (parsed, asn, data, n_data, "publicExponent", CKA_PUBLIC_EXPONENT) ||
+ !parsed_asn1_attribute (parsed, asn, data, n_data, "privateExponent", CKA_PRIVATE_EXPONENT) ||
+ !parsed_asn1_attribute (parsed, asn, data, n_data, "prime1", CKA_PRIME_1) ||
+ !parsed_asn1_attribute (parsed, asn, data, n_data, "prime2", CKA_PRIME_2) ||
+ !parsed_asn1_attribute (parsed, asn, data, n_data, "coefficient", CKA_COEFFICIENT))
goto done;
- parsed_fire (self);
+ parsed_fire (self, parsed);
res = SUCCESS;
- parsing_end (self);
done:
egg_asn1x_destroy (asn);
if (res == GCR_ERROR_FAILURE)
g_message ("invalid RSA key");
+ pop_parsed (self, parsed);
return res;
}
{
gint ret = GCR_ERROR_UNRECOGNIZED;
GNode *asn = NULL;
+ GcrParsed *parsed;
+
+ parsed = push_parsed (self);
asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data, n_data);
if (!asn)
goto done;
- parsing_begin (self, data, n_data);
- parsing_object (self, CKO_PRIVATE_KEY);
- parsed_ulong (self, CKA_KEY_TYPE, CKK_DSA);
- parsed_boolean (self, CKA_PRIVATE, CK_TRUE);
+ parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data, n_data);
+ parsing_object (parsed, CKO_PRIVATE_KEY);
+ parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
+ parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
ret = GCR_ERROR_FAILURE;
- if (!parsed_asn1_attribute (self, asn, data, n_data, "p", CKA_PRIME) ||
- !parsed_asn1_attribute (self, asn, data, n_data, "q", CKA_SUBPRIME) ||
- !parsed_asn1_attribute (self, asn, data, n_data, "g", CKA_BASE) ||
- !parsed_asn1_attribute (self, asn, data, n_data, "priv", CKA_VALUE))
+ if (!parsed_asn1_attribute (parsed, asn, data, n_data, "p", CKA_PRIME) ||
+ !parsed_asn1_attribute (parsed, asn, data, n_data, "q", CKA_SUBPRIME) ||
+ !parsed_asn1_attribute (parsed, asn, data, n_data, "g", CKA_BASE) ||
+ !parsed_asn1_attribute (parsed, asn, data, n_data, "priv", CKA_VALUE))
goto done;
- parsed_fire (self);
+ parsed_fire (self, parsed);
ret = SUCCESS;
- parsing_end (self);
done:
egg_asn1x_destroy (asn);
if (ret == GCR_ERROR_FAILURE)
g_message ("invalid DSA key");
+ pop_parsed (self, parsed);
return ret;
}
gint ret = GCR_ERROR_UNRECOGNIZED;
GNode *asn_params = NULL;
GNode *asn_key = NULL;
+ GcrParsed *parsed;
+
+ parsed = push_parsed (self);
asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params, n_params);
asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata, n_keydata);
if (!asn_params || !asn_key)
goto done;
- parsed_ulong (self, CKA_KEY_TYPE, CKK_DSA);
- parsed_boolean (self, CKA_PRIVATE, CK_TRUE);
+ parsing_object (parsed, CKO_PRIVATE_KEY);
+ parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
+ parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
ret = GCR_ERROR_FAILURE;
- if (!parsed_asn1_attribute (self, asn_params, params, n_params, "p", CKA_PRIME) ||
- !parsed_asn1_attribute (self, asn_params, params, n_params, "q", CKA_SUBPRIME) ||
- !parsed_asn1_attribute (self, asn_params, params, n_params, "g", CKA_BASE) ||
- !parsed_asn1_attribute (self, asn_key, keydata, n_keydata, NULL, CKA_VALUE))
+ if (!parsed_asn1_attribute (parsed, asn_params, params, n_params, "p", CKA_PRIME) ||
+ !parsed_asn1_attribute (parsed, asn_params, params, n_params, "q", CKA_SUBPRIME) ||
+ !parsed_asn1_attribute (parsed, asn_params, params, n_params, "g", CKA_BASE) ||
+ !parsed_asn1_attribute (parsed, asn_key, keydata, n_keydata, NULL, CKA_VALUE))
goto done;
- parsed_fire (self);
+ parsed_fire (self, parsed);
ret = SUCCESS;
done:
if (ret == GCR_ERROR_FAILURE)
g_message ("invalid DSA key");
+ pop_parsed (self, parsed);
return ret;
}
const guchar *params;
gsize n_params;
GNode *asn = NULL;
+ GcrParsed *parsed;
+ parsed = push_parsed (self);
ret = GCR_ERROR_UNRECOGNIZED;
asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data, n_data);
if (!asn)
goto done;
+ parsing_block (parsed, GCR_FORMAT_DER_PKCS8_PLAIN, data, n_data);
ret = GCR_ERROR_FAILURE;
key_type = GCK_INVALID;
/* Try the normal sane format */
ret = parse_der_private_key_dsa (self, keydata, n_keydata);
- parsing_begin (self, data, n_data);
- parsing_object (self, CKO_PRIVATE_KEY);
-
/* 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);
-
- parsing_end (self);
break;
default:
g_message ("invalid or unsupported key type in PKCS#8 key");
}
egg_asn1x_destroy (asn);
+ pop_parsed (self, parsed);
return ret;
}
gsize n_crypted, n_params;
const gchar *password;
gint l;
+ GcrParsed *parsed;
+ parsed = push_parsed (self);
ret = GCR_ERROR_UNRECOGNIZED;
asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data, n_data);
if (!asn)
goto done;
+ parsing_block (parsed, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data, n_data);
ret = GCR_ERROR_FAILURE;
/* Figure out the type of encryption */
params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), &n_params);
- parsing_begin (self, data, n_data);
- parsing_object (self, CKO_PRIVATE_KEY);
-
/* Loop to try different passwords */
for (;;) {
/* We assume unrecognized data, is a bad encryption key */
}
- parsing_end (self);
-
done:
if (cih)
gcry_cipher_close (cih);
egg_asn1x_destroy (asn);
egg_secure_free (crypted);
+ pop_parsed (self, parsed);
return ret;
}
{
gchar *name = NULL;
GNode *asn;
+ GcrParsed *parsed;
asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data);
if (asn == NULL)
return GCR_ERROR_UNRECOGNIZED;
- parsing_begin (self, data, n_data);
- parsing_object (self, CKO_CERTIFICATE);
+ parsed = push_parsed (self);
- parsed_ulong (self, CKA_CERTIFICATE_TYPE, CKC_X_509);
+ parsing_block (parsed, GCR_FORMAT_DER_CERTIFICATE_X509, data, n_data);
+ parsing_object (parsed, CKO_CERTIFICATE);
+ parsed_ulong_attribute (parsed, CKA_CERTIFICATE_TYPE, CKC_X_509);
- if (self->pv->parsed_label == NULL)
+ if (gcr_parser_get_parsed_label (self) == NULL)
name = egg_dn_read_part (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL), "CN");
egg_asn1x_destroy (asn);
if (name != NULL) {
- parsed_label (self, name);
+ parsed_label (parsed, name);
g_free (name);
}
- parsed_attribute (self, CKA_VALUE, data, n_data);
- parsed_fire (self);
+ parsed_attribute (parsed, CKA_VALUE, data, n_data);
+ parsed_fire (self, parsed);
- parsing_end (self);
+ pop_parsed (self, parsed);
return SUCCESS;
}
const guchar* content = NULL;
gsize n_content;
GQuark oid;
+ GcrParsed *parsed;
+ parsed = push_parsed (self);
ret = GCR_ERROR_UNRECOGNIZED;
asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-ContentInfo", data, n_data);
if (!asn)
goto done;
+ parsing_block (parsed, GCR_FORMAT_DER_PKCS7, data, n_data);
ret = GCR_ERROR_FAILURE;
node = egg_asn1x_node (asn, "contentType", NULL);
done:
egg_asn1x_destroy (asn);
+ pop_parsed (self, parsed);
return ret;
}
gchar *friendly;
gsize n_element;
guint i;
+ GcrParsed *parsed;
ret = GCR_ERROR_UNRECOGNIZED;
if (!element)
goto done;
+ parsed = push_parsed (self);
+
friendly = parse_pkcs12_bag_friendly_name (egg_asn1x_node (asn, i, "bagAttributes", NULL));
if (friendly != NULL)
- parsed_label (self, friendly);
+ parsed_label (parsed, friendly);
/* A normal unencrypted key */
if (oid == GCR_OID_PKCS12_BAG_PKCS8_KEY) {
r = GCR_ERROR_UNRECOGNIZED;
}
- if (friendly != NULL)
- parsed_label (self, NULL);
+ pop_parsed (self, parsed);
if (r == GCR_ERROR_FAILURE ||
r == GCR_ERROR_CANCELLED ||
guchar *content = NULL;
gsize n_element, n_content;
GQuark oid;
+ GcrParsed *parsed;
+ parsed = push_parsed (self);
ret = GCR_ERROR_UNRECOGNIZED;
asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab, "pkcs-12-PFX",
if (!asn)
goto done;
- parsing_begin (self, data, n_data);
+ parsing_block (parsed, GCR_FORMAT_DER_PKCS12, data, n_data);
oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "authSafe", "contentType", NULL));
if (!oid)
if (ret == SUCCESS)
ret = handle_pkcs12_safe (self, content, n_content);
- parsing_end (self);
-
done:
g_free (content);
egg_asn1x_destroy (asn_content);
egg_asn1x_destroy (asn);
+ pop_parsed (self, parsed);
return ret;
}
gpointer user_data)
{
GcrParser *self = GCR_PARSER (user_data);
+ GcrParsed *parsed;
+
+ parsed = push_parsed (self);
/* All we can do is the packet bounds */
- parsing_begin (self, outer, n_outer);
- parsing_object (self, CKO_DATA);
- parsed_fire (self);
- parsing_end (self);
+ parsing_block (parsed, GCR_FORMAT_OPENPGP_PACKET, outer, n_outer);
+ parsing_object (parsed, CKO_DATA);
+ parsed_fire (self, parsed);
+ pop_parsed (self, parsed);
}
static gint
}
/* -----------------------------------------------------------------------------
- * PEM PARSING
+ * ARMOR PARSING
*/
+static gboolean
+formats_for_armor_type (GQuark armor_type,
+ gint *inner_format,
+ gint *outer_format)
+{
+ gint dummy;
+ if (!inner_format)
+ inner_format = &dummy;
+ if (!outer_format)
+ outer_format = &dummy;
+
+ if (armor_type == PEM_RSA_PRIVATE_KEY) {
+ *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_RSA;
+ *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_RSA;
+ } else if (armor_type == PEM_DSA_PRIVATE_KEY) {
+ *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_DSA;
+ *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_DSA;
+ } else if (armor_type == PEM_ANY_PRIVATE_KEY) {
+ *inner_format = GCR_FORMAT_DER_PRIVATE_KEY;
+ *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY;
+ } else if (armor_type == PEM_PRIVATE_KEY) {
+ *inner_format = GCR_FORMAT_DER_PKCS8_PLAIN;
+ *outer_format = GCR_FORMAT_PEM_PKCS8_PLAIN;
+ } else if (armor_type == PEM_ENCRYPTED_PRIVATE_KEY) {
+ *inner_format = GCR_FORMAT_DER_PKCS8_ENCRYPTED;
+ *outer_format = GCR_FORMAT_PEM_PKCS8_ENCRYPTED;
+ } else if (armor_type == PEM_CERTIFICATE) {
+ *inner_format = GCR_FORMAT_DER_CERTIFICATE_X509;
+ *outer_format = GCR_FORMAT_PEM_CERTIFICATE_X509;
+ } else if (armor_type == PEM_PKCS7) {
+ *inner_format = GCR_FORMAT_DER_PKCS7;
+ *outer_format = GCR_FORMAT_PEM_PKCS7;
+ } else if (armor_type == PEM_PKCS12) {
+ *inner_format = GCR_FORMAT_DER_PKCS12;
+ *outer_format = GCR_FORMAT_PEM_PKCS12;
+ } else if (armor_type == ARMOR_PGP_PRIVATE_KEY_BLOCK) {
+ *inner_format = GCR_FORMAT_OPENPGP_PACKET;
+ *outer_format = GCR_FORMAT_OPENPGP_ARMOR;
+ } else if (armor_type == ARMOR_PGP_PUBLIC_KEY_BLOCK) {
+ *inner_format = GCR_FORMAT_OPENPGP_PACKET;
+ *outer_format = GCR_FORMAT_OPENPGP_ARMOR;
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static gint
-handle_plain_pem (GcrParser *self, GQuark type, gint subformat,
- const guchar *data, gsize n_data)
+handle_plain_pem (GcrParser *self,
+ gint format_id,
+ gint want_format,
+ const guchar *data,
+ gsize n_data)
{
ParserFormat *format;
- gint format_id;
-
- if (type == PEM_RSA_PRIVATE_KEY)
- format_id = GCR_FORMAT_DER_PRIVATE_KEY_RSA;
-
- else if (type == PEM_DSA_PRIVATE_KEY)
- format_id = GCR_FORMAT_DER_PRIVATE_KEY_DSA;
-
- else if (type == PEM_ANY_PRIVATE_KEY)
- format_id = GCR_FORMAT_DER_PRIVATE_KEY;
-
- else if (type == PEM_PRIVATE_KEY)
- format_id = GCR_FORMAT_DER_PKCS8_PLAIN;
-
- else if (type == PEM_ENCRYPTED_PRIVATE_KEY)
- format_id = GCR_FORMAT_DER_PKCS8_ENCRYPTED;
-
- else if (type == PEM_CERTIFICATE)
- format_id = GCR_FORMAT_DER_CERTIFICATE_X509;
- else if (type == PEM_PKCS7)
- format_id = GCR_FORMAT_DER_PKCS7;
-
- else if (type == PEM_PKCS12)
- format_id = GCR_FORMAT_DER_PKCS12;
-
- else if (type == ARMOR_PGP_PRIVATE_KEY_BLOCK)
- format_id = GCR_FORMAT_OPENPGP_PACKET;
-
- else if (type == ARMOR_PGP_PUBLIC_KEY_BLOCK)
- format_id = GCR_FORMAT_OPENPGP_PACKET;
-
- else
- return GCR_ERROR_UNRECOGNIZED;
-
- if (subformat != 0 && subformat != format_id)
+ if (want_format != 0 && want_format != format_id)
return GCR_ERROR_UNRECOGNIZED;
format = parser_format_lookup (format_id);
return (format->function) (self, data, n_data);
}
-static CK_OBJECT_CLASS
-pem_type_to_class (gint type)
-{
- if (type == PEM_RSA_PRIVATE_KEY ||
- type == PEM_DSA_PRIVATE_KEY ||
- type == PEM_ANY_PRIVATE_KEY ||
- type == PEM_PRIVATE_KEY ||
- type == PEM_ENCRYPTED_PRIVATE_KEY)
- return CKO_PRIVATE_KEY;
-
- else if (type == PEM_CERTIFICATE)
- return CKO_CERTIFICATE;
-
- else if (type == PEM_PKCS7 ||
- type == PEM_PKCS12)
- return 0;
-
- return 0;
-}
-
static gint
-handle_encrypted_pem (GcrParser *self, GQuark type, gint subformat,
- GHashTable *headers, const guchar *data, gsize n_data)
+handle_encrypted_pem (GcrParser *self,
+ gint format_id,
+ gint want_format,
+ GHashTable *headers,
+ const guchar *data,
+ gsize n_data)
{
PasswordState pstate = PASSWORD_STATE_INIT;
const gchar *password;
g_assert (GCR_IS_PARSER (self));
g_assert (headers);
- g_assert (type);
val = g_hash_table_lookup (headers, "DEK-Info");
if (!val) {
n_decrypted = l;
/* Try to parse */
- res = handle_plain_pem (self, type, subformat, decrypted, n_decrypted);
+ res = handle_plain_pem (self, format_id, want_format,
+ decrypted, n_decrypted);
egg_secure_free (decrypted);
/* Unrecognized is a bad password */
typedef struct {
GcrParser *parser;
gint result;
- gint subformat;
+ gint want_format;
} HandlePemArgs;
static void
gint res = GCR_ERROR_FAILURE;
gboolean encrypted = FALSE;
const gchar *val;
+ gint inner_format;
+ gint outer_format;
+ GcrParsed *parsed;
/* Something already failed to parse */
if (args->result == GCR_ERROR_FAILURE)
return;
+ if (!formats_for_armor_type (type, &inner_format, &outer_format))
+ return;
+
+ parsed = push_parsed (args->parser);
+
/* Fill in information necessary for prompting */
- parsing_begin (args->parser, outer, n_outer);
- parsing_object (args->parser, pem_type_to_class (type));
+ parsing_block (parsed, outer_format, outer, n_outer);
/* See if it's encrypted PEM all openssl like*/
if (headers) {
}
if (encrypted)
- res = handle_encrypted_pem (args->parser, type, args->subformat,
- headers, data, n_data);
+ res = handle_encrypted_pem (args->parser, inner_format,
+ args->want_format, headers,
+ data, n_data);
else
- res = handle_plain_pem (args->parser, type, args->subformat,
- data, n_data);
+ res = handle_plain_pem (args->parser, inner_format,
+ args->want_format, data, n_data);
- parsing_end (args->parser);
+ pop_parsed (args->parser, parsed);
if (res != GCR_ERROR_UNRECOGNIZED) {
if (args->result == GCR_ERROR_UNRECOGNIZED)
gpointer user_data)
{
GcrParser *self = GCR_PARSER (user_data);
+ GcrParsed *parsed;
- parsing_begin (self, outer, n_outer);
- parsed_attributes (self, attrs);
- parsed_label (self, label);
- parsed_fire (self);
- parsing_end (self);
+ parsed = push_parsed (self);
+ parsing_block (parsed, GCR_FORMAT_OPENSSH_PUBLIC, outer, n_outer);
+ parsed_attributes (parsed, attrs);
+ parsed_label (parsed, label);
+ parsed_fire (self, parsed);
+ pop_parsed (self, parsed);
}
static gint
* FORMATS
*/
+/**
+ * GcrDataFormat:
+ * @GCR_FORMAT_INVALID: Not a valid format
+ * @GCR_FORMAT_DER_PRIVATE_KEY: DER encoded private key
+ * @GCR_FORMAT_DER_PRIVATE_KEY_RSA: DER encoded RSA private key
+ * @GCR_FORMAT_DER_PRIVATE_KEY_DSA: DER encoded DSA private key
+ * @GCR_FORMAT_DER_CERTIFICATE_X509: DER encoded X.509 certificate
+ * @GCR_FORMAT_DER_PKCS7: DER encoded PKCS\#7 container file which can contain certificates
+ * @GCR_FORMAT_DER_PKCS8: DER encoded PKCS\#8 file which can contain a key
+ * @GCR_FORMAT_DER_PKCS8_PLAIN: Unencrypted DER encoded PKCS\#8 file which can contain a key
+ * @GCR_FORMAT_DER_PKCS8_ENCRYPTED: Encrypted DER encoded PKCS\#8 file which can contain a key
+ * @GCR_FORMAT_DER_PKCS12: DER encoded PKCS\#12 file which can contain certificates and/or keys
+ * @GCR_FORMAT_OPENSSH_PUBLIC: OpenSSH v1 or v2 public key
+ * @GCR_FORMAT_OPENPGP_PACKET: OpenPGP key packet(s)
+ * @GCR_FORMAT_OPENPGP_ARMOR: OpenPGP public or private key armor encoded data
+ * @GCR_FORMAT_PEM: An OpenSSL style PEM file with unspecified contents
+ * @GCR_FORMAT_PEM_PRIVATE_KEY: An OpenSSL style PEM file with a private key
+ * @GCR_FORMAT_PEM_PRIVATE_KEY_RSA: An OpenSSL style PEM file with a private RSA key
+ * @GCR_FORMAT_PEM_PRIVATE_KEY_DSA: An OpenSSL style PEM file with a private DSA key
+ * @GCR_FORMAT_PEM_CERTIFICATE_X509: An OpenSSL style PEM file with an X.509 certificate
+ * @GCR_FORMAT_PEM_PKCS7: An OpenSSL style PEM file containing PKCS\#7
+ * @GCR_FORMAT_PEM_PKCS8_PLAIN: Unencrypted OpenSSL style PEM file containing PKCS\#8
+ * @GCR_FORMAT_PEM_PKCS8_ENCRYPTED: Encrypted OpenSSL style PEM file containing PKCS\#8
+ * @GCR_FORMAT_PEM_PKCS12: An OpenSSL style PEM file containing PKCS\#12
+ *
+ * The various format identifiers.
+ */
+
/* In order of parsing when no formats specified */
static const ParserFormat parser_normal[] = {
{ GCR_FORMAT_PEM, parse_pem },
GcrParser *self = GCR_PARSER (obj);
gsize i;
- if (self->pv->parsed_attrs)
- gck_attributes_unref (self->pv->parsed_attrs);
- self->pv->parsed_attrs = NULL;
-
- g_free (self->pv->parsed_label);
- self->pv->parsed_label = NULL;
+ g_assert (!self->pv->parsed);
for (i = 0; i < self->pv->passwords->len; ++i)
egg_secure_strfree (g_ptr_array_index (self->pv->passwords, i));
{
GcrParser *self = GCR_PARSER (obj);
- g_assert (!self->pv->parsed_attrs);
- g_assert (!self->pv->parsed_label);
+ g_assert (!self->pv->parsed);
g_ptr_array_free (self->pv->passwords, TRUE);
self->pv->passwords = NULL;
/**
* gcr_parser_format_enable:
* @self: The parser
- * @format_id: The format identifier
+ * @format: The format identifier
*
* Enable parsing of the given format. Use -1 to enable all the formats.
*/
void
-gcr_parser_format_enable (GcrParser *self, gint format_id)
+gcr_parser_format_enable (GcrParser *self,
+ GcrDataFormat format)
{
- const ParserFormat *format;
+ const ParserFormat *form;
guint i;
g_return_if_fail (GCR_IS_PARSER (self));
if (!self->pv->specific_formats)
self->pv->specific_formats = g_tree_new (compare_pointers);
- if (format_id != -1) {
- format = parser_format_lookup (format_id);
- g_return_if_fail (format);
+ if (format != -1) {
+ form = parser_format_lookup (format);
+ g_return_if_fail (form);
g_tree_insert (self->pv->specific_formats,
- (gpointer)format, (gpointer)format);
+ (gpointer)form, (gpointer)form);
} else {
for (i = 0; i < G_N_ELEMENTS (parser_formats); i++) {
- format = &parser_formats[i];
- g_tree_insert (self->pv->specific_formats, (gpointer)format,
- (gpointer)format);
+ form = &parser_formats[i];
+ g_tree_insert (self->pv->specific_formats, (gpointer)form,
+ (gpointer)form);
}
}
}
/**
* gcr_parser_format_disable:
* @self: The parser
- * @format_id: The format identifier
+ * @format: The format identifier
*
* Disable parsing of the given format. Use -1 to disable all the formats.
*/
void
-gcr_parser_format_disable (GcrParser *self, gint format_id)
+gcr_parser_format_disable (GcrParser *self,
+ GcrDataFormat format)
{
- ParserFormat *format;
+ ParserFormat *form;
g_return_if_fail (GCR_IS_PARSER (self));
- if (format_id == -1) {
+ if (format == -1) {
if (self->pv->specific_formats)
g_tree_destroy (self->pv->specific_formats);
self->pv->specific_formats = NULL;
if (!self->pv->specific_formats)
return;
- format = parser_format_lookup (format_id);
- g_return_if_fail (format);
+ form = parser_format_lookup (format);
+ g_return_if_fail (form);
- g_tree_remove (self->pv->specific_formats, format);
+ g_tree_remove (self->pv->specific_formats, form);
}
/**
* gcr_parser_format_supported:
* @self: The parser
- * @format_id: The format identifier
+ * @format: The format identifier
*
* Check whether the given format is supported by the parser.
*
* Returns: Whether the format is supported.
*/
gboolean
-gcr_parser_format_supported (GcrParser *self, gint format_id)
+gcr_parser_format_supported (GcrParser *self,
+ GcrDataFormat format)
{
g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
- g_return_val_if_fail (format_id != -1, FALSE);
- return parser_format_lookup (format_id) ? TRUE : FALSE;
+ g_return_val_if_fail (format != -1, FALSE);
+ return parser_format_lookup (format) ? TRUE : FALSE;
}
/**
const gchar*
gcr_parser_get_parsed_description (GcrParser *self)
{
+ GcrParsed *parsed;
+
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
- return self->pv->parsed_desc;
+
+ for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
+ if (parsed->description != NULL)
+ return parsed->description;
+ }
+
+ return NULL;
}
/**
GckAttributes*
gcr_parser_get_parsed_attributes (GcrParser *self)
{
+ GcrParsed *parsed;
+
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
- return self->pv->parsed_attrs;
+
+ for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
+ if (parsed->attrs != NULL)
+ return parsed->attrs;
+ }
+
+ return NULL;
}
/**
const gchar*
gcr_parser_get_parsed_label (GcrParser *self)
{
+ GcrParsed *parsed;
+
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
- return self->pv->parsed_label;
+
+ for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
+ if (parsed->label != NULL)
+ return parsed->label;
+ }
+
+ return NULL;
}
/**
gcr_parser_get_parsed_block (GcrParser *self,
gsize *n_block)
{
+ GcrParsed *parsed;
+
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
g_return_val_if_fail (n_block, NULL);
- *n_block = self->pv->parsing_n_block;
- return self->pv->parsing_block;
+
+ for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
+ if (parsed->block != NULL) {
+ *n_block = parsed->n_block;
+ return parsed->block;
+ }
+ }
+
+ *n_block = 0;
+ return NULL;
+}
+
+/**
+ * gcr_parser_get_parsed_format:
+ * @self: a parser
+ *
+ * Get the format of the raw data block that represents this parsed object.
+ * This corresponds with the data returned from gcr_parser_get_parsed_block().
+ *
+ * This is only valid during the GcrParser::parsed signal.
+ *
+ * Returns: The data format of the currently parsed item.
+ */
+GcrDataFormat
+gcr_parser_get_parsed_format (GcrParser *self)
+{
+ GcrParsed *parsed;
+
+ g_return_val_if_fail (GCR_IS_PARSER (self), 0);
+
+ for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
+ if (parsed->block != NULL)
+ return parsed->format;
+ }
+
+ return 0;
}
/* ---------------------------------------------------------------------------------