LCOV - code coverage report
Current view: top level - gcr - gcr-parser.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 1186 1435 82.6 %
Date: 2022-09-04 10:20:22 Functions: 108 129 83.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 523 964 54.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * gnome-keyring
       3                 :            :  *
       4                 :            :  * Copyright (C) 2008 Stefan Walter
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or modify
       7                 :            :  * it under the terms of the GNU Lesser General Public License as
       8                 :            :  * published by the Free Software Foundation; either version 2.1 of
       9                 :            :  * the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This program is distributed in the hope that it will be useful, but
      12                 :            :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Lesser General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Lesser General Public
      17                 :            :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18                 :            :  */
      19                 :            : 
      20                 :            : #include "config.h"
      21                 :            : 
      22                 :            : #include "gck/gck.h"
      23                 :            : 
      24                 :            : #include "gcr-internal.h"
      25                 :            : #include "gcr-openpgp.h"
      26                 :            : #include "gcr-openssh.h"
      27                 :            : #include "gcr-parser.h"
      28                 :            : #include "gcr-record.h"
      29                 :            : #include "gcr-types.h"
      30                 :            : 
      31                 :            : #include "gcr/gcr-marshal.h"
      32                 :            : #include "gcr/gcr-oids.h"
      33                 :            : 
      34                 :            : #include "egg/egg-armor.h"
      35                 :            : #include "egg/egg-asn1x.h"
      36                 :            : #include "egg/egg-asn1-defs.h"
      37                 :            : #include "egg/egg-dn.h"
      38                 :            : #include "egg/egg-openssl.h"
      39                 :            : #include "egg/egg-secure-memory.h"
      40                 :            : #include "egg/egg-symkey.h"
      41                 :            : 
      42                 :            : #include <glib/gi18n-lib.h>
      43                 :            : 
      44                 :            : #include <stdlib.h>
      45                 :            : #include <gcrypt.h>
      46                 :            : 
      47                 :            : /**
      48                 :            :  * GcrParser:
      49                 :            :  *
      50                 :            :  * A parser for parsing various types of files or data.
      51                 :            :  *
      52                 :            :  * A `GcrParser` can parse various certificate and key files such as OpenSSL
      53                 :            :  * PEM files, DER encoded certifictes, PKCS#8 keys and so on. Each various
      54                 :            :  * format is identified by a value in the [enum@DataFormat] enumeration.
      55                 :            :  *
      56                 :            :  * In order to parse data, a new parser is created with gcr_parser_new() and
      57                 :            :  * then the [signal@Parser::authenticate] and [signal@Parser::parsed] signals
      58                 :            :  * should be connected to. Data is then fed to the parser via
      59                 :            :  * [method@Parser.parse_data] or [method@Parser.parse_stream].
      60                 :            :  *
      61                 :            :  * During the [signal@Parser::parsed] signal the attributes that make up the
      62                 :            :  * currently parsed item can be retrieved using the
      63                 :            :  * [method@Parser.get_parsed_attributes] function.
      64                 :            :  */
      65                 :            : 
      66                 :            : /**
      67                 :            :  * GcrParsed:
      68                 :            :  *
      69                 :            :  * A parsed item parsed by a #GcrParser.
      70                 :            :  */
      71                 :            : 
      72                 :            : /**
      73                 :            :  * GcrParserClass:
      74                 :            :  * @parent_class: The parent class
      75                 :            :  * @authenticate: The default handler for the authenticate signal.
      76                 :            :  * @parsed: The default handler for the parsed signal.
      77                 :            :  *
      78                 :            :  * The class for #GcrParser
      79                 :            :  */
      80                 :            : 
      81                 :            : /**
      82                 :            :  * GCR_DATA_ERROR:
      83                 :            :  *
      84                 :            :  * A domain for data errors with codes from #GcrDataError
      85                 :            :  */
      86                 :            : 
      87                 :            : /**
      88                 :            :  * GcrDataError:
      89                 :            :  * @GCR_ERROR_FAILURE: Failed to parse or serialize the data
      90                 :            :  * @GCR_ERROR_UNRECOGNIZED: The data was unrecognized or unsupported
      91                 :            :  * @GCR_ERROR_CANCELLED: The operation was cancelled
      92                 :            :  * @GCR_ERROR_LOCKED: The data was encrypted or locked and could not be unlocked.
      93                 :            :  *
      94                 :            :  * Values responding to error codes for parsing and serializing data.
      95                 :            :  */
      96                 :            : 
      97                 :            : enum {
      98                 :            :         PROP_0,
      99                 :            :         PROP_PARSED_LABEL,
     100                 :            :         PROP_PARSED_ATTRIBUTES,
     101                 :            :         PROP_PARSED_DESCRIPTION
     102                 :            : };
     103                 :            : 
     104                 :            : enum {
     105                 :            :         AUTHENTICATE,
     106                 :            :         PARSED,
     107                 :            :         LAST_SIGNAL
     108                 :            : };
     109                 :            : 
     110                 :            : #define SUCCESS 0
     111                 :            : 
     112                 :            : static guint signals[LAST_SIGNAL] = { 0 };
     113                 :            : 
     114                 :            : struct _GcrParsed {
     115                 :            :         gint refs;
     116                 :            :         GckBuilder builder;
     117                 :            :         GckAttributes *attrs;
     118                 :            :         const gchar *description;
     119                 :            :         gchar *label;
     120                 :            :         GBytes *data;
     121                 :            :         gboolean sensitive;
     122                 :            :         GcrDataFormat format;
     123                 :            :         gchar *filename;
     124                 :            :         struct _GcrParsed *next;
     125                 :            : };
     126                 :            : 
     127                 :            : struct _GcrParserPrivate {
     128                 :            :         GTree *specific_formats;
     129                 :            :         gboolean normal_formats;
     130                 :            :         GPtrArray *passwords;
     131                 :            :         GcrParsed *parsed;
     132                 :            :         gchar *filename;
     133                 :            : };
     134                 :            : 
     135   [ +  +  +  -  :       9006 : G_DEFINE_TYPE_WITH_PRIVATE (GcrParser, gcr_parser, G_TYPE_OBJECT);
                   +  + ]
     136                 :            : 
     137                 :            : typedef struct {
     138                 :            :         gint ask_state;
     139                 :            :         gint seen;
     140                 :            : } PasswordState;
     141                 :            : 
     142                 :            : #define PASSWORD_STATE_INIT { 0, 0 }
     143                 :            : 
     144                 :            : typedef struct _ParserFormat {
     145                 :            :         gint format_id;
     146                 :            :         gint (*function) (GcrParser *self, GBytes *data);
     147                 :            : } ParserFormat;
     148                 :            : 
     149                 :            : /* Forward declarations */
     150                 :            : static const ParserFormat parser_normal[];
     151                 :            : static const ParserFormat parser_formats[];
     152                 :            : static ParserFormat* parser_format_lookup (gint format_id);
     153                 :            : 
     154                 :        965 : EGG_SECURE_DECLARE (parser);
     155                 :            : 
     156                 :            : /* -----------------------------------------------------------------------------
     157                 :            :  * QUARK DEFINITIONS
     158                 :            :  */
     159                 :            : 
     160                 :            : /*
     161                 :            :  * PEM STRINGS
     162                 :            :  * The xxxxx in: ----- BEGIN xxxxx ------
     163                 :            :  */
     164                 :            : 
     165                 :            : static GQuark PEM_CERTIFICATE;
     166                 :            : static GQuark PEM_RSA_PRIVATE_KEY;
     167                 :            : static GQuark PEM_DSA_PRIVATE_KEY;
     168                 :            : static GQuark PEM_EC_PRIVATE_KEY;
     169                 :            : static GQuark PEM_ANY_PRIVATE_KEY;
     170                 :            : static GQuark PEM_ENCRYPTED_PRIVATE_KEY;
     171                 :            : static GQuark PEM_PRIVATE_KEY;
     172                 :            : static GQuark PEM_PKCS7;
     173                 :            : static GQuark PEM_PKCS12;
     174                 :            : static GQuark PEM_CERTIFICATE_REQUEST;
     175                 :            : static GQuark PEM_NEW_CERTIFICATE_REQUEST;
     176                 :            : static GQuark PEM_PUBLIC_KEY;
     177                 :            : 
     178                 :            : static GQuark ARMOR_PGP_PUBLIC_KEY_BLOCK;
     179                 :            : static GQuark ARMOR_PGP_PRIVATE_KEY_BLOCK;
     180                 :            : 
     181                 :            : static void
     182                 :          3 : init_quarks (void)
     183                 :            : {
     184                 :            :         static size_t quarks_inited = 0;
     185                 :            : 
     186   [ +  -  +  -  :          3 :         if (g_once_init_enter (&quarks_inited)) {
                   +  - ]
     187                 :            : 
     188                 :            :                 #define QUARK(name, value) \
     189                 :            :                         name = g_quark_from_static_string(value)
     190                 :            : 
     191                 :          3 :                 QUARK (PEM_CERTIFICATE, "CERTIFICATE");
     192                 :          3 :                 QUARK (PEM_PRIVATE_KEY, "PRIVATE KEY");
     193                 :          3 :                 QUARK (PEM_RSA_PRIVATE_KEY, "RSA PRIVATE KEY");
     194                 :          3 :                 QUARK (PEM_DSA_PRIVATE_KEY, "DSA PRIVATE KEY");
     195                 :          3 :                 QUARK (PEM_EC_PRIVATE_KEY, "EC PRIVATE KEY");
     196                 :          3 :                 QUARK (PEM_ANY_PRIVATE_KEY, "ANY PRIVATE KEY");
     197                 :          3 :                 QUARK (PEM_ENCRYPTED_PRIVATE_KEY, "ENCRYPTED PRIVATE KEY");
     198                 :          3 :                 QUARK (PEM_PKCS7, "PKCS7");
     199                 :          3 :                 QUARK (PEM_PKCS12, "PKCS12");
     200                 :          3 :                 QUARK (PEM_CERTIFICATE_REQUEST, "CERTIFICATE REQUEST");
     201                 :          3 :                 QUARK (PEM_NEW_CERTIFICATE_REQUEST, "NEW CERTIFICATE REQUEST");
     202                 :          3 :                 QUARK (PEM_PUBLIC_KEY, "PUBLIC KEY");
     203                 :            : 
     204                 :          3 :                 QUARK (ARMOR_PGP_PRIVATE_KEY_BLOCK, "PGP PRIVATE KEY BLOCK");
     205                 :          3 :                 QUARK (ARMOR_PGP_PUBLIC_KEY_BLOCK, "PGP PUBLIC KEY BLOCK");
     206                 :            : 
     207                 :            :                 #undef QUARK
     208                 :            : 
     209                 :          3 :                 g_once_init_leave (&quarks_inited, 1);
     210                 :            :         }
     211                 :          3 : }
     212                 :            : 
     213                 :            : /* -----------------------------------------------------------------------------
     214                 :            :  * INTERNAL
     215                 :            :  */
     216                 :            : 
     217                 :            : static void
     218                 :         26 : parsed_attribute (GcrParsed *parsed,
     219                 :            :                   CK_ATTRIBUTE_TYPE type,
     220                 :            :                   gconstpointer data,
     221                 :            :                   gsize n_data)
     222                 :            : {
     223         [ -  + ]:         26 :         g_assert (parsed != NULL);
     224                 :         26 :         gck_builder_add_data (&parsed->builder, type, data, n_data);
     225                 :         26 : }
     226                 :            : 
     227                 :            : static void
     228                 :       1998 : parsed_attribute_bytes (GcrParsed *parsed,
     229                 :            :                         CK_ATTRIBUTE_TYPE type,
     230                 :            :                         GBytes *data)
     231                 :            : {
     232         [ -  + ]:       1998 :         g_assert (parsed != NULL);
     233                 :       3996 :         gck_builder_add_data (&parsed->builder, type,
     234                 :       1998 :                               g_bytes_get_data (data, NULL),
     235                 :            :                               g_bytes_get_size (data));
     236                 :       1998 : }
     237                 :            : 
     238                 :            : static gboolean
     239                 :        873 : parsed_asn1_number (GcrParsed *parsed,
     240                 :            :                     GNode *asn,
     241                 :            :                     const gchar *part,
     242                 :            :                     CK_ATTRIBUTE_TYPE type)
     243                 :            : {
     244                 :            :         GBytes *value;
     245                 :            : 
     246         [ -  + ]:        873 :         g_assert (asn);
     247         [ -  + ]:        873 :         g_assert (parsed);
     248                 :            : 
     249                 :        873 :         value = egg_asn1x_get_integer_as_usg (egg_asn1x_node (asn, part, NULL));
     250         [ -  + ]:        873 :         if (value == NULL)
     251                 :          0 :                 return FALSE;
     252                 :            : 
     253                 :        873 :         parsed_attribute_bytes (parsed, type, value);
     254                 :        873 :         g_bytes_unref (value);
     255                 :        873 :         return TRUE;
     256                 :            : }
     257                 :            : 
     258                 :            : static gboolean
     259                 :        690 : parsed_asn1_element (GcrParsed *parsed,
     260                 :            :                      GNode *asn,
     261                 :            :                      const gchar *part,
     262                 :            :                      CK_ATTRIBUTE_TYPE type)
     263                 :            : {
     264                 :            :         GBytes *value;
     265                 :            : 
     266         [ -  + ]:        690 :         g_assert (asn);
     267         [ -  + ]:        690 :         g_assert (parsed);
     268                 :            : 
     269                 :        690 :         value = egg_asn1x_get_element_raw (egg_asn1x_node (asn, part, NULL));
     270         [ -  + ]:        690 :         if (value == NULL)
     271                 :          0 :                 return FALSE;
     272                 :            : 
     273                 :        690 :         parsed_attribute_bytes (parsed, type, value);
     274                 :        690 :         g_bytes_unref (value);
     275                 :        690 :         return TRUE;
     276                 :            : }
     277                 :            : 
     278                 :            : static gboolean
     279                 :         46 : parsed_asn1_structure (GcrParsed *parsed,
     280                 :            :                       GNode *asn,
     281                 :            :                       CK_ATTRIBUTE_TYPE type)
     282                 :            : {
     283                 :            :         GBytes *value;
     284                 :            : 
     285         [ -  + ]:         46 :         g_assert (asn);
     286         [ -  + ]:         46 :         g_assert (parsed);
     287                 :            : 
     288                 :         46 :         value = egg_asn1x_encode (asn, g_realloc);
     289         [ -  + ]:         46 :         if (value == NULL)
     290                 :          0 :                 return FALSE;
     291                 :            : 
     292                 :         46 :         parsed_attribute_bytes (parsed, type, value);
     293                 :         46 :         g_bytes_unref (value);
     294                 :         46 :         return TRUE;
     295                 :            : }
     296                 :            : 
     297                 :            : static void
     298                 :        509 : parsed_ulong_attribute (GcrParsed *parsed,
     299                 :            :                         CK_ATTRIBUTE_TYPE type,
     300                 :            :                         gulong value)
     301                 :            : {
     302         [ -  + ]:        509 :         g_assert (parsed != NULL);
     303                 :        509 :         gck_builder_add_ulong (&parsed->builder, type, value);
     304                 :        509 : }
     305                 :            : 
     306                 :            : static void
     307                 :        104 : parsed_boolean_attribute (GcrParsed *parsed,
     308                 :            :                           CK_ATTRIBUTE_TYPE type,
     309                 :            :                           gboolean value)
     310                 :            : {
     311         [ -  + ]:        104 :         g_assert (parsed != NULL);
     312                 :        104 :         gck_builder_add_boolean (&parsed->builder, type, value);
     313                 :        104 : }
     314                 :            : 
     315                 :            : 
     316                 :            : static void
     317                 :        774 : parsing_block (GcrParsed *parsed,
     318                 :            :                gint format,
     319                 :            :                GBytes *data)
     320                 :            : {
     321         [ -  + ]:        774 :         g_assert (parsed != NULL);
     322         [ -  + ]:        774 :         g_assert (data != NULL);
     323         [ -  + ]:        774 :         g_assert (format != 0);
     324         [ -  + ]:        774 :         g_assert (parsed->data == NULL);
     325                 :            : 
     326                 :        774 :         parsed->format = format;
     327                 :        774 :         parsed->data = g_bytes_ref (data);
     328                 :        774 : }
     329                 :            : 
     330                 :            : static void
     331                 :        539 : parsed_description (GcrParsed *parsed,
     332                 :            :                     CK_OBJECT_CLASS klass)
     333                 :            : {
     334         [ -  + ]:        539 :         g_assert (parsed != NULL);
     335   [ +  +  +  +  :        539 :         switch (klass) {
                   +  - ]
     336                 :        104 :         case CKO_PRIVATE_KEY:
     337                 :        104 :                 parsed->description = _("Private Key");
     338                 :        104 :                 break;
     339                 :        327 :         case CKO_CERTIFICATE:
     340                 :        327 :                 parsed->description = _("Certificate");
     341                 :        327 :                 break;
     342                 :         66 :         case CKO_PUBLIC_KEY:
     343                 :         66 :                 parsed->description = _("Public Key");
     344                 :         66 :                 break;
     345                 :         26 :         case CKO_GCR_GNUPG_RECORDS:
     346                 :         26 :                 parsed->description = _("PGP Key");
     347                 :         26 :                 break;
     348                 :         16 :         case CKO_GCR_CERTIFICATE_REQUEST:
     349                 :         16 :                 parsed->description = _("Certificate Request");
     350                 :         16 :                 break;
     351                 :          0 :         default:
     352                 :          0 :                 parsed->description = NULL;
     353                 :          0 :                 break;
     354                 :            :         }
     355                 :        539 : }
     356                 :            : 
     357                 :            : static void
     358                 :        535 : parsing_object (GcrParsed *parsed,
     359                 :            :                 CK_OBJECT_CLASS klass)
     360                 :            : {
     361         [ -  + ]:        535 :         g_assert (parsed != NULL);
     362                 :            : 
     363                 :        535 :         gck_builder_clear (&parsed->builder);
     364         [ +  + ]:        535 :         if (parsed->sensitive)
     365                 :        166 :                 gck_builder_init_full (&parsed->builder, GCK_BUILDER_SECURE_MEMORY);
     366                 :            :         else
     367                 :        369 :                 gck_builder_init_full (&parsed->builder, GCK_BUILDER_NONE);
     368                 :        535 :         gck_builder_add_ulong (&parsed->builder, CKA_CLASS, klass);
     369                 :        535 :         parsed_description (parsed, klass);
     370                 :        535 : }
     371                 :            : 
     372                 :            : static void
     373                 :          4 : parsed_attributes (GcrParsed *parsed,
     374                 :            :                    GckAttributes *attrs)
     375                 :            : {
     376                 :            :         gulong klass;
     377                 :            : 
     378         [ -  + ]:          4 :         g_assert (parsed != NULL);
     379         [ -  + ]:          4 :         g_assert (attrs != NULL);
     380                 :            : 
     381         [ +  - ]:          4 :         if (gck_attributes_find_ulong (attrs, CKA_CLASS, &klass))
     382                 :          4 :                 parsed_description (parsed, klass);
     383                 :          4 :         gck_builder_add_all (&parsed->builder, attrs);
     384                 :          4 : }
     385                 :            : 
     386                 :            : static void
     387                 :        305 : parsed_label (GcrParsed *parsed,
     388                 :            :               const gchar *label)
     389                 :            : {
     390         [ -  + ]:        305 :         g_assert (parsed != NULL);
     391         [ -  + ]:        305 :         g_assert (parsed->label == NULL);
     392                 :        305 :         parsed->label = g_strdup (label);
     393                 :        305 : }
     394                 :            : 
     395                 :            : static GcrParsed *
     396                 :       1466 : push_parsed (GcrParser *self,
     397                 :            :              gboolean sensitive)
     398                 :            : {
     399                 :       1466 :         GcrParsed *parsed = g_new0 (GcrParsed, 1);
     400                 :       1466 :         parsed->refs = 0;
     401                 :       1466 :         parsed->sensitive = sensitive;
     402                 :       1466 :         parsed->next = self->pv->parsed;
     403                 :       1466 :         parsed->filename = g_strdup (gcr_parser_get_filename (self));
     404                 :       1466 :         self->pv->parsed = parsed;
     405                 :       1466 :         return parsed;
     406                 :            : }
     407                 :            : 
     408                 :            : static void
     409                 :       1467 : _gcr_parsed_free (GcrParsed *parsed)
     410                 :            : {
     411                 :       1467 :         gck_builder_clear (&parsed->builder);
     412         [ +  + ]:       1467 :         if (parsed->attrs)
     413                 :        540 :                 gck_attributes_unref (parsed->attrs);
     414         [ +  + ]:       1467 :         if (parsed->data)
     415                 :        775 :                 g_bytes_unref (parsed->data);
     416                 :       1467 :         g_free (parsed->label);
     417                 :       1467 :         g_free (parsed->filename);
     418                 :       1467 :         g_free (parsed);
     419                 :       1467 : }
     420                 :            : 
     421                 :            : static void
     422                 :       1466 : pop_parsed (GcrParser *self,
     423                 :            :             GcrParsed *parsed)
     424                 :            : {
     425         [ -  + ]:       1466 :         g_assert (parsed == self->pv->parsed);
     426                 :       1466 :         self->pv->parsed = parsed->next;
     427                 :       1466 :         _gcr_parsed_free (parsed);
     428                 :       1466 : }
     429                 :            : 
     430                 :            : static gint
     431                 :         66 : enum_next_password (GcrParser *self, PasswordState *state, const gchar **password)
     432                 :            : {
     433                 :            :         gboolean result;
     434                 :            : 
     435                 :            :         /*
     436                 :            :          * Next passes we look through all the passwords that the parser
     437                 :            :          * has seen so far. This is because different parts of a encrypted
     438                 :            :          * container (such as PKCS#12) often use the same password even
     439                 :            :          * if with different algorithms.
     440                 :            :          *
     441                 :            :          * If we didn't do this and the user chooses enters a password,
     442                 :            :          * but doesn't save it, they would get prompted for the same thing
     443                 :            :          * over and over, dumb.
     444                 :            :          */
     445                 :            : 
     446                 :            :         /* Look in our list of passwords */
     447         [ +  + ]:         66 :         if (state->seen < self->pv->passwords->len) {
     448         [ -  + ]:         52 :                 g_assert (state->seen >= 0);
     449                 :         52 :                 *password = g_ptr_array_index (self->pv->passwords, state->seen);
     450                 :         52 :                 ++state->seen;
     451                 :         52 :                 return SUCCESS;
     452                 :            :         }
     453                 :            : 
     454                 :            :         /* Fire off all the parsed property signals so anyone watching can update their state */
     455                 :         14 :         g_object_notify (G_OBJECT (self), "parsed-description");
     456                 :         14 :         g_object_notify (G_OBJECT (self), "parsed-attributes");
     457                 :         14 :         g_object_notify (G_OBJECT (self), "parsed-label");
     458                 :            : 
     459                 :         14 :         g_signal_emit (self, signals[AUTHENTICATE], 0, state->ask_state, &result);
     460                 :         14 :         ++state->ask_state;
     461                 :            : 
     462         [ -  + ]:         14 :         if (!result)
     463                 :          0 :                 return GCR_ERROR_CANCELLED;
     464                 :            : 
     465                 :            :         /* Return any passwords added */
     466         [ +  - ]:         14 :         if (state->seen < self->pv->passwords->len) {
     467         [ -  + ]:         14 :                 g_assert (state->seen >= 0);
     468                 :         14 :                 *password = g_ptr_array_index (self->pv->passwords, state->seen);
     469                 :         14 :                 ++state->seen;
     470                 :         14 :                 return SUCCESS;
     471                 :            :         }
     472                 :            : 
     473                 :          0 :         return GCR_ERROR_LOCKED;
     474                 :            : }
     475                 :            : 
     476                 :            : static void
     477                 :        539 : parsed_fire (GcrParser *self,
     478                 :            :              GcrParsed *parsed)
     479                 :            : {
     480   [ -  +  +  -  :        539 :         g_assert (GCR_IS_PARSER (self));
             +  -  -  + ]
     481         [ -  + ]:        539 :         g_assert (parsed != NULL);
     482         [ -  + ]:        539 :         g_assert (parsed == self->pv->parsed);
     483         [ -  + ]:        539 :         g_assert (parsed->attrs == NULL);
     484                 :            : 
     485                 :        539 :         parsed->attrs = gck_builder_end (&parsed->builder);
     486                 :            : 
     487                 :        539 :         g_object_notify (G_OBJECT (self), "parsed-description");
     488                 :        539 :         g_object_notify (G_OBJECT (self), "parsed-attributes");
     489                 :        539 :         g_object_notify (G_OBJECT (self), "parsed-label");
     490                 :            : 
     491                 :        539 :         g_signal_emit (self, signals[PARSED], 0);
     492                 :        539 : }
     493                 :            : 
     494                 :            : /* -----------------------------------------------------------------------------
     495                 :            :  * RSA PRIVATE KEY
     496                 :            :  */
     497                 :            : 
     498                 :            : static gint
     499                 :        188 : parse_der_private_key_rsa (GcrParser *self,
     500                 :            :                            GBytes *data)
     501                 :            : {
     502                 :        188 :         gint res = GCR_ERROR_UNRECOGNIZED;
     503                 :        188 :         GNode *asn = NULL;
     504                 :            :         gulong version;
     505                 :            :         GcrParsed *parsed;
     506                 :            : 
     507                 :        188 :         parsed = push_parsed (self, TRUE);
     508                 :            : 
     509                 :        188 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data);
     510         [ +  + ]:        188 :         if (!asn)
     511                 :        135 :                 goto done;
     512                 :            : 
     513                 :         53 :         parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data);
     514                 :         53 :         parsing_object (parsed, CKO_PRIVATE_KEY);
     515                 :         53 :         parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_RSA);
     516                 :         53 :         parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
     517                 :         53 :         res = GCR_ERROR_FAILURE;
     518                 :            : 
     519         [ -  + ]:         53 :         if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version))
     520                 :          0 :                 goto done;
     521                 :            : 
     522                 :            :         /* We only support simple version */
     523         [ -  + ]:         53 :         if (version != 0) {
     524                 :          0 :                 res = GCR_ERROR_UNRECOGNIZED;
     525                 :          0 :                 g_message ("unsupported version of RSA key: %lu", version);
     526                 :          0 :                 goto done;
     527                 :            :         }
     528                 :            : 
     529   [ +  -  +  - ]:        106 :         if (!parsed_asn1_number (parsed, asn, "modulus", CKA_MODULUS) ||
     530         [ +  - ]:        106 :             !parsed_asn1_number (parsed, asn, "publicExponent", CKA_PUBLIC_EXPONENT) ||
     531         [ +  - ]:        106 :             !parsed_asn1_number (parsed, asn, "privateExponent", CKA_PRIVATE_EXPONENT) ||
     532         [ +  - ]:        106 :             !parsed_asn1_number (parsed, asn, "prime1", CKA_PRIME_1) ||
     533         [ -  + ]:        106 :             !parsed_asn1_number (parsed, asn, "prime2", CKA_PRIME_2) ||
     534                 :         53 :             !parsed_asn1_number (parsed, asn, "coefficient", CKA_COEFFICIENT))
     535                 :          0 :                 goto done;
     536                 :            : 
     537                 :         53 :         parsed_fire (self, parsed);
     538                 :         53 :         res = SUCCESS;
     539                 :            : 
     540                 :        188 : done:
     541                 :        188 :         egg_asn1x_destroy (asn);
     542         [ -  + ]:        188 :         if (res == GCR_ERROR_FAILURE)
     543                 :          0 :                 g_message ("invalid RSA key");
     544                 :            : 
     545                 :        188 :         pop_parsed (self, parsed);
     546                 :        188 :         return res;
     547                 :            : }
     548                 :            : 
     549                 :            : /* -----------------------------------------------------------------------------
     550                 :            :  * DSA PRIVATE KEY
     551                 :            :  */
     552                 :            : 
     553                 :            : static gint
     554                 :        159 : parse_der_private_key_dsa (GcrParser *self,
     555                 :            :                            GBytes *data)
     556                 :            : {
     557                 :        159 :         gint ret = GCR_ERROR_UNRECOGNIZED;
     558                 :        159 :         GNode *asn = NULL;
     559                 :            :         GcrParsed *parsed;
     560                 :            : 
     561                 :        159 :         parsed = push_parsed (self, TRUE);
     562                 :            : 
     563                 :        159 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data);
     564         [ +  + ]:        159 :         if (!asn)
     565                 :        134 :                 goto done;
     566                 :            : 
     567                 :         25 :         parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data);
     568                 :         25 :         parsing_object (parsed, CKO_PRIVATE_KEY);
     569                 :         25 :         parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
     570                 :         25 :         parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
     571                 :         25 :         ret = GCR_ERROR_FAILURE;
     572                 :            : 
     573   [ +  -  +  - ]:         50 :         if (!parsed_asn1_number (parsed, asn, "p", CKA_PRIME) ||
     574         [ +  - ]:         50 :             !parsed_asn1_number (parsed, asn, "q", CKA_SUBPRIME) ||
     575         [ -  + ]:         50 :             !parsed_asn1_number (parsed, asn, "g", CKA_BASE) ||
     576                 :         25 :             !parsed_asn1_number (parsed, asn, "priv", CKA_VALUE))
     577                 :          0 :                 goto done;
     578                 :            : 
     579                 :         25 :         parsed_fire (self, parsed);
     580                 :         25 :         ret = SUCCESS;
     581                 :            : 
     582                 :        159 : done:
     583                 :        159 :         egg_asn1x_destroy (asn);
     584         [ -  + ]:        159 :         if (ret == GCR_ERROR_FAILURE)
     585                 :          0 :                 g_message ("invalid DSA key");
     586                 :            : 
     587                 :        159 :         pop_parsed (self, parsed);
     588                 :        159 :         return ret;
     589                 :            : }
     590                 :            : 
     591                 :            : static gint
     592                 :          2 : parse_der_private_key_dsa_parts (GcrParser *self,
     593                 :            :                                  GBytes *keydata,
     594                 :            :                                  GNode *params)
     595                 :            : {
     596                 :          2 :         gint ret = GCR_ERROR_UNRECOGNIZED;
     597                 :          2 :         GNode *asn_params = NULL;
     598                 :          2 :         GNode *asn_key = NULL;
     599                 :            :         GcrParsed *parsed;
     600                 :            : 
     601                 :          2 :         parsed = push_parsed (self, TRUE);
     602                 :            : 
     603                 :          2 :         asn_params = egg_asn1x_get_any_as (params, pk_asn1_tab, "DSAParameters");
     604                 :          2 :         asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata);
     605   [ +  -  -  + ]:          2 :         if (!asn_params || !asn_key)
     606                 :          0 :                 goto done;
     607                 :            : 
     608                 :          2 :         parsing_object (parsed, CKO_PRIVATE_KEY);
     609                 :          2 :         parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
     610                 :          2 :         parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
     611                 :          2 :         ret = GCR_ERROR_FAILURE;
     612                 :            : 
     613   [ +  -  +  - ]:          4 :         if (!parsed_asn1_number (parsed, asn_params, "p", CKA_PRIME) ||
     614         [ +  - ]:          4 :             !parsed_asn1_number (parsed, asn_params, "q", CKA_SUBPRIME) ||
     615         [ -  + ]:          4 :             !parsed_asn1_number (parsed, asn_params, "g", CKA_BASE) ||
     616                 :          2 :             !parsed_asn1_number (parsed, asn_key, NULL, CKA_VALUE))
     617                 :          0 :                 goto done;
     618                 :            : 
     619                 :          2 :         parsed_fire (self, parsed);
     620                 :          2 :         ret = SUCCESS;
     621                 :            : 
     622                 :          2 : done:
     623                 :          2 :         egg_asn1x_destroy (asn_key);
     624                 :          2 :         egg_asn1x_destroy (asn_params);
     625         [ -  + ]:          2 :         if (ret == GCR_ERROR_FAILURE)
     626                 :          0 :                 g_message ("invalid DSA key");
     627                 :            : 
     628                 :          2 :         pop_parsed (self, parsed);
     629                 :          2 :         return ret;
     630                 :            : }
     631                 :            : /* -----------------------------------------------------------------------------
     632                 :            :  * EC PRIVATE KEY
     633                 :            :  */
     634                 :            : 
     635                 :            : static gint
     636                 :        136 : parse_der_private_key_ec (GcrParser *self,
     637                 :            :                           GBytes *data)
     638                 :            : {
     639                 :        136 :         gint ret = GCR_ERROR_UNRECOGNIZED;
     640                 :        136 :         GNode *asn = NULL;
     641                 :        136 :         GBytes *value = NULL;
     642                 :        136 :         GBytes *pub = NULL;
     643                 :        136 :         GNode *asn_q = NULL;
     644                 :            :         GcrParsed *parsed;
     645                 :            :         guint bits;
     646                 :            :         gulong version;
     647                 :            : 
     648                 :        136 :         parsed = push_parsed (self, TRUE);
     649                 :            : 
     650                 :        136 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECPrivateKey", data);
     651         [ +  + ]:        136 :         if (!asn)
     652                 :        112 :                 goto done;
     653                 :            : 
     654         [ -  + ]:         24 :         if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version))
     655                 :          0 :                 goto done;
     656                 :            : 
     657                 :            :         /* We only support simple version */
     658         [ -  + ]:         24 :         if (version != 1) {
     659                 :          0 :                 g_message ("unsupported version of EC key: %lu", version);
     660                 :          0 :                 goto done;
     661                 :            :         }
     662                 :            : 
     663                 :         24 :         parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_EC, data);
     664                 :         24 :         parsing_object (parsed, CKO_PRIVATE_KEY);
     665                 :         24 :         parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_EC);
     666                 :         24 :         parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
     667                 :         24 :         ret = GCR_ERROR_FAILURE;
     668                 :            : 
     669         [ -  + ]:         24 :         if (!parsed_asn1_element (parsed, asn, "parameters", CKA_EC_PARAMS))
     670                 :          0 :                 goto done;
     671                 :            : 
     672                 :         24 :         value = egg_asn1x_get_string_as_usg (egg_asn1x_node (asn, "privateKey", NULL), egg_secure_realloc);
     673         [ -  + ]:         24 :         if (!value)
     674                 :          0 :                 goto done;
     675                 :            : 
     676                 :         24 :         parsed_attribute_bytes (parsed, CKA_VALUE, value);
     677                 :            : 
     678                 :         24 :         pub = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "publicKey", NULL), &bits);
     679   [ +  -  -  + ]:         24 :         if (!pub || bits != 8 * g_bytes_get_size (pub))
     680                 :          0 :                 goto done;
     681                 :         24 :         asn_q = egg_asn1x_create (pk_asn1_tab, "ECPoint");
     682         [ -  + ]:         24 :         if (!asn_q)
     683                 :          0 :                 goto done;
     684                 :         24 :         egg_asn1x_set_string_as_bytes (asn_q, pub);
     685                 :            : 
     686         [ -  + ]:         24 :         if (!parsed_asn1_structure (parsed, asn_q, CKA_EC_POINT))
     687                 :          0 :                 goto done;
     688                 :            : 
     689                 :         24 :         parsed_fire (self, parsed);
     690                 :         24 :         ret = SUCCESS;
     691                 :            : 
     692                 :        136 : done:
     693         [ +  + ]:        136 :         if (pub)
     694                 :         24 :                 g_bytes_unref (pub);
     695         [ +  + ]:        136 :         if (value)
     696                 :         24 :                 g_bytes_unref (value);
     697                 :        136 :         egg_asn1x_destroy (asn);
     698                 :        136 :         egg_asn1x_destroy (asn_q);
     699         [ -  + ]:        136 :         if (ret == GCR_ERROR_FAILURE)
     700                 :          0 :                 g_message ("invalid EC key");
     701                 :            : 
     702                 :        136 :         pop_parsed (self, parsed);
     703                 :        136 :         return ret;
     704                 :            : }
     705                 :            : 
     706                 :            : /* -----------------------------------------------------------------------------
     707                 :            :  * PRIVATE KEY
     708                 :            :  */
     709                 :            : 
     710                 :            : static gint
     711                 :         54 : parse_der_private_key (GcrParser *self,
     712                 :            :                        GBytes *data)
     713                 :            : {
     714                 :            :         gint res;
     715                 :            : 
     716                 :         54 :         res = parse_der_private_key_rsa (self, data);
     717         [ +  - ]:         54 :         if (res == GCR_ERROR_UNRECOGNIZED)
     718                 :         54 :                 res = parse_der_private_key_dsa (self, data);
     719         [ +  - ]:         54 :         if (res == GCR_ERROR_UNRECOGNIZED)
     720                 :         54 :                 res = parse_der_private_key_ec (self, data);
     721                 :            : 
     722                 :         54 :         return res;
     723                 :            : }
     724                 :            : 
     725                 :            : /* -----------------------------------------------------------------------------
     726                 :            :  * SUBJECT PUBLIC KEY
     727                 :            :  */
     728                 :            : 
     729                 :            : static gint
     730                 :         20 : handle_subject_public_key_rsa (GcrParser *self,
     731                 :            :                                GcrParsed *parsed,
     732                 :            :                                GBytes *key,
     733                 :            :                                GNode *params)
     734                 :            : {
     735                 :         20 :         gint res = GCR_ERROR_FAILURE;
     736                 :         20 :         GNode *asn = NULL;
     737                 :            : 
     738                 :         20 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", key);
     739         [ -  + ]:         20 :         if (!asn)
     740                 :          0 :                 goto done;
     741                 :            : 
     742                 :         20 :         parsing_object (parsed, CKO_PUBLIC_KEY);
     743                 :         20 :         parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_RSA);
     744                 :            : 
     745   [ +  -  -  + ]:         40 :         if (!parsed_asn1_number (parsed, asn, "modulus", CKA_MODULUS) ||
     746                 :         20 :             !parsed_asn1_number (parsed, asn, "publicExponent", CKA_PUBLIC_EXPONENT))
     747                 :          0 :                 goto done;
     748                 :            : 
     749                 :         20 :         res = SUCCESS;
     750                 :            : 
     751                 :         20 : done:
     752                 :         20 :         egg_asn1x_destroy (asn);
     753                 :         20 :         return res;
     754                 :            : }
     755                 :            : 
     756                 :            : static gint
     757                 :         20 : handle_subject_public_key_dsa (GcrParser *self,
     758                 :            :                                GcrParsed *parsed,
     759                 :            :                                GBytes *key,
     760                 :            :                                GNode *params)
     761                 :            : {
     762                 :         20 :         gint res = GCR_ERROR_FAILURE;
     763                 :         20 :         GNode *key_asn = NULL;
     764                 :         20 :         GNode *param_asn = NULL;
     765                 :            : 
     766                 :         20 :         key_asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPublicPart", key);
     767                 :         20 :         param_asn = egg_asn1x_get_any_as (params, pk_asn1_tab, "DSAParameters");
     768                 :            : 
     769   [ +  -  -  + ]:         20 :         if (!key_asn || !param_asn)
     770                 :          0 :                 goto done;
     771                 :            : 
     772                 :         20 :         parsing_object (parsed, CKO_PUBLIC_KEY);
     773                 :         20 :         parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
     774                 :            : 
     775   [ +  -  +  - ]:         40 :         if (!parsed_asn1_number (parsed, param_asn, "p", CKA_PRIME) ||
     776         [ +  - ]:         40 :             !parsed_asn1_number (parsed, param_asn, "q", CKA_SUBPRIME) ||
     777         [ -  + ]:         40 :             !parsed_asn1_number (parsed, param_asn, "g", CKA_BASE) ||
     778                 :         20 :             !parsed_asn1_number (parsed, key_asn, NULL, CKA_VALUE))
     779                 :          0 :                 goto done;
     780                 :            : 
     781                 :         20 :         res = SUCCESS;
     782                 :            : 
     783                 :         20 : done:
     784                 :         20 :         egg_asn1x_destroy (key_asn);
     785                 :         20 :         egg_asn1x_destroy (param_asn);
     786                 :         20 :         return res;
     787                 :            : }
     788                 :            : 
     789                 :            : static gint
     790                 :         22 : handle_subject_public_key_ec (GcrParser *self,
     791                 :            :                               GcrParsed *parsed,
     792                 :            :                               GBytes *key,
     793                 :            :                               GNode *params)
     794                 :            : {
     795                 :         22 :         gint ret = GCR_ERROR_FAILURE;
     796                 :         22 :         GBytes *bytes = NULL;
     797                 :         22 :         GNode *asn = NULL;
     798                 :            : 
     799                 :         22 :         parsing_object (parsed, CKO_PUBLIC_KEY);
     800                 :         22 :         parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_EC);
     801                 :            : 
     802                 :         22 :         bytes = egg_asn1x_encode (params, g_realloc);
     803                 :         22 :         parsed_attribute_bytes (parsed, CKA_EC_PARAMS, bytes);
     804                 :         22 :         g_bytes_unref (bytes);
     805                 :            : 
     806                 :         22 :         asn = egg_asn1x_create (pk_asn1_tab, "ECPoint");
     807         [ -  + ]:         22 :         if (!asn)
     808                 :          0 :                 goto done;
     809                 :         22 :         egg_asn1x_set_string_as_bytes (asn, key);
     810                 :         22 :         parsed_asn1_structure (parsed, asn, CKA_EC_POINT);
     811                 :         22 :         ret = SUCCESS;
     812                 :         22 : done:
     813                 :         22 :         egg_asn1x_destroy (asn);
     814                 :         22 :         return ret;
     815                 :            : }
     816                 :            : 
     817                 :            : static gint
     818                 :        135 : parse_der_subject_public_key (GcrParser *self,
     819                 :            :                               GBytes *data)
     820                 :            : {
     821                 :            :         GcrParsed *parsed;
     822                 :            :         GNode *params;
     823                 :            :         GBytes *key;
     824                 :        135 :         GNode *asn = NULL;
     825                 :            :         GNode *node;
     826                 :            :         GQuark oid;
     827                 :            :         guint bits;
     828                 :            :         gint ret;
     829                 :            : 
     830                 :        135 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data);
     831         [ +  + ]:        135 :         if (asn == NULL)
     832                 :         73 :                 return GCR_ERROR_UNRECOGNIZED;
     833                 :            : 
     834                 :         62 :         parsed = push_parsed (self, TRUE);
     835                 :         62 :         parsing_block (parsed, GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, data);
     836                 :            : 
     837                 :         62 :         node = egg_asn1x_node (asn, "algorithm", "algorithm", NULL);
     838                 :         62 :         oid = egg_asn1x_get_oid_as_quark (node);
     839                 :            : 
     840                 :         62 :         params = egg_asn1x_node (asn, "algorithm", "parameters", NULL);
     841                 :            : 
     842                 :         62 :         node = egg_asn1x_node (asn, "subjectPublicKey", NULL);
     843                 :         62 :         key = egg_asn1x_get_bits_as_raw (node, &bits);
     844                 :            : 
     845         [ +  + ]:         62 :         if (oid == GCR_OID_PKIX1_RSA)
     846                 :         20 :                 ret = handle_subject_public_key_rsa (self, parsed, key, params);
     847                 :            : 
     848         [ +  + ]:         42 :         else if (oid == GCR_OID_PKIX1_DSA)
     849                 :         20 :                 ret = handle_subject_public_key_dsa (self, parsed, key, params);
     850                 :            : 
     851         [ +  - ]:         22 :         else if (oid == GCR_OID_PKIX1_EC)
     852                 :         22 :                 ret = handle_subject_public_key_ec (self, parsed, key, params);
     853                 :            : 
     854                 :            :         else
     855                 :          0 :                 ret = GCR_ERROR_UNRECOGNIZED;
     856                 :            : 
     857                 :         62 :         g_bytes_unref (key);
     858                 :            : 
     859         [ +  - ]:         62 :         if (ret == SUCCESS)
     860                 :         62 :                 parsed_fire (self, parsed);
     861                 :            : 
     862                 :         62 :         pop_parsed (self, parsed);
     863                 :            : 
     864                 :         62 :         egg_asn1x_destroy (asn);
     865                 :         62 :         return ret;
     866                 :            : }
     867                 :            : 
     868                 :            : /* -----------------------------------------------------------------------------
     869                 :            :  * PKCS8
     870                 :            :  */
     871                 :            : 
     872                 :            : static gint
     873                 :        133 : parse_der_pkcs8_plain (GcrParser *self,
     874                 :            :                        GBytes *data)
     875                 :            : {
     876                 :            :         gint ret;
     877                 :            :         CK_KEY_TYPE key_type;
     878                 :            :         GQuark key_algo;
     879                 :        133 :         GBytes *keydata = NULL;
     880                 :        133 :         GNode *params = NULL;
     881                 :        133 :         GNode *asn = NULL;
     882                 :            :         GcrParsed *parsed;
     883                 :            : 
     884                 :        133 :         parsed = push_parsed (self, TRUE);
     885                 :        133 :         ret = GCR_ERROR_UNRECOGNIZED;
     886                 :            : 
     887                 :        133 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data);
     888         [ +  + ]:        133 :         if (!asn)
     889                 :        117 :                 goto done;
     890                 :            : 
     891                 :         16 :         parsing_block (parsed, GCR_FORMAT_DER_PKCS8_PLAIN, data);
     892                 :         16 :         ret = GCR_ERROR_FAILURE;
     893                 :         16 :         key_type = GCK_INVALID;
     894                 :            : 
     895                 :         16 :         key_algo = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "privateKeyAlgorithm", "algorithm", NULL));
     896         [ -  + ]:         16 :         if (!key_algo)
     897                 :          0 :                 goto done;
     898         [ +  + ]:         16 :         else if (key_algo == GCR_OID_PKIX1_RSA)
     899                 :         14 :                 key_type = CKK_RSA;
     900         [ +  - ]:          2 :         else if (key_algo == GCR_OID_PKIX1_DSA)
     901                 :          2 :                 key_type = CKK_DSA;
     902         [ #  # ]:          0 :         else if (key_algo == GCR_OID_PKIX1_EC)
     903                 :          0 :                 key_type = CKK_EC;
     904                 :            : 
     905         [ -  + ]:         16 :         if (key_type == GCK_INVALID) {
     906                 :          0 :                 ret = GCR_ERROR_UNRECOGNIZED;
     907                 :          0 :                 goto done;
     908                 :            :         }
     909                 :            : 
     910                 :         16 :         keydata = egg_asn1x_get_string_as_bytes (egg_asn1x_node (asn, "privateKey", NULL));
     911         [ -  + ]:         16 :         if (!keydata)
     912                 :          0 :                 goto done;
     913                 :            : 
     914                 :         16 :         params = egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL);
     915                 :            : 
     916                 :         16 :         ret = SUCCESS;
     917                 :            : 
     918                 :        133 : done:
     919         [ +  + ]:        133 :         if (ret == SUCCESS) {
     920   [ +  +  -  - ]:         16 :                 switch (key_type) {
     921                 :         14 :                 case CKK_RSA:
     922                 :         14 :                         ret = parse_der_private_key_rsa (self, keydata);
     923                 :         14 :                         break;
     924                 :          2 :                 case CKK_DSA:
     925                 :            :                         /* Try the normal sane format */
     926                 :          2 :                         ret = parse_der_private_key_dsa (self, keydata);
     927                 :            : 
     928                 :            :                         /* Otherwise try the two part format that everyone seems to like */
     929   [ +  -  +  - ]:          2 :                         if (ret == GCR_ERROR_UNRECOGNIZED && params)
     930                 :          2 :                                 ret = parse_der_private_key_dsa_parts (self, keydata, params);
     931                 :          2 :                         break;
     932                 :          0 :                 case CKK_EC:
     933                 :          0 :                         ret = parse_der_private_key_ec (self, keydata);
     934                 :          0 :                         break;
     935                 :            : 
     936                 :          0 :                 default:
     937                 :          0 :                         g_message ("invalid or unsupported key type in PKCS#8 key");
     938                 :          0 :                         ret = GCR_ERROR_UNRECOGNIZED;
     939                 :          0 :                         break;
     940                 :            :                 };
     941                 :            : 
     942         [ -  + ]:        117 :         } else if (ret == GCR_ERROR_FAILURE) {
     943                 :          0 :                 g_message ("invalid PKCS#8 key");
     944                 :            :         }
     945                 :            : 
     946         [ +  + ]:        133 :         if (keydata)
     947                 :         16 :                 g_bytes_unref (keydata);
     948                 :        133 :         egg_asn1x_destroy (asn);
     949                 :        133 :         pop_parsed (self, parsed);
     950                 :        133 :         return ret;
     951                 :            : }
     952                 :            : 
     953                 :            : static gint
     954                 :         96 : parse_der_pkcs8_encrypted (GcrParser *self,
     955                 :            :                            GBytes *data)
     956                 :            : {
     957                 :         96 :         PasswordState pstate = PASSWORD_STATE_INIT;
     958                 :         96 :         GNode *asn = NULL;
     959                 :         96 :         gcry_cipher_hd_t cih = NULL;
     960                 :            :         gcry_error_t gcry;
     961                 :            :         gint ret, r;
     962                 :            :         GQuark scheme;
     963                 :         96 :         guchar *crypted = NULL;
     964                 :         96 :         GNode *params = NULL;
     965                 :            :         GBytes *cbytes;
     966                 :            :         gsize n_crypted;
     967                 :            :         const gchar *password;
     968                 :            :         GcrParsed *parsed;
     969                 :            :         gint l;
     970                 :            : 
     971                 :         96 :         parsed = push_parsed (self, FALSE);
     972                 :         96 :         ret = GCR_ERROR_UNRECOGNIZED;
     973                 :            : 
     974                 :         96 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data);
     975         [ +  + ]:         96 :         if (!asn)
     976                 :         83 :                 goto done;
     977                 :            : 
     978                 :         13 :         parsing_block (parsed, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data);
     979                 :         13 :         ret = GCR_ERROR_FAILURE;
     980                 :            : 
     981                 :            :         /* Figure out the type of encryption */
     982                 :         13 :         scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL));
     983         [ -  + ]:         13 :         if (!scheme)
     984                 :          0 :                 goto done;
     985                 :            : 
     986                 :         13 :         params = egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL);
     987                 :            : 
     988                 :            :         /* Loop to try different passwords */
     989                 :            :         for (;;) {
     990                 :            : 
     991         [ -  + ]:         39 :                 g_assert (cih == NULL);
     992                 :            : 
     993                 :         39 :                 r = enum_next_password (self, &pstate, &password);
     994         [ -  + ]:         39 :                 if (r != SUCCESS) {
     995                 :          0 :                         ret = r;
     996                 :          0 :                         break;
     997                 :            :                 }
     998                 :            : 
     999                 :            :                 /* Parse the encryption stuff into a cipher. */
    1000         [ -  + ]:         39 :                 if (!egg_symkey_read_cipher (scheme, password, -1, params, &cih))
    1001                 :          0 :                         break;
    1002                 :            : 
    1003                 :         39 :                 crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedData", NULL), egg_secure_realloc, &n_crypted);
    1004         [ -  + ]:         39 :                 if (!crypted)
    1005                 :          0 :                         break;
    1006                 :            : 
    1007                 :         39 :                 gcry = gcry_cipher_decrypt (cih, crypted, n_crypted, NULL, 0);
    1008                 :         39 :                 gcry_cipher_close (cih);
    1009                 :         39 :                 cih = NULL;
    1010                 :            : 
    1011         [ -  + ]:         39 :                 if (gcry != 0) {
    1012                 :          0 :                         g_warning ("couldn't decrypt pkcs8 data: %s", gcry_strerror (gcry));
    1013                 :          0 :                         break;
    1014                 :            :                 }
    1015                 :            : 
    1016                 :            :                 /* Unpad the DER data */
    1017                 :         39 :                 l = egg_asn1x_element_length (crypted, n_crypted);
    1018         [ +  + ]:         39 :                 if (l > 0)
    1019                 :         22 :                         n_crypted = l;
    1020                 :            : 
    1021                 :         39 :                 cbytes = g_bytes_new_with_free_func (crypted, n_crypted,
    1022                 :            :                                                        egg_secure_free, crypted);
    1023                 :         39 :                 crypted = NULL;
    1024                 :            : 
    1025                 :            :                 /* Try to parse the resulting key */
    1026                 :         39 :                 r = parse_der_pkcs8_plain (self, cbytes);
    1027                 :         39 :                 g_bytes_unref (cbytes);
    1028                 :            : 
    1029         [ +  + ]:         39 :                 if (r != GCR_ERROR_UNRECOGNIZED) {
    1030                 :         13 :                         ret = r;
    1031                 :         13 :                         break;
    1032                 :            :                 }
    1033                 :            : 
    1034                 :            :                 /* We assume unrecognized data, is a bad encryption key */
    1035                 :            :         }
    1036                 :            : 
    1037                 :         96 : done:
    1038         [ -  + ]:         96 :         if (cih)
    1039                 :          0 :                 gcry_cipher_close (cih);
    1040                 :         96 :         egg_asn1x_destroy (asn);
    1041                 :         96 :         egg_secure_free (crypted);
    1042                 :            : 
    1043                 :         96 :         pop_parsed (self, parsed);
    1044                 :         96 :         return ret;
    1045                 :            : }
    1046                 :            : 
    1047                 :            : static gint
    1048                 :         36 : parse_der_pkcs8 (GcrParser *self,
    1049                 :            :                  GBytes *data)
    1050                 :            : {
    1051                 :            :         gint ret;
    1052                 :            : 
    1053                 :         36 :         ret = parse_der_pkcs8_plain (self, data);
    1054         [ +  - ]:         36 :         if (ret == GCR_ERROR_UNRECOGNIZED)
    1055                 :         36 :                 ret = parse_der_pkcs8_encrypted (self, data);
    1056                 :            : 
    1057                 :         36 :         return ret;
    1058                 :            : }
    1059                 :            : 
    1060                 :            : /* -----------------------------------------------------------------------------
    1061                 :            :  * CERTIFICATE
    1062                 :            :  */
    1063                 :            : 
    1064                 :            : static gint
    1065                 :        385 : parse_der_certificate (GcrParser *self,
    1066                 :            :                        GBytes *data)
    1067                 :            : {
    1068                 :        385 :         gchar *name = NULL;
    1069                 :            :         GcrParsed *parsed;
    1070                 :            :         GNode *node;
    1071                 :            :         GNode *asn;
    1072                 :            : 
    1073                 :        385 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data);
    1074         [ +  + ]:        385 :         if (asn == NULL)
    1075                 :         58 :                 return GCR_ERROR_UNRECOGNIZED;
    1076                 :            : 
    1077                 :        327 :         parsed = push_parsed (self, FALSE);
    1078                 :            : 
    1079                 :        327 :         parsing_block (parsed, GCR_FORMAT_DER_CERTIFICATE_X509, data);
    1080                 :        327 :         parsing_object (parsed, CKO_CERTIFICATE);
    1081                 :        327 :         parsed_ulong_attribute (parsed, CKA_CERTIFICATE_TYPE, CKC_X_509);
    1082                 :            : 
    1083                 :        327 :         node = egg_asn1x_node (asn, "tbsCertificate", NULL);
    1084         [ -  + ]:        327 :         g_return_val_if_fail (node != NULL, GCR_ERROR_FAILURE);
    1085                 :            : 
    1086         [ +  + ]:        327 :         if (gcr_parser_get_parsed_label (self) == NULL)
    1087                 :        323 :                 name = egg_dn_read_part (egg_asn1x_node (node, "subject", "rdnSequence", NULL), "CN");
    1088                 :            : 
    1089         [ +  + ]:        327 :         if (name != NULL) {
    1090                 :        281 :                 parsed_label (parsed, name);
    1091                 :        281 :                 g_free (name);
    1092                 :            :         }
    1093                 :            : 
    1094                 :        327 :         parsed_attribute_bytes (parsed, CKA_VALUE, data);
    1095                 :        327 :         parsed_asn1_element (parsed, node, "subject", CKA_SUBJECT);
    1096                 :        327 :         parsed_asn1_element (parsed, node, "issuer", CKA_ISSUER);
    1097                 :        327 :         parsed_asn1_number (parsed, node, "serialNumber", CKA_SERIAL_NUMBER);
    1098                 :        327 :         parsed_fire (self, parsed);
    1099                 :            : 
    1100                 :        327 :         egg_asn1x_destroy (asn);
    1101                 :            : 
    1102                 :        327 :         pop_parsed (self, parsed);
    1103                 :        327 :         return SUCCESS;
    1104                 :            : }
    1105                 :            : 
    1106                 :            : /* -----------------------------------------------------------------------------
    1107                 :            :  * PKCS7
    1108                 :            :  */
    1109                 :            : 
    1110                 :            : static gint
    1111                 :          1 : handle_pkcs7_signed_data (GcrParser *self,
    1112                 :            :                           GNode *content)
    1113                 :            : {
    1114                 :          1 :         GNode *asn = NULL;
    1115                 :            :         GNode *node;
    1116                 :            :         gint ret;
    1117                 :            :         GBytes *certificate;
    1118                 :            :         int i;
    1119                 :            : 
    1120                 :          1 :         ret = GCR_ERROR_UNRECOGNIZED;
    1121                 :            : 
    1122                 :          1 :         asn = egg_asn1x_get_any_as (content, pkix_asn1_tab, "pkcs-7-SignedData");
    1123         [ -  + ]:          1 :         if (!asn)
    1124                 :          0 :                 goto done;
    1125                 :            : 
    1126                 :          1 :         for (i = 0; TRUE; ++i) {
    1127                 :            : 
    1128                 :          2 :                 node = egg_asn1x_node (asn, "certificates", i + 1, NULL);
    1129                 :            : 
    1130                 :            :                 /* No more certificates? */
    1131         [ +  + ]:          2 :                 if (node == NULL)
    1132                 :          1 :                         break;
    1133                 :            : 
    1134                 :          1 :                 certificate = egg_asn1x_get_element_raw (node);
    1135                 :          1 :                 ret = parse_der_certificate (self, certificate);
    1136                 :          1 :                 g_bytes_unref (certificate);
    1137                 :            : 
    1138         [ -  + ]:          1 :                 if (ret != SUCCESS)
    1139                 :          0 :                         goto done;
    1140                 :            :         }
    1141                 :            : 
    1142                 :            :         /* TODO: Parse out all the CRLs */
    1143                 :            : 
    1144                 :          1 :         ret = SUCCESS;
    1145                 :            : 
    1146                 :          1 : done:
    1147                 :          1 :         egg_asn1x_destroy (asn);
    1148                 :          1 :         return ret;
    1149                 :            : }
    1150                 :            : 
    1151                 :            : static gint
    1152                 :         58 : parse_der_pkcs7 (GcrParser *self,
    1153                 :            :                  GBytes *data)
    1154                 :            : {
    1155                 :         58 :         GNode *asn = NULL;
    1156                 :            :         GNode *node;
    1157                 :            :         gint ret;
    1158                 :         58 :         GNode *content = NULL;
    1159                 :            :         GQuark oid;
    1160                 :            :         GcrParsed *parsed;
    1161                 :            : 
    1162                 :         58 :         parsed = push_parsed (self, FALSE);
    1163                 :         58 :         ret = GCR_ERROR_UNRECOGNIZED;
    1164                 :            : 
    1165                 :         58 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-ContentInfo", data);
    1166         [ +  + ]:         58 :         if (!asn)
    1167                 :         57 :                 goto done;
    1168                 :            : 
    1169                 :          1 :         parsing_block (parsed, GCR_FORMAT_DER_PKCS7, data);
    1170                 :          1 :         ret = GCR_ERROR_FAILURE;
    1171                 :            : 
    1172                 :          1 :         node = egg_asn1x_node (asn, "contentType", NULL);
    1173         [ -  + ]:          1 :         if (!node)
    1174                 :          0 :                 goto done;
    1175                 :            : 
    1176                 :          1 :         oid = egg_asn1x_get_oid_as_quark (node);
    1177         [ -  + ]:          1 :         g_return_val_if_fail (oid, GCR_ERROR_FAILURE);
    1178                 :            : 
    1179                 :            :         /* Outer most one must just be plain data */
    1180         [ -  + ]:          1 :         if (oid != GCR_OID_PKCS7_SIGNED_DATA) {
    1181                 :          0 :                 g_message ("unsupported outer content type in pkcs7: %s", g_quark_to_string (oid));
    1182                 :          0 :                 goto done;
    1183                 :            :         }
    1184                 :            : 
    1185                 :          1 :         content = egg_asn1x_node (asn, "content", NULL);
    1186         [ -  + ]:          1 :         if (!content)
    1187                 :          0 :                 goto done;
    1188                 :            : 
    1189                 :          1 :         ret = handle_pkcs7_signed_data (self, content);
    1190                 :            : 
    1191                 :         58 : done:
    1192                 :         58 :         egg_asn1x_destroy (asn);
    1193                 :         58 :         pop_parsed (self, parsed);
    1194                 :         58 :         return ret;
    1195                 :            : }
    1196                 :            : 
    1197                 :            : /* -----------------------------------------------------------------------------
    1198                 :            :  * PKCS12
    1199                 :            :  */
    1200                 :            : 
    1201                 :            : static gint
    1202                 :          5 : handle_pkcs12_cert_bag (GcrParser *self,
    1203                 :            :                         GBytes *data)
    1204                 :            : {
    1205                 :          5 :         GNode *asn = NULL;
    1206                 :          5 :         GNode *asn_content = NULL;
    1207                 :          5 :         guchar *certificate = NULL;
    1208                 :          5 :         GNode *element = NULL;
    1209                 :            :         gsize n_certificate;
    1210                 :            :         GBytes *bytes;
    1211                 :            :         gint ret;
    1212                 :            : 
    1213                 :          5 :         ret = GCR_ERROR_UNRECOGNIZED;
    1214                 :          5 :         asn = egg_asn1x_create_and_decode_full (pkix_asn1_tab, "pkcs-12-CertBag",
    1215                 :            :                                                 data, EGG_ASN1X_NO_STRICT);
    1216         [ -  + ]:          5 :         if (!asn)
    1217                 :          0 :                 goto done;
    1218                 :            : 
    1219                 :          5 :         ret = GCR_ERROR_FAILURE;
    1220                 :            : 
    1221                 :          5 :         element = egg_asn1x_node (asn, "certValue", NULL);
    1222         [ -  + ]:          5 :         if (!element)
    1223                 :          0 :                 goto done;
    1224                 :            : 
    1225                 :          5 :         asn_content = egg_asn1x_get_any_as (element, pkix_asn1_tab, "pkcs-7-Data");
    1226         [ -  + ]:          5 :         if (!asn_content)
    1227                 :          0 :                 goto done;
    1228                 :            : 
    1229                 :          5 :         certificate = egg_asn1x_get_string_as_raw (asn_content, NULL, &n_certificate);
    1230         [ -  + ]:          5 :         if (!certificate)
    1231                 :          0 :                 goto done;
    1232                 :            : 
    1233                 :          5 :         bytes = g_bytes_new_take (certificate, n_certificate);
    1234                 :          5 :         ret = parse_der_certificate (self, bytes);
    1235                 :          5 :         g_bytes_unref (bytes);
    1236                 :            : 
    1237                 :          5 : done:
    1238                 :          5 :         egg_asn1x_destroy (asn_content);
    1239                 :          5 :         egg_asn1x_destroy (asn);
    1240                 :          5 :         return ret;
    1241                 :            : }
    1242                 :            : 
    1243                 :            : static gchar *
    1244                 :          9 : parse_pkcs12_bag_friendly_name (GNode *asn)
    1245                 :            : {
    1246                 :            :         guint count, i;
    1247                 :            :         GQuark oid;
    1248                 :            :         GNode *node;
    1249                 :            :         GNode *asn_str;
    1250                 :            :         gchar *result;
    1251                 :            : 
    1252         [ -  + ]:          9 :         if (asn == NULL)
    1253                 :          0 :                 return NULL;
    1254                 :            : 
    1255                 :          9 :         count = egg_asn1x_count (asn);
    1256         [ +  + ]:         15 :         for (i = 1; i <= count; i++) {
    1257                 :         14 :                 oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, i, "type", NULL));
    1258         [ +  + ]:         14 :                 if (oid == GCR_OID_PKCS9_ATTRIBUTE_FRIENDLY) {
    1259                 :          8 :                         node = egg_asn1x_node (asn, i, "values", 1, NULL);
    1260         [ +  - ]:          8 :                         if (node != NULL) {
    1261                 :          8 :                                 asn_str = egg_asn1x_get_any_as_string (node, EGG_ASN1X_BMP_STRING);
    1262         [ +  - ]:          8 :                                 if (asn_str) {
    1263                 :          8 :                                         result = egg_asn1x_get_bmpstring_as_utf8 (asn_str);
    1264                 :          8 :                                         egg_asn1x_destroy (asn_str);
    1265                 :          8 :                                         return result;
    1266                 :            :                                 }
    1267                 :            :                         }
    1268                 :            :                 }
    1269                 :            :         }
    1270                 :            : 
    1271                 :          1 :         return NULL;
    1272                 :            : }
    1273                 :            : 
    1274                 :            : static gint
    1275                 :         16 : handle_pkcs12_bag (GcrParser *self,
    1276                 :            :                    GBytes *data)
    1277                 :            : {
    1278                 :         16 :         GNode *asn = NULL;
    1279                 :            :         gint ret, r;
    1280                 :         16 :         guint count = 0;
    1281                 :            :         GQuark oid;
    1282                 :            :         GNode *value;
    1283                 :         16 :         GBytes *element = NULL;
    1284                 :            :         gchar *friendly;
    1285                 :            :         guint i;
    1286                 :            :         GcrParsed *parsed;
    1287                 :            : 
    1288                 :         16 :         ret = GCR_ERROR_UNRECOGNIZED;
    1289                 :            : 
    1290                 :         16 :         asn = egg_asn1x_create_and_decode_full (pkix_asn1_tab, "pkcs-12-SafeContents",
    1291                 :            :                                                 data, EGG_ASN1X_NO_STRICT);
    1292         [ +  + ]:         16 :         if (!asn)
    1293                 :          8 :                 goto done;
    1294                 :            : 
    1295                 :          8 :         ret = GCR_ERROR_FAILURE;
    1296                 :            : 
    1297                 :            :         /* Get the number of elements in this bag */
    1298                 :          8 :         count = egg_asn1x_count (asn);
    1299                 :            : 
    1300                 :            :         /*
    1301                 :            :          * Now inside each bag are multiple elements. Who comes up
    1302                 :            :          * with this stuff?
    1303                 :            :          */
    1304         [ +  + ]:         17 :         for (i = 1; i <= count; i++) {
    1305                 :            : 
    1306                 :          9 :                 oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, i, "bagId", NULL));
    1307         [ -  + ]:          9 :                 if (!oid)
    1308                 :          0 :                         goto done;
    1309                 :            : 
    1310                 :          9 :                 value = egg_asn1x_node (asn, i, "bagValue", NULL);
    1311         [ -  + ]:          9 :                 if (!value)
    1312                 :          0 :                         goto done;
    1313                 :            : 
    1314                 :          9 :                 element = egg_asn1x_get_element_raw (value);
    1315                 :          9 :                 parsed = push_parsed (self, FALSE);
    1316                 :            : 
    1317                 :          9 :                 friendly = parse_pkcs12_bag_friendly_name (egg_asn1x_node (asn, i, "bagAttributes", NULL));
    1318         [ +  + ]:          9 :                 if (friendly != NULL) {
    1319                 :          8 :                         parsed_label (parsed, friendly);
    1320                 :          8 :                         g_free (friendly);
    1321                 :            :                 }
    1322                 :            : 
    1323                 :            :                 /* A normal unencrypted key */
    1324         [ -  + ]:          9 :                 if (oid == GCR_OID_PKCS12_BAG_PKCS8_KEY) {
    1325                 :          0 :                         r = parse_der_pkcs8_plain (self, element);
    1326                 :            : 
    1327                 :            :                 /* A properly encrypted key */
    1328         [ +  + ]:          9 :                 } else if (oid == GCR_OID_PKCS12_BAG_PKCS8_ENCRYPTED_KEY) {
    1329                 :          4 :                         r = parse_der_pkcs8_encrypted (self, element);
    1330                 :            : 
    1331                 :            :                 /* A certificate */
    1332         [ +  - ]:          5 :                 } else if (oid == GCR_OID_PKCS12_BAG_CERTIFICATE) {
    1333                 :          5 :                         r = handle_pkcs12_cert_bag (self, element);
    1334                 :            : 
    1335                 :            :                 /* TODO: GCR_OID_PKCS12_BAG_CRL */
    1336                 :            :                 } else {
    1337                 :          0 :                         r = GCR_ERROR_UNRECOGNIZED;
    1338                 :            :                 }
    1339                 :            : 
    1340         [ +  - ]:          9 :                 if (element != NULL)
    1341                 :          9 :                         g_bytes_unref (element);
    1342                 :            : 
    1343                 :          9 :                 pop_parsed (self, parsed);
    1344                 :            : 
    1345   [ +  -  +  - ]:          9 :                 if (r == GCR_ERROR_FAILURE ||
    1346         [ -  + ]:          9 :                     r == GCR_ERROR_CANCELLED ||
    1347                 :            :                     r == GCR_ERROR_LOCKED) {
    1348                 :          0 :                         ret = r;
    1349                 :          0 :                         goto done;
    1350                 :            :                 }
    1351                 :            :         }
    1352                 :            : 
    1353                 :          8 :         ret = SUCCESS;
    1354                 :            : 
    1355                 :         16 : done:
    1356                 :         16 :         egg_asn1x_destroy (asn);
    1357                 :         16 :         return ret;
    1358                 :            : }
    1359                 :            : 
    1360                 :            : static gint
    1361                 :          4 : handle_pkcs12_encrypted_bag (GcrParser *self,
    1362                 :            :                              GNode *bag)
    1363                 :            : {
    1364                 :          4 :         PasswordState pstate = PASSWORD_STATE_INIT;
    1365                 :          4 :         GNode *asn = NULL;
    1366                 :          4 :         gcry_cipher_hd_t cih = NULL;
    1367                 :            :         gcry_error_t gcry;
    1368                 :          4 :         guchar *crypted = NULL;
    1369                 :          4 :         GNode *params = NULL;
    1370                 :            :         gsize n_crypted;
    1371                 :            :         const gchar *password;
    1372                 :            :         GBytes *cbytes;
    1373                 :            :         GQuark scheme;
    1374                 :            :         gint ret, r;
    1375                 :            :         gint l;
    1376                 :            : 
    1377                 :          4 :         ret = GCR_ERROR_UNRECOGNIZED;
    1378                 :            : 
    1379                 :          4 :         asn = egg_asn1x_get_any_as_full (bag, pkix_asn1_tab, "pkcs-7-EncryptedData",
    1380                 :            :                                          EGG_ASN1X_NO_STRICT);
    1381         [ -  + ]:          4 :         if (!asn)
    1382                 :          0 :                 goto done;
    1383                 :            : 
    1384                 :          4 :         ret = GCR_ERROR_FAILURE;
    1385                 :            : 
    1386                 :            :         /* Check the encryption schema OID */
    1387                 :          4 :         scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptedContentInfo", "contentEncryptionAlgorithm", "algorithm", NULL));
    1388         [ -  + ]:          4 :         if (!scheme)
    1389                 :          0 :                 goto done;
    1390                 :            : 
    1391                 :          4 :         params = egg_asn1x_node (asn, "encryptedContentInfo", "contentEncryptionAlgorithm", "parameters", NULL);
    1392         [ +  - ]:          4 :         if (!params)
    1393                 :          0 :                 goto done;
    1394                 :            : 
    1395                 :            :         /* Loop to try different passwords */
    1396                 :            :         for (;;) {
    1397                 :            : 
    1398         [ -  + ]:         12 :                 g_assert (cih == NULL);
    1399                 :            : 
    1400                 :         12 :                 r = enum_next_password (self, &pstate, &password);
    1401         [ -  + ]:         12 :                 if (r != SUCCESS) {
    1402                 :          0 :                         ret = r;
    1403                 :          0 :                         goto done;
    1404                 :            :                 }
    1405                 :            : 
    1406                 :            :                 /* Parse the encryption stuff into a cipher. */
    1407         [ -  + ]:         12 :                 if (!egg_symkey_read_cipher (scheme, password, -1, params, &cih)) {
    1408                 :          0 :                         ret = GCR_ERROR_FAILURE;
    1409                 :          0 :                         goto done;
    1410                 :            :                 }
    1411                 :            : 
    1412                 :         12 :                 crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedContentInfo", "encryptedContent", NULL),
    1413                 :            :                                                        egg_secure_realloc, &n_crypted);
    1414         [ -  + ]:         12 :                 if (!crypted)
    1415                 :          0 :                         goto done;
    1416                 :            : 
    1417                 :         12 :                 gcry = gcry_cipher_decrypt (cih, crypted, n_crypted, NULL, 0);
    1418                 :         12 :                 gcry_cipher_close (cih);
    1419                 :         12 :                 cih = NULL;
    1420                 :            : 
    1421         [ -  + ]:         12 :                 if (gcry != 0) {
    1422                 :          0 :                         g_warning ("couldn't decrypt pkcs12 data: %s", gcry_strerror (gcry));
    1423                 :          0 :                         goto done;
    1424                 :            :                 }
    1425                 :            : 
    1426                 :            :                 /* Unpad the DER data */
    1427                 :         12 :                 l = egg_asn1x_element_length (crypted, n_crypted);
    1428         [ +  + ]:         12 :                 if (l > 0)
    1429                 :          8 :                         n_crypted = l;
    1430                 :            : 
    1431                 :         12 :                 cbytes = g_bytes_new_with_free_func (crypted, n_crypted, egg_secure_free, crypted);
    1432                 :         12 :                 crypted = NULL;
    1433                 :            : 
    1434                 :            :                 /* Try to parse the resulting key */
    1435                 :         12 :                 r = handle_pkcs12_bag (self, cbytes);
    1436                 :         12 :                 g_bytes_unref (cbytes);
    1437                 :            : 
    1438         [ +  + ]:         12 :                 if (r != GCR_ERROR_UNRECOGNIZED) {
    1439                 :          4 :                         ret = r;
    1440                 :          4 :                         break;
    1441                 :            :                 }
    1442                 :            : 
    1443                 :            :                 /* We assume unrecognized data is a bad encryption key */
    1444                 :            :         }
    1445                 :            : 
    1446                 :          4 : done:
    1447         [ -  + ]:          4 :         if (cih)
    1448                 :          0 :                 gcry_cipher_close (cih);
    1449                 :          4 :         egg_asn1x_destroy (asn);
    1450                 :          4 :         egg_secure_free (crypted);
    1451                 :          4 :         return ret;
    1452                 :            : }
    1453                 :            : 
    1454                 :            : static gint
    1455                 :          4 : handle_pkcs12_safe (GcrParser *self,
    1456                 :            :                     GBytes *data)
    1457                 :            : {
    1458                 :          4 :         GNode *asn = NULL;
    1459                 :          4 :         GNode *asn_content = NULL;
    1460                 :            :         gint ret, r;
    1461                 :            :         GNode *bag;
    1462                 :            :         GBytes *content;
    1463                 :            :         GQuark oid;
    1464                 :            :         guint i;
    1465                 :            :         GNode *node;
    1466                 :            : 
    1467                 :          4 :         ret = GCR_ERROR_UNRECOGNIZED;
    1468                 :            : 
    1469                 :          4 :         asn = egg_asn1x_create_and_decode_full (pkix_asn1_tab, "pkcs-12-AuthenticatedSafe",
    1470                 :            :                                                 data, EGG_ASN1X_NO_STRICT);
    1471         [ -  + ]:          4 :         if (!asn)
    1472                 :          0 :                 goto done;
    1473                 :            : 
    1474                 :          4 :         ret = GCR_ERROR_FAILURE;
    1475                 :            : 
    1476                 :            :         /*
    1477                 :            :          * Inside each PKCS12 safe there are multiple bags.
    1478                 :            :          */
    1479                 :          4 :         for (i = 0; TRUE; ++i) {
    1480                 :         12 :                 node = egg_asn1x_node (asn, i + 1, "contentType", NULL);
    1481                 :            : 
    1482                 :            :                 /* All done? no more bags */
    1483         [ +  + ]:         12 :                 if (!node)
    1484                 :          4 :                         break;
    1485                 :            : 
    1486                 :          8 :                 oid = egg_asn1x_get_oid_as_quark (node);
    1487                 :            : 
    1488                 :          8 :                 bag = egg_asn1x_node (asn, i + 1, "content", NULL);
    1489         [ -  + ]:          8 :                 if (!bag)
    1490                 :          0 :                         goto done;
    1491                 :            : 
    1492                 :            :                 /* A non encrypted bag, just parse */
    1493         [ +  + ]:          8 :                 if (oid == GCR_OID_PKCS7_DATA) {
    1494                 :            : 
    1495                 :          4 :                         egg_asn1x_destroy (asn_content);
    1496                 :          4 :                         asn_content = egg_asn1x_get_any_as_full (bag, pkix_asn1_tab,
    1497                 :            :                                                                  "pkcs-7-Data", EGG_ASN1X_NO_STRICT);
    1498         [ -  + ]:          4 :                         if (!asn_content)
    1499                 :          0 :                                 goto done;
    1500                 :            : 
    1501                 :          4 :                         content = egg_asn1x_get_string_as_bytes (asn_content);
    1502         [ -  + ]:          4 :                         if (!content)
    1503                 :          0 :                                 goto done;
    1504                 :            : 
    1505                 :          4 :                         r = handle_pkcs12_bag (self, content);
    1506                 :          4 :                         g_bytes_unref (content);
    1507                 :            : 
    1508                 :            :                 /* Encrypted data first needs decryption */
    1509         [ +  - ]:          4 :                 } else if (oid == GCR_OID_PKCS7_ENCRYPTED_DATA) {
    1510                 :          4 :                         r = handle_pkcs12_encrypted_bag (self, bag);
    1511                 :            : 
    1512                 :            :                 /* Hmmmm, not sure what this is */
    1513                 :            :                 } else {
    1514                 :          0 :                         g_warning ("unrecognized type of safe content in pkcs12: %s", g_quark_to_string (oid));
    1515                 :          0 :                         r = GCR_ERROR_UNRECOGNIZED;
    1516                 :            :                 }
    1517                 :            : 
    1518   [ +  -  +  - ]:          8 :                 if (r == GCR_ERROR_FAILURE ||
    1519         [ -  + ]:          8 :                     r == GCR_ERROR_CANCELLED ||
    1520                 :            :                     r == GCR_ERROR_LOCKED) {
    1521                 :          0 :                         ret = r;
    1522                 :          0 :                         goto done;
    1523                 :            :                 }
    1524                 :            :         }
    1525                 :            : 
    1526                 :          4 :         ret = SUCCESS;
    1527                 :            : 
    1528                 :          4 : done:
    1529                 :          4 :         egg_asn1x_destroy (asn);
    1530                 :          4 :         egg_asn1x_destroy (asn_content);
    1531                 :          4 :         return ret;
    1532                 :            : }
    1533                 :            : 
    1534                 :            : static gint
    1535                 :          4 : verify_pkcs12_safe (GcrParser *self,
    1536                 :            :                     GNode *asn,
    1537                 :            :                     GBytes *content)
    1538                 :            : {
    1539                 :          4 :         PasswordState pstate = PASSWORD_STATE_INIT;
    1540                 :            :         const gchar *password;
    1541                 :          4 :         gcry_md_hd_t mdh = NULL;
    1542                 :            :         const guchar *mac_digest;
    1543                 :            :         gsize mac_len;
    1544                 :          4 :         guchar *digest = NULL;
    1545                 :            :         gsize n_digest;
    1546                 :            :         GQuark algorithm;
    1547                 :            :         GNode *mac_data;
    1548                 :            :         int ret, r;
    1549                 :            : 
    1550                 :          4 :         ret = GCR_ERROR_FAILURE;
    1551                 :            : 
    1552                 :            :         /*
    1553                 :            :          * The MAC is optional (and outside the encryption no less). I wonder
    1554                 :            :          * what the designers (ha) of PKCS#12 were trying to achieve
    1555                 :            :          */
    1556                 :            : 
    1557                 :          4 :         mac_data = egg_asn1x_node (asn, "macData", NULL);
    1558         [ -  + ]:          4 :         if (mac_data == NULL)
    1559                 :          0 :                 return SUCCESS;
    1560                 :            : 
    1561                 :          4 :         algorithm = egg_asn1x_get_oid_as_quark (egg_asn1x_node (mac_data, "mac",
    1562                 :            :                                                 "digestAlgorithm", "algorithm", NULL));
    1563         [ -  + ]:          4 :         if (!algorithm)
    1564                 :          0 :                 goto done;
    1565                 :            : 
    1566                 :          4 :         digest = egg_asn1x_get_string_as_raw (egg_asn1x_node (mac_data, "mac", "digest", NULL), NULL, &n_digest);
    1567         [ -  + ]:          4 :         if (!digest)
    1568                 :          0 :                 goto done;
    1569                 :            : 
    1570                 :            :         /* Loop to try different passwords */
    1571                 :            :         for (;;) {
    1572         [ -  + ]:         12 :                 g_assert (mdh == NULL);
    1573                 :            : 
    1574                 :         12 :                 r = enum_next_password (self, &pstate, &password);
    1575         [ -  + ]:         12 :                 if (r != SUCCESS) {
    1576                 :          0 :                         ret = r;
    1577                 :          0 :                         goto done;
    1578                 :            :                 }
    1579                 :            : 
    1580                 :            :                 /* Parse the encryption stuff into a cipher. */
    1581         [ -  + ]:         12 :                 if (!egg_symkey_read_mac (algorithm, password, -1, mac_data, &mdh, &mac_len)) {
    1582                 :          0 :                         ret = GCR_ERROR_FAILURE;
    1583                 :          0 :                         goto done;
    1584                 :            :                 }
    1585                 :            : 
    1586                 :            :                 /* If not the right length, then that's really broken */
    1587         [ -  + ]:         12 :                 if (mac_len != n_digest) {
    1588                 :          0 :                         r = GCR_ERROR_FAILURE;
    1589                 :            : 
    1590                 :            :                 } else {
    1591                 :         12 :                         gcry_md_write (mdh, g_bytes_get_data (content, NULL), g_bytes_get_size (content));
    1592                 :         12 :                         mac_digest = gcry_md_read (mdh, 0);
    1593         [ -  + ]:         12 :                         g_return_val_if_fail (mac_digest, GCR_ERROR_FAILURE);
    1594         [ +  + ]:         12 :                         r = memcmp (mac_digest, digest, n_digest) == 0 ? SUCCESS : GCR_ERROR_LOCKED;
    1595                 :            :                 }
    1596                 :            : 
    1597                 :         12 :                 gcry_md_close (mdh);
    1598                 :         12 :                 mdh = NULL;
    1599                 :            : 
    1600         [ +  + ]:         12 :                 if (r != GCR_ERROR_LOCKED) {
    1601                 :          4 :                         ret = r;
    1602                 :          4 :                         break;
    1603                 :            :                 }
    1604                 :            :         }
    1605                 :            : 
    1606                 :          4 : done:
    1607         [ -  + ]:          4 :         if (mdh)
    1608                 :          0 :                 gcry_md_close (mdh);
    1609                 :          4 :         g_free (digest);
    1610                 :          4 :         return ret;
    1611                 :            : 
    1612                 :            : }
    1613                 :            : 
    1614                 :            : static gint
    1615                 :         47 : parse_der_pkcs12 (GcrParser *self,
    1616                 :            :                   GBytes *data)
    1617                 :            : {
    1618                 :         47 :         GNode *asn = NULL;
    1619                 :            :         gint ret;
    1620                 :         47 :         GNode *content = NULL;
    1621                 :         47 :         GBytes *string = NULL;
    1622                 :            :         GQuark oid;
    1623                 :            :         GcrParsed *parsed;
    1624                 :            : 
    1625                 :         47 :         parsed = push_parsed (self, FALSE);
    1626                 :         47 :         ret = GCR_ERROR_UNRECOGNIZED;
    1627                 :            : 
    1628                 :            :         /*
    1629                 :            :          * Because PKCS#12 files, the bags specifically, are notorious for
    1630                 :            :          * being crappily constructed and are often break rules such as DER
    1631                 :            :          * sorting order etc.. we parse the DER in a non-strict fashion.
    1632                 :            :          *
    1633                 :            :          * The rules in DER are designed for X.509 certificates, so there is
    1634                 :            :          * only one way to represent a given certificate (although they fail
    1635                 :            :          * at that as well). But with PKCS#12 we don't have such high
    1636                 :            :          * requirements, and we can slack off on our validation.
    1637                 :            :          */
    1638                 :            : 
    1639                 :         47 :         asn = egg_asn1x_create_and_decode_full (pkix_asn1_tab, "pkcs-12-PFX",
    1640                 :            :                                                 data, EGG_ASN1X_NO_STRICT);
    1641         [ +  + ]:         47 :         if (!asn)
    1642                 :         43 :                 goto done;
    1643                 :            : 
    1644                 :          4 :         parsing_block (parsed, GCR_FORMAT_DER_PKCS12, data);
    1645                 :            : 
    1646                 :          4 :         oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "authSafe", "contentType", NULL));
    1647         [ -  + ]:          4 :         if (!oid)
    1648                 :          0 :                 goto done;
    1649                 :            : 
    1650                 :            :         /* Outer most one must just be plain data */
    1651         [ -  + ]:          4 :         if (oid != GCR_OID_PKCS7_DATA) {
    1652                 :          0 :                 g_message ("unsupported safe content type in pkcs12: %s", g_quark_to_string (oid));
    1653                 :          0 :                 goto done;
    1654                 :            :         }
    1655                 :            : 
    1656                 :          4 :         content = egg_asn1x_get_any_as (egg_asn1x_node (asn, "authSafe", "content", NULL),
    1657                 :            :                                         pkix_asn1_tab, "pkcs-7-Data");
    1658         [ -  + ]:          4 :         if (!content)
    1659                 :          0 :                 goto done;
    1660                 :            : 
    1661                 :          4 :         string = egg_asn1x_get_string_as_bytes (content);
    1662         [ -  + ]:          4 :         if (!string)
    1663                 :          0 :                 goto done;
    1664                 :            : 
    1665                 :          4 :         ret = verify_pkcs12_safe (self, asn, string);
    1666         [ -  + ]:          4 :         if (ret == SUCCESS)
    1667                 :          4 :                 ret = handle_pkcs12_safe (self, string);
    1668                 :            : 
    1669                 :          0 : done:
    1670         [ +  + ]:         47 :         if (content)
    1671                 :          4 :                 egg_asn1x_destroy (content);
    1672         [ +  + ]:         47 :         if (string)
    1673                 :          4 :                 g_bytes_unref (string);
    1674                 :         47 :         egg_asn1x_destroy (asn);
    1675                 :         47 :         pop_parsed (self, parsed);
    1676                 :         47 :         return ret;
    1677                 :            : }
    1678                 :            : 
    1679                 :            : /* -----------------------------------------------------------------------------
    1680                 :            :  * CERTIFICATE REQUESTS
    1681                 :            :  */
    1682                 :            : 
    1683                 :            : static gint
    1684                 :         49 : parse_der_pkcs10 (GcrParser *self,
    1685                 :            :                   GBytes *data)
    1686                 :            : {
    1687                 :         49 :         GNode *asn = NULL;
    1688                 :            :         GNode *node;
    1689                 :            :         GcrParsed *parsed;
    1690                 :         49 :         gchar *name = NULL;
    1691                 :            : 
    1692                 :         49 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-10-CertificationRequest", data);
    1693         [ +  + ]:         49 :         if (!asn)
    1694                 :         37 :                 return GCR_ERROR_UNRECOGNIZED;
    1695                 :            : 
    1696                 :         12 :         parsed = push_parsed (self, FALSE);
    1697                 :         12 :         parsing_block (parsed, GCR_FORMAT_DER_PKCS10, data);
    1698                 :            : 
    1699                 :         12 :         parsing_object (parsed, CKO_GCR_CERTIFICATE_REQUEST);
    1700                 :         12 :         parsed_ulong_attribute (parsed, CKA_GCR_CERTIFICATE_REQUEST_TYPE, CKQ_GCR_PKCS10);
    1701                 :            : 
    1702                 :         12 :         node = egg_asn1x_node (asn, "certificationRequestInfo", NULL);
    1703         [ -  + ]:         12 :         g_return_val_if_fail (node != NULL, GCR_ERROR_FAILURE);
    1704                 :            : 
    1705         [ +  - ]:         12 :         if (gcr_parser_get_parsed_label (self) == NULL)
    1706                 :         12 :                 name = egg_dn_read_part (egg_asn1x_node (node, "subject", "rdnSequence", NULL), "CN");
    1707                 :            : 
    1708         [ +  - ]:         12 :         if (name != NULL) {
    1709                 :         12 :                 parsed_label (parsed, name);
    1710                 :         12 :                 g_free (name);
    1711                 :            :         }
    1712                 :            : 
    1713                 :         12 :         parsed_attribute_bytes (parsed, CKA_VALUE, data);
    1714                 :         12 :         parsed_asn1_element (parsed, node, "subject", CKA_SUBJECT);
    1715                 :         12 :         parsed_fire (self, parsed);
    1716                 :            : 
    1717                 :         12 :         egg_asn1x_destroy (asn);
    1718                 :            : 
    1719                 :         12 :         pop_parsed (self, parsed);
    1720                 :         12 :         return SUCCESS;
    1721                 :            : }
    1722                 :            : 
    1723                 :            : static gint
    1724                 :         40 : parse_der_spkac (GcrParser *self,
    1725                 :            :                  GBytes *data)
    1726                 :            : {
    1727                 :         40 :         GNode *asn = NULL;
    1728                 :            :         GcrParsed *parsed;
    1729                 :            : 
    1730                 :         40 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SignedPublicKeyAndChallenge", data);
    1731         [ +  + ]:         40 :         if (!asn)
    1732                 :         36 :                 return GCR_ERROR_UNRECOGNIZED;
    1733                 :            : 
    1734                 :          4 :         parsed = push_parsed (self, FALSE);
    1735                 :          4 :         parsing_block (parsed, GCR_FORMAT_DER_SPKAC, data);
    1736                 :            : 
    1737                 :          4 :         parsing_object (parsed, CKO_GCR_CERTIFICATE_REQUEST);
    1738                 :          4 :         parsed_ulong_attribute (parsed, CKA_GCR_CERTIFICATE_REQUEST_TYPE, CKQ_GCR_SPKAC);
    1739                 :            : 
    1740                 :          4 :         parsed_attribute_bytes (parsed, CKA_VALUE, data);
    1741                 :          4 :         parsed_fire (self, parsed);
    1742                 :            : 
    1743                 :          4 :         egg_asn1x_destroy (asn);
    1744                 :            : 
    1745                 :          4 :         pop_parsed (self, parsed);
    1746                 :          4 :         return SUCCESS;
    1747                 :            : }
    1748                 :            : 
    1749                 :            : static gint
    1750                 :         81 : parse_base64_spkac (GcrParser *self,
    1751                 :            :                     GBytes *dat)
    1752                 :            : {
    1753                 :         81 :         const gchar *PREFIX = "SPKAC=";
    1754                 :         81 :         const gsize PREFIX_LEN = 6;
    1755                 :            : 
    1756                 :            :         GcrParsed *parsed;
    1757                 :            :         guchar *spkac;
    1758                 :            :         gsize n_spkac;
    1759                 :            :         const guchar *data;
    1760                 :            :         GBytes *bytes;
    1761                 :            :         gsize n_data;
    1762                 :            :         gint ret;
    1763                 :         81 :         data = g_bytes_get_data (dat, &n_data);
    1764                 :            : 
    1765   [ +  -  +  + ]:         81 :         if (n_data > PREFIX_LEN && memcmp (PREFIX, data, PREFIX_LEN))
    1766                 :         80 :                 return GCR_ERROR_UNRECOGNIZED;
    1767                 :            : 
    1768                 :          1 :         parsed = push_parsed (self, FALSE);
    1769                 :          1 :         parsing_block (parsed, GCR_FORMAT_DER_SPKAC, dat);
    1770                 :            : 
    1771                 :          1 :         data += PREFIX_LEN;
    1772                 :          1 :         n_data -= PREFIX_LEN;
    1773                 :            : 
    1774                 :          1 :         spkac = g_base64_decode ((const gchar *)data, &n_spkac);
    1775         [ +  - ]:          1 :         if (spkac != NULL) {
    1776                 :          1 :                 bytes = g_bytes_new_take (spkac, n_spkac);
    1777                 :          1 :                 ret = parse_der_spkac (self, bytes);
    1778                 :          1 :                 g_bytes_unref (bytes);
    1779                 :            :         } else {
    1780                 :          0 :                 ret = GCR_ERROR_FAILURE;
    1781                 :            :         }
    1782                 :            : 
    1783                 :          1 :         pop_parsed (self, parsed);
    1784                 :          1 :         return ret;
    1785                 :            : }
    1786                 :            : 
    1787                 :            : /* -----------------------------------------------------------------------------
    1788                 :            :  * OPENPGP
    1789                 :            :  */
    1790                 :            : 
    1791                 :            : static void
    1792                 :         26 : on_openpgp_packet (GPtrArray *records,
    1793                 :            :                    GBytes *outer,
    1794                 :            :                    gpointer user_data)
    1795                 :            : {
    1796                 :         26 :         GcrParser *self = GCR_PARSER (user_data);
    1797                 :            :         GcrParsed *parsed;
    1798                 :            :         gchar *string;
    1799                 :            : 
    1800                 :            :         /*
    1801                 :            :          * If it's an openpgp packet that doesn't contain a key, then
    1802                 :            :          * just ignore it here.
    1803                 :            :          */
    1804         [ -  + ]:         26 :         if (records->len == 0)
    1805                 :          0 :                 return;
    1806                 :            : 
    1807                 :         26 :         parsed = push_parsed (self, FALSE);
    1808                 :            : 
    1809                 :            :         /* All we can do is the packet bounds */
    1810                 :         26 :         parsing_block (parsed, GCR_FORMAT_OPENPGP_PACKET, outer);
    1811                 :         26 :         parsing_object (parsed, CKO_GCR_GNUPG_RECORDS);
    1812                 :         26 :         string = _gcr_records_format (records);
    1813                 :         26 :         parsed_attribute (parsed, CKA_VALUE, string, strlen (string));
    1814                 :         26 :         parsed_fire (self, parsed);
    1815                 :         26 :         pop_parsed (self, parsed);
    1816                 :            : 
    1817                 :         26 :         g_free (string);
    1818                 :            : }
    1819                 :            : 
    1820                 :            : static gint
    1821                 :         56 : parse_openpgp_packets (GcrParser *self,
    1822                 :            :                        GBytes *data)
    1823                 :            : {
    1824                 :            :         gint num_parsed;
    1825                 :            : 
    1826                 :         56 :         num_parsed = _gcr_openpgp_parse (data,
    1827                 :            :                                          GCR_OPENPGP_PARSE_KEYS |
    1828                 :            :                                          GCR_OPENPGP_PARSE_ATTRIBUTES |
    1829                 :            :                                          GCR_OPENPGP_PARSE_SIGNATURES,
    1830                 :            :                                          on_openpgp_packet, self);
    1831                 :            : 
    1832         [ +  + ]:         56 :         if (num_parsed == 0)
    1833                 :         40 :                 return GCR_ERROR_UNRECOGNIZED;
    1834                 :         16 :         return SUCCESS;
    1835                 :            : }
    1836                 :            : 
    1837                 :            : /* -----------------------------------------------------------------------------
    1838                 :            :  * ARMOR PARSING
    1839                 :            :  */
    1840                 :            : 
    1841                 :            : static gboolean
    1842                 :        202 : formats_for_armor_type (GQuark armor_type,
    1843                 :            :                         gint *inner_format,
    1844                 :            :                         gint *outer_format)
    1845                 :            : {
    1846                 :            :         gint dummy;
    1847         [ -  + ]:        202 :         if (!inner_format)
    1848                 :          0 :                 inner_format = &dummy;
    1849         [ -  + ]:        202 :         if (!outer_format)
    1850                 :          0 :                 outer_format = &dummy;
    1851                 :            : 
    1852         [ +  + ]:        202 :         if (armor_type == PEM_RSA_PRIVATE_KEY) {
    1853                 :         39 :                 *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_RSA;
    1854                 :         39 :                 *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_RSA;
    1855         [ +  + ]:        163 :         } else if (armor_type == PEM_DSA_PRIVATE_KEY) {
    1856                 :         39 :                 *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_DSA;
    1857                 :         39 :                 *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_DSA;
    1858         [ +  + ]:        124 :         } else if (armor_type == PEM_EC_PRIVATE_KEY) {
    1859                 :          1 :                 *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_EC;
    1860                 :          1 :                 *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_EC;
    1861         [ -  + ]:        123 :         } else if (armor_type == PEM_ANY_PRIVATE_KEY) {
    1862                 :          0 :                 *inner_format = GCR_FORMAT_DER_PRIVATE_KEY;
    1863                 :          0 :                 *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY;
    1864         [ -  + ]:        123 :         } else if (armor_type == PEM_PRIVATE_KEY) {
    1865                 :          0 :                 *inner_format = GCR_FORMAT_DER_PKCS8_PLAIN;
    1866                 :          0 :                 *outer_format = GCR_FORMAT_PEM_PKCS8_PLAIN;
    1867         [ +  + ]:        123 :         } else if (armor_type == PEM_ENCRYPTED_PRIVATE_KEY) {
    1868                 :          1 :                 *inner_format = GCR_FORMAT_DER_PKCS8_ENCRYPTED;
    1869                 :          1 :                 *outer_format = GCR_FORMAT_PEM_PKCS8_ENCRYPTED;
    1870         [ +  + ]:        122 :         } else if (armor_type == PEM_CERTIFICATE) {
    1871                 :        117 :                 *inner_format = GCR_FORMAT_DER_CERTIFICATE_X509;
    1872                 :        117 :                 *outer_format = GCR_FORMAT_PEM_CERTIFICATE_X509;
    1873         [ -  + ]:          5 :         } else if (armor_type == PEM_PKCS7) {
    1874                 :          0 :                 *inner_format = GCR_FORMAT_DER_PKCS7;
    1875                 :          0 :                 *outer_format = GCR_FORMAT_PEM_PKCS7;
    1876         [ +  + ]:          5 :         } else if (armor_type == PEM_CERTIFICATE_REQUEST) {
    1877                 :          2 :                 *inner_format = GCR_FORMAT_DER_PKCS10;
    1878                 :          2 :                 *outer_format = GCR_FORMAT_PEM_PKCS10;
    1879         [ +  + ]:          3 :         } else if (armor_type == PEM_NEW_CERTIFICATE_REQUEST) {
    1880                 :          1 :                 *inner_format = GCR_FORMAT_DER_PKCS10;
    1881                 :          1 :                 *outer_format = GCR_FORMAT_PEM_PKCS10;
    1882         [ -  + ]:          2 :         } else if (armor_type == PEM_PKCS12) {
    1883                 :          0 :                 *inner_format = GCR_FORMAT_DER_PKCS12;
    1884                 :          0 :                 *outer_format = GCR_FORMAT_PEM_PKCS12;
    1885         [ +  + ]:          2 :         } else if (armor_type == PEM_PUBLIC_KEY) {
    1886                 :          1 :                 *inner_format = GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY;
    1887                 :          1 :                 *outer_format = GCR_FORMAT_PEM_PUBLIC_KEY;
    1888         [ -  + ]:          1 :         } else if (armor_type == ARMOR_PGP_PRIVATE_KEY_BLOCK) {
    1889                 :          0 :                 *inner_format = GCR_FORMAT_OPENPGP_PACKET;
    1890                 :          0 :                 *outer_format = GCR_FORMAT_OPENPGP_ARMOR;
    1891         [ +  - ]:          1 :         } else if (armor_type == ARMOR_PGP_PUBLIC_KEY_BLOCK) {
    1892                 :          1 :                 *inner_format = GCR_FORMAT_OPENPGP_PACKET;
    1893                 :          1 :                 *outer_format = GCR_FORMAT_OPENPGP_ARMOR;
    1894                 :            :         } else {
    1895                 :          0 :                 return FALSE;
    1896                 :            :         }
    1897                 :            : 
    1898                 :        202 :         return TRUE;
    1899                 :            : }
    1900                 :            : 
    1901                 :            : static gint
    1902                 :        204 : handle_plain_pem (GcrParser *self,
    1903                 :            :                   gint format_id,
    1904                 :            :                   gint want_format,
    1905                 :            :                   GBytes *data)
    1906                 :            : {
    1907                 :            :         ParserFormat *format;
    1908                 :            : 
    1909   [ +  +  +  - ]:        204 :         if (want_format != 0 && want_format != format_id)
    1910                 :         36 :                 return GCR_ERROR_UNRECOGNIZED;
    1911                 :            : 
    1912                 :        168 :         format = parser_format_lookup (format_id);
    1913         [ -  + ]:        168 :         if (format == NULL)
    1914                 :          0 :                 return GCR_ERROR_UNRECOGNIZED;
    1915                 :            : 
    1916                 :        168 :         return (format->function) (self, data);
    1917                 :            : }
    1918                 :            : 
    1919                 :            : static gint
    1920                 :          1 : handle_encrypted_pem (GcrParser *self,
    1921                 :            :                       gint format_id,
    1922                 :            :                       gint want_format,
    1923                 :            :                       GHashTable *headers,
    1924                 :            :                       GBytes *data)
    1925                 :            : {
    1926                 :          1 :         PasswordState pstate = PASSWORD_STATE_INIT;
    1927                 :            :         const gchar *password;
    1928                 :            :         guchar *decrypted;
    1929                 :            :         gsize n_decrypted;
    1930                 :            :         const gchar *val;
    1931                 :            :         GBytes *dbytes;
    1932                 :            :         gint res;
    1933                 :            :         gint l;
    1934                 :            : 
    1935   [ -  +  +  -  :          1 :         g_assert (GCR_IS_PARSER (self));
             +  -  -  + ]
    1936         [ -  + ]:          1 :         g_assert (headers);
    1937                 :            : 
    1938                 :          1 :         val = g_hash_table_lookup (headers, "DEK-Info");
    1939         [ -  + ]:          1 :         if (!val) {
    1940                 :          0 :                 g_message ("missing encryption header");
    1941                 :          0 :                 return GCR_ERROR_FAILURE;
    1942                 :            :         }
    1943                 :            : 
    1944                 :            :         for (;;) {
    1945                 :            : 
    1946                 :          3 :                 res = enum_next_password (self, &pstate, &password);
    1947         [ -  + ]:          3 :                 if (res != SUCCESS)
    1948                 :          0 :                         break;
    1949                 :            : 
    1950                 :            :                 /* Decrypt, this will result in garble if invalid password */
    1951                 :          3 :                 decrypted = egg_openssl_decrypt_block (val, password, -1, data, &n_decrypted);
    1952         [ -  + ]:          3 :                 if (!decrypted) {
    1953                 :          0 :                         res = GCR_ERROR_FAILURE;
    1954                 :          0 :                         break;
    1955                 :            :                 }
    1956                 :            : 
    1957                 :            :                 /* Unpad the DER data */
    1958                 :          3 :                 l = egg_asn1x_element_length (decrypted, n_decrypted);
    1959         [ +  + ]:          3 :                 if (l > 0)
    1960                 :          1 :                         n_decrypted = l;
    1961                 :            : 
    1962                 :          3 :                 dbytes = g_bytes_new_with_free_func (decrypted, n_decrypted,
    1963                 :            :                                                        egg_secure_free, decrypted);
    1964                 :          3 :                 decrypted = NULL;
    1965                 :            : 
    1966                 :            :                 /* Try to parse */
    1967                 :          3 :                 res = handle_plain_pem (self, format_id, want_format, dbytes);
    1968                 :          3 :                 g_bytes_unref (dbytes);
    1969                 :            : 
    1970                 :            :                 /* Unrecognized is a bad password */
    1971         [ +  + ]:          3 :                 if (res != GCR_ERROR_UNRECOGNIZED)
    1972                 :          1 :                         break;
    1973                 :            :         }
    1974                 :            : 
    1975                 :          1 :         return res;
    1976                 :            : }
    1977                 :            : 
    1978                 :            : typedef struct {
    1979                 :            :         GcrParser *parser;
    1980                 :            :         gint result;
    1981                 :            :         gint want_format;
    1982                 :            : } HandlePemArgs;
    1983                 :            : 
    1984                 :            : static void
    1985                 :        202 : handle_pem_data (GQuark type,
    1986                 :            :                  GBytes *data,
    1987                 :            :                  GBytes *outer,
    1988                 :            :                  GHashTable *headers,
    1989                 :            :                  gpointer user_data)
    1990                 :            : {
    1991                 :        202 :         HandlePemArgs *args = (HandlePemArgs*)user_data;
    1992                 :        202 :         gint res = GCR_ERROR_FAILURE;
    1993                 :        202 :         gboolean encrypted = FALSE;
    1994                 :            :         const gchar *val;
    1995                 :            :         gint inner_format;
    1996                 :            :         gint outer_format;
    1997                 :            :         GcrParsed *parsed;
    1998                 :            : 
    1999                 :            :         /* Something already failed to parse */
    2000         [ -  + ]:        202 :         if (args->result == GCR_ERROR_FAILURE)
    2001                 :          0 :                 return;
    2002                 :            : 
    2003         [ -  + ]:        202 :         if (!formats_for_armor_type (type, &inner_format, &outer_format))
    2004                 :          0 :                 return;
    2005                 :            : 
    2006                 :        202 :         parsed = push_parsed (args->parser, FALSE);
    2007                 :            : 
    2008                 :            :         /* Fill in information necessary for prompting */
    2009                 :        202 :         parsing_block (parsed, outer_format, outer);
    2010                 :            : 
    2011                 :            :         /* See if it's encrypted PEM all openssl like*/
    2012         [ +  + ]:        202 :         if (headers) {
    2013                 :          2 :                 val = g_hash_table_lookup (headers, "Proc-Type");
    2014   [ +  +  +  - ]:          2 :                 if (val && strcmp (val, "4,ENCRYPTED") == 0)
    2015                 :          1 :                         encrypted = TRUE;
    2016                 :            :         }
    2017                 :            : 
    2018         [ +  + ]:        202 :         if (encrypted)
    2019                 :          1 :                 res = handle_encrypted_pem (args->parser, inner_format,
    2020                 :            :                                             args->want_format, headers,
    2021                 :            :                                             data);
    2022                 :            :         else
    2023                 :        201 :                 res = handle_plain_pem (args->parser, inner_format,
    2024                 :            :                                         args->want_format, data);
    2025                 :            : 
    2026                 :        202 :         pop_parsed (args->parser, parsed);
    2027                 :            : 
    2028         [ +  + ]:        202 :         if (res != GCR_ERROR_UNRECOGNIZED) {
    2029         [ +  + ]:        166 :                 if (args->result == GCR_ERROR_UNRECOGNIZED)
    2030                 :         67 :                         args->result = res;
    2031         [ -  + ]:         99 :                 else if (res > args->result)
    2032                 :          0 :                         args->result = res;
    2033                 :            :         }
    2034                 :            : }
    2035                 :            : 
    2036                 :            : static gint
    2037                 :        152 : handle_pem_format (GcrParser *self,
    2038                 :            :                    gint subformat,
    2039                 :            :                    GBytes *data)
    2040                 :            : {
    2041                 :        152 :         HandlePemArgs ctx = { self, GCR_ERROR_UNRECOGNIZED, subformat };
    2042                 :            :         guint found;
    2043                 :            : 
    2044         [ -  + ]:        152 :         if (g_bytes_get_size (data) == 0)
    2045                 :          0 :                 return GCR_ERROR_UNRECOGNIZED;
    2046                 :            : 
    2047                 :        152 :         found = egg_armor_parse (data, handle_pem_data, &ctx);
    2048                 :            : 
    2049         [ +  + ]:        152 :         if (found == 0)
    2050                 :         49 :                 return GCR_ERROR_UNRECOGNIZED;
    2051                 :            : 
    2052                 :        103 :         return ctx.result;
    2053                 :            : }
    2054                 :            : 
    2055                 :            : 
    2056                 :            : static gint
    2057                 :        112 : parse_pem (GcrParser *self,
    2058                 :            :            GBytes *data)
    2059                 :            : {
    2060                 :        112 :         return handle_pem_format (self, 0, data);
    2061                 :            : }
    2062                 :            : 
    2063                 :            : static gint
    2064                 :          0 : parse_pem_private_key_rsa (GcrParser *self,
    2065                 :            :                            GBytes *data)
    2066                 :            : {
    2067                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data);
    2068                 :            : }
    2069                 :            : 
    2070                 :            : static gint
    2071                 :          0 : parse_pem_private_key_dsa (GcrParser *self,
    2072                 :            :                            GBytes *data)
    2073                 :            : {
    2074                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data);
    2075                 :            : }
    2076                 :            : 
    2077                 :            : static gint
    2078                 :          0 : parse_pem_private_key_ec (GcrParser *self,
    2079                 :            :                           GBytes *data)
    2080                 :            : {
    2081                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_EC, data);
    2082                 :            : }
    2083                 :            : 
    2084                 :            : static gint
    2085                 :          0 : parse_pem_public_key (GcrParser *self,
    2086                 :            :                       GBytes *data)
    2087                 :            : {
    2088                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, data);
    2089                 :            : }
    2090                 :            : 
    2091                 :            : static gint
    2092                 :          0 : parse_pem_certificate (GcrParser *self,
    2093                 :            :                        GBytes *data)
    2094                 :            : {
    2095                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_CERTIFICATE_X509, data);
    2096                 :            : }
    2097                 :            : 
    2098                 :            : static gint
    2099                 :          0 : parse_pem_pkcs8_plain (GcrParser *self,
    2100                 :            :                        GBytes *data)
    2101                 :            : {
    2102                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_PKCS8_PLAIN, data);
    2103                 :            : }
    2104                 :            : 
    2105                 :            : static gint
    2106                 :          0 : parse_pem_pkcs8_encrypted (GcrParser *self,
    2107                 :            :                            GBytes *data)
    2108                 :            : {
    2109                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data);
    2110                 :            : }
    2111                 :            : 
    2112                 :            : static gint
    2113                 :          0 : parse_pem_pkcs7 (GcrParser *self,
    2114                 :            :                  GBytes *data)
    2115                 :            : {
    2116                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_PKCS7, data);
    2117                 :            : }
    2118                 :            : 
    2119                 :            : static gint
    2120                 :          0 : parse_pem_pkcs10 (GcrParser *self,
    2121                 :            :                   GBytes *data)
    2122                 :            : {
    2123                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_PKCS10, data);
    2124                 :            : }
    2125                 :            : 
    2126                 :            : static gint
    2127                 :          0 : parse_pem_pkcs12 (GcrParser *self,
    2128                 :            :                   GBytes *data)
    2129                 :            : {
    2130                 :          0 :         return handle_pem_format (self, GCR_FORMAT_DER_PKCS12, data);
    2131                 :            : }
    2132                 :            : 
    2133                 :            : static gint
    2134                 :         40 : parse_openpgp_armor (GcrParser *self,
    2135                 :            :                      GBytes *data)
    2136                 :            : {
    2137                 :         40 :         return handle_pem_format (self, GCR_FORMAT_OPENPGP_PACKET, data);
    2138                 :            : }
    2139                 :            : 
    2140                 :            : /* -----------------------------------------------------------------------------
    2141                 :            :  * OPENSSH
    2142                 :            :  */
    2143                 :            : 
    2144                 :            : static void
    2145                 :          4 : on_openssh_public_key_parsed (GckAttributes *attrs,
    2146                 :            :                               const gchar *label,
    2147                 :            :                               const gchar *options,
    2148                 :            :                               GBytes *outer,
    2149                 :            :                               gpointer user_data)
    2150                 :            : {
    2151                 :          4 :         GcrParser *self = GCR_PARSER (user_data);
    2152                 :            :         GcrParsed *parsed;
    2153                 :            : 
    2154                 :          4 :         parsed = push_parsed (self, FALSE);
    2155                 :          4 :         parsing_block (parsed, GCR_FORMAT_OPENSSH_PUBLIC, outer);
    2156                 :          4 :         parsed_attributes (parsed, attrs);
    2157                 :          4 :         parsed_label (parsed, label);
    2158                 :          4 :         parsed_fire (self, parsed);
    2159                 :          4 :         pop_parsed (self, parsed);
    2160                 :          4 : }
    2161                 :            : 
    2162                 :            : static gint
    2163                 :         45 : parse_openssh_public (GcrParser *self,
    2164                 :            :                       GBytes *data)
    2165                 :            : {
    2166                 :            :         guint num_parsed;
    2167                 :            : 
    2168                 :         45 :         num_parsed = _gcr_openssh_pub_parse (data, on_openssh_public_key_parsed, self);
    2169                 :            : 
    2170         [ +  + ]:         45 :         if (num_parsed == 0)
    2171                 :         42 :                 return GCR_ERROR_UNRECOGNIZED;
    2172                 :          3 :         return SUCCESS;
    2173                 :            : }
    2174                 :            : 
    2175                 :            : /* -----------------------------------------------------------------------------
    2176                 :            :  * FORMATS
    2177                 :            :  */
    2178                 :            : 
    2179                 :            : /**
    2180                 :            :  * GcrDataFormat:
    2181                 :            :  * @GCR_FORMAT_ALL: Represents all the formats, when enabling or disabling
    2182                 :            :  * @GCR_FORMAT_INVALID: Not a valid format
    2183                 :            :  * @GCR_FORMAT_DER_PRIVATE_KEY: DER encoded private key
    2184                 :            :  * @GCR_FORMAT_DER_PRIVATE_KEY_RSA: DER encoded RSA private key
    2185                 :            :  * @GCR_FORMAT_DER_PRIVATE_KEY_DSA: DER encoded DSA private key
    2186                 :            :  * @GCR_FORMAT_DER_PRIVATE_KEY_EC: DER encoded EC private key
    2187                 :            :  * @GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY: DER encoded SubjectPublicKeyInfo
    2188                 :            :  * @GCR_FORMAT_DER_CERTIFICATE_X509: DER encoded X.509 certificate
    2189                 :            :  * @GCR_FORMAT_DER_PKCS7: DER encoded PKCS#7 container file which can contain certificates
    2190                 :            :  * @GCR_FORMAT_DER_PKCS8: DER encoded PKCS#8 file which can contain a key
    2191                 :            :  * @GCR_FORMAT_DER_PKCS8_PLAIN: Unencrypted DER encoded PKCS#8 file which can contain a key
    2192                 :            :  * @GCR_FORMAT_DER_PKCS8_ENCRYPTED: Encrypted DER encoded PKCS#8 file which can contain a key
    2193                 :            :  * @GCR_FORMAT_DER_PKCS10: DER encoded PKCS#10 certificate request file
    2194                 :            :  * @GCR_FORMAT_DER_PKCS12: DER encoded PKCS#12 file which can contain certificates and/or keys
    2195                 :            :  * @GCR_FORMAT_OPENSSH_PUBLIC: OpenSSH v1 or v2 public key
    2196                 :            :  * @GCR_FORMAT_OPENPGP_PACKET: OpenPGP key packet(s)
    2197                 :            :  * @GCR_FORMAT_OPENPGP_ARMOR: OpenPGP public or private key armor encoded data
    2198                 :            :  * @GCR_FORMAT_PEM: An OpenSSL style PEM file with unspecified contents
    2199                 :            :  * @GCR_FORMAT_PEM_PRIVATE_KEY: An OpenSSL style PEM file with a private key
    2200                 :            :  * @GCR_FORMAT_PEM_PRIVATE_KEY_RSA: An OpenSSL style PEM file with a private RSA key
    2201                 :            :  * @GCR_FORMAT_PEM_PRIVATE_KEY_DSA: An OpenSSL style PEM file with a private DSA key
    2202                 :            :  * @GCR_FORMAT_PEM_PRIVATE_KEY_EC: An OpenSSL style PEM file with a private EC key
    2203                 :            :  * @GCR_FORMAT_PEM_CERTIFICATE_X509: An OpenSSL style PEM file with an X.509 certificate
    2204                 :            :  * @GCR_FORMAT_PEM_PKCS7: An OpenSSL style PEM file containing PKCS#7
    2205                 :            :  * @GCR_FORMAT_PEM_PKCS8_PLAIN: Unencrypted OpenSSL style PEM file containing PKCS#8
    2206                 :            :  * @GCR_FORMAT_PEM_PKCS8_ENCRYPTED: Encrypted OpenSSL style PEM file containing PKCS#8
    2207                 :            :  * @GCR_FORMAT_PEM_PKCS10: An OpenSSL style PEM file containing PKCS#10
    2208                 :            :  * @GCR_FORMAT_PEM_PKCS12: An OpenSSL style PEM file containing PKCS#12
    2209                 :            :  * @GCR_FORMAT_PEM_PUBLIC_KEY: An OpenSSL style PEM file containing a SubjectPublicKeyInfo
    2210                 :            :  * @GCR_FORMAT_DER_SPKAC: DER encoded SPKAC as generated by HTML5 keygen element
    2211                 :            :  * @GCR_FORMAT_BASE64_SPKAC: OpenSSL style SPKAC data
    2212                 :            :  *
    2213                 :            :  * The various format identifiers.
    2214                 :            :  */
    2215                 :            : 
    2216                 :            : /*
    2217                 :            :  * In order of parsing when no formats specified. We put formats earlier
    2218                 :            :  * if the parser can quickly detect whether GCR_ERROR_UNRECOGNIZED or not
    2219                 :            :  */
    2220                 :            : 
    2221                 :            : static const ParserFormat parser_normal[] = {
    2222                 :            :         { GCR_FORMAT_PEM, parse_pem },
    2223                 :            :         { GCR_FORMAT_BASE64_SPKAC, parse_base64_spkac },
    2224                 :            :         { GCR_FORMAT_DER_PRIVATE_KEY_RSA, parse_der_private_key_rsa },
    2225                 :            :         { GCR_FORMAT_DER_PRIVATE_KEY_DSA, parse_der_private_key_dsa },
    2226                 :            :         { GCR_FORMAT_DER_PRIVATE_KEY_EC, parse_der_private_key_ec },
    2227                 :            :         { GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, parse_der_subject_public_key },
    2228                 :            :         { GCR_FORMAT_DER_CERTIFICATE_X509, parse_der_certificate },
    2229                 :            :         { GCR_FORMAT_DER_PKCS7, parse_der_pkcs7 },
    2230                 :            :         { GCR_FORMAT_DER_PKCS8_PLAIN, parse_der_pkcs8_plain },
    2231                 :            :         { GCR_FORMAT_DER_PKCS8_ENCRYPTED, parse_der_pkcs8_encrypted },
    2232                 :            :         { GCR_FORMAT_DER_PKCS12, parse_der_pkcs12 },
    2233                 :            :         { GCR_FORMAT_OPENSSH_PUBLIC, parse_openssh_public },
    2234                 :            :         { GCR_FORMAT_OPENPGP_PACKET, parse_openpgp_packets },
    2235                 :            :         { GCR_FORMAT_OPENPGP_ARMOR, parse_openpgp_armor },
    2236                 :            :         { GCR_FORMAT_DER_PKCS10, parse_der_pkcs10 },
    2237                 :            :         { GCR_FORMAT_DER_SPKAC, parse_der_spkac },
    2238                 :            : };
    2239                 :            : 
    2240                 :            : /* Must be in format_id numeric order */
    2241                 :            : static const ParserFormat parser_formats[] = {
    2242                 :            :         { GCR_FORMAT_DER_PRIVATE_KEY, parse_der_private_key },
    2243                 :            :         { GCR_FORMAT_DER_PRIVATE_KEY_RSA, parse_der_private_key_rsa },
    2244                 :            :         { GCR_FORMAT_DER_PRIVATE_KEY_DSA, parse_der_private_key_dsa },
    2245                 :            :         { GCR_FORMAT_DER_PRIVATE_KEY_EC, parse_der_private_key_ec },
    2246                 :            :         { GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, parse_der_subject_public_key },
    2247                 :            :         { GCR_FORMAT_DER_CERTIFICATE_X509, parse_der_certificate },
    2248                 :            :         { GCR_FORMAT_DER_PKCS7, parse_der_pkcs7 },
    2249                 :            :         { GCR_FORMAT_DER_PKCS8, parse_der_pkcs8 },
    2250                 :            :         { GCR_FORMAT_DER_PKCS8_PLAIN, parse_der_pkcs8_plain },
    2251                 :            :         { GCR_FORMAT_DER_PKCS8_ENCRYPTED, parse_der_pkcs8_encrypted },
    2252                 :            :         { GCR_FORMAT_DER_PKCS10, parse_der_pkcs10 },
    2253                 :            :         { GCR_FORMAT_DER_SPKAC, parse_der_spkac },
    2254                 :            :         { GCR_FORMAT_BASE64_SPKAC, parse_base64_spkac },
    2255                 :            :         { GCR_FORMAT_DER_PKCS12, parse_der_pkcs12 },
    2256                 :            :         { GCR_FORMAT_OPENSSH_PUBLIC, parse_openssh_public },
    2257                 :            :         { GCR_FORMAT_OPENPGP_PACKET, parse_openpgp_packets },
    2258                 :            :         { GCR_FORMAT_OPENPGP_ARMOR, parse_openpgp_armor },
    2259                 :            :         { GCR_FORMAT_PEM, parse_pem },
    2260                 :            :         { GCR_FORMAT_PEM_PRIVATE_KEY_RSA, parse_pem_private_key_rsa },
    2261                 :            :         { GCR_FORMAT_PEM_PRIVATE_KEY_DSA, parse_pem_private_key_dsa },
    2262                 :            :         { GCR_FORMAT_PEM_CERTIFICATE_X509, parse_pem_certificate },
    2263                 :            :         { GCR_FORMAT_PEM_PKCS7, parse_pem_pkcs7 },
    2264                 :            :         { GCR_FORMAT_PEM_PKCS8_PLAIN, parse_pem_pkcs8_plain },
    2265                 :            :         { GCR_FORMAT_PEM_PKCS8_ENCRYPTED, parse_pem_pkcs8_encrypted },
    2266                 :            :         { GCR_FORMAT_PEM_PKCS12, parse_pem_pkcs12 },
    2267                 :            :         { GCR_FORMAT_PEM_PKCS10, parse_pem_pkcs10 },
    2268                 :            :         { GCR_FORMAT_PEM_PRIVATE_KEY_EC, parse_pem_private_key_ec },
    2269                 :            :         { GCR_FORMAT_PEM_PUBLIC_KEY, parse_pem_public_key },
    2270                 :            : };
    2271                 :            : 
    2272                 :            : static int
    2273                 :       1943 : compar_id_to_parser_format (const void *a, const void *b)
    2274                 :            : {
    2275                 :       1943 :         const gint *format_id = a;
    2276                 :       1943 :         const ParserFormat *format = b;
    2277                 :            : 
    2278         [ -  + ]:       1943 :         g_assert (format_id);
    2279         [ -  + ]:       1943 :         g_assert (format);
    2280                 :            : 
    2281         [ +  + ]:       1943 :         if (format->format_id == *format_id)
    2282                 :        462 :                 return 0;
    2283         [ +  + ]:       1481 :         return (*format_id < format->format_id) ? -1 : 1;
    2284                 :            : }
    2285                 :            : 
    2286                 :            : static ParserFormat*
    2287                 :        462 : parser_format_lookup (gint format_id)
    2288                 :            : {
    2289                 :        462 :         return bsearch (&format_id, parser_formats, G_N_ELEMENTS (parser_formats),
    2290                 :            :                         sizeof (parser_formats[0]), compar_id_to_parser_format);
    2291                 :            : }
    2292                 :            : 
    2293                 :            : static gint
    2294                 :       5886 : compare_pointers (gconstpointer a, gconstpointer b)
    2295                 :            : {
    2296         [ -  + ]:       5886 :         if (a == b)
    2297                 :          0 :                 return 0;
    2298         [ -  + ]:       5886 :         return a < b ? -1 : 1;
    2299                 :            : }
    2300                 :            : 
    2301                 :            : typedef struct _ForeachArgs {
    2302                 :            :         GcrParser *parser;
    2303                 :            :         GBytes *data;
    2304                 :            :         gint result;
    2305                 :            : } ForeachArgs;
    2306                 :            : 
    2307                 :            : static gboolean
    2308                 :       1382 : parser_format_foreach (gpointer key, gpointer value, gpointer data)
    2309                 :            : {
    2310                 :       1382 :         ForeachArgs *args = data;
    2311                 :       1382 :         ParserFormat *format = key;
    2312                 :            :         gint result;
    2313                 :            : 
    2314         [ -  + ]:       1382 :         g_assert (format);
    2315         [ -  + ]:       1382 :         g_assert (format->function);
    2316   [ -  +  +  -  :       1382 :         g_assert (GCR_IS_PARSER (args->parser));
             +  -  -  + ]
    2317                 :            : 
    2318                 :       1382 :         result = (format->function) (args->parser, args->data);
    2319         [ +  + ]:       1382 :         if (result != GCR_ERROR_UNRECOGNIZED) {
    2320                 :        424 :                 args->result = result;
    2321                 :        424 :                 return TRUE;
    2322                 :            :         }
    2323                 :            : 
    2324                 :            :         /* Keep going */
    2325                 :        958 :         return FALSE;
    2326                 :            : }
    2327                 :            : 
    2328                 :            : /* -----------------------------------------------------------------------------
    2329                 :            :  * OBJECT
    2330                 :            :  */
    2331                 :            : 
    2332                 :            : 
    2333                 :            : static GObject*
    2334                 :        426 : gcr_parser_constructor (GType type, guint n_props, GObjectConstructParam *props)
    2335                 :            : {
    2336                 :        426 :         GcrParser *self = GCR_PARSER (G_OBJECT_CLASS (gcr_parser_parent_class)->constructor(type, n_props, props));
    2337         [ -  + ]:        426 :         g_return_val_if_fail (self, NULL);
    2338                 :            : 
    2339                 :            :         /* Always try to parse with NULL and empty passwords first */
    2340                 :        426 :         gcr_parser_add_password (self, NULL);
    2341                 :        426 :         gcr_parser_add_password (self, "");
    2342                 :            : 
    2343                 :        426 :         return G_OBJECT (self);
    2344                 :            : }
    2345                 :            : 
    2346                 :            : static void
    2347                 :        426 : gcr_parser_init (GcrParser *self)
    2348                 :            : {
    2349                 :        426 :         self->pv = gcr_parser_get_instance_private (self);
    2350                 :        426 :         self->pv->passwords = g_ptr_array_new ();
    2351                 :        426 :         self->pv->normal_formats = TRUE;
    2352                 :        426 : }
    2353                 :            : 
    2354                 :            : static void
    2355                 :        426 : gcr_parser_dispose (GObject *obj)
    2356                 :            : {
    2357                 :        426 :         GcrParser *self = GCR_PARSER (obj);
    2358                 :            :         gsize i;
    2359                 :            : 
    2360         [ -  + ]:        426 :         g_assert (!self->pv->parsed);
    2361                 :            : 
    2362         [ +  + ]:        426 :         if (self->pv->specific_formats)
    2363                 :        348 :                 g_tree_destroy (self->pv->specific_formats);
    2364                 :        426 :         self->pv->specific_formats = NULL;
    2365                 :            : 
    2366         [ +  + ]:       1292 :         for (i = 0; i < self->pv->passwords->len; ++i)
    2367                 :        866 :                 egg_secure_strfree (g_ptr_array_index (self->pv->passwords, i));
    2368                 :        426 :         g_ptr_array_set_size (self->pv->passwords, 0);
    2369                 :            : 
    2370                 :        426 :         G_OBJECT_CLASS (gcr_parser_parent_class)->dispose (obj);
    2371                 :        426 : }
    2372                 :            : 
    2373                 :            : static void
    2374                 :        426 : gcr_parser_finalize (GObject *obj)
    2375                 :            : {
    2376                 :        426 :         GcrParser *self = GCR_PARSER (obj);
    2377                 :            : 
    2378         [ -  + ]:        426 :         g_assert (!self->pv->parsed);
    2379                 :            : 
    2380                 :        426 :         g_ptr_array_free (self->pv->passwords, TRUE);
    2381                 :        426 :         self->pv->passwords = NULL;
    2382                 :            : 
    2383                 :        426 :         g_free (self->pv->filename);
    2384                 :        426 :         self->pv->filename = NULL;
    2385                 :            : 
    2386                 :        426 :         G_OBJECT_CLASS (gcr_parser_parent_class)->finalize (obj);
    2387                 :        426 : }
    2388                 :            : 
    2389                 :            : static void
    2390                 :          0 : gcr_parser_set_property (GObject *obj, guint prop_id, const GValue *value,
    2391                 :            :                            GParamSpec *pspec)
    2392                 :            : {
    2393                 :            :         switch (prop_id) {
    2394                 :            :         default:
    2395                 :          0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
    2396                 :          0 :                 break;
    2397                 :            :         }
    2398                 :          0 : }
    2399                 :            : 
    2400                 :            : static void
    2401                 :          0 : gcr_parser_get_property (GObject *obj, guint prop_id, GValue *value,
    2402                 :            :                          GParamSpec *pspec)
    2403                 :            : {
    2404                 :          0 :         GcrParser *self = GCR_PARSER (obj);
    2405                 :            : 
    2406   [ #  #  #  # ]:          0 :         switch (prop_id) {
    2407                 :          0 :         case PROP_PARSED_ATTRIBUTES:
    2408                 :          0 :                 g_value_set_boxed (value, gcr_parser_get_parsed_attributes (self));
    2409                 :          0 :                 break;
    2410                 :          0 :         case PROP_PARSED_LABEL:
    2411                 :          0 :                 g_value_set_string (value, gcr_parser_get_parsed_label (self));
    2412                 :          0 :                 break;
    2413                 :          0 :         case PROP_PARSED_DESCRIPTION:
    2414                 :          0 :                 g_value_set_string (value, gcr_parser_get_parsed_description (self));
    2415                 :          0 :                 break;
    2416                 :          0 :         default:
    2417                 :          0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
    2418                 :          0 :                 break;
    2419                 :            :         }
    2420                 :          0 : }
    2421                 :            : 
    2422                 :            : static void
    2423                 :          3 : gcr_parser_class_init (GcrParserClass *klass)
    2424                 :            : {
    2425                 :          3 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
    2426                 :            :         gint i;
    2427                 :            : 
    2428                 :          3 :         gobject_class->constructor = gcr_parser_constructor;
    2429                 :          3 :         gobject_class->dispose = gcr_parser_dispose;
    2430                 :          3 :         gobject_class->finalize = gcr_parser_finalize;
    2431                 :          3 :         gobject_class->set_property = gcr_parser_set_property;
    2432                 :          3 :         gobject_class->get_property = gcr_parser_get_property;
    2433                 :            : 
    2434                 :            :         /**
    2435                 :            :          * GcrParser:parsed-attributes:
    2436                 :            :          *
    2437                 :            :          * Get the attributes that make up the currently parsed item. This is
    2438                 :            :          * generally only valid during a [signal@Parser::parsed] signal.
    2439                 :            :          */
    2440                 :          3 :         g_object_class_install_property (gobject_class, PROP_PARSED_ATTRIBUTES,
    2441                 :            :                    g_param_spec_boxed ("parsed-attributes", "Parsed Attributes", "Parsed PKCS#11 attributes",
    2442                 :            :                                        GCK_TYPE_ATTRIBUTES,
    2443                 :            :                                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
    2444                 :            : 
    2445                 :            :         /**
    2446                 :            :          * GcrParser:parsed-label:
    2447                 :            :          *
    2448                 :            :          * The label of the currently parsed item. This is generally
    2449                 :            :          * only valid during a [signal@Parser::parsed] signal.
    2450                 :            :          */
    2451                 :          3 :         g_object_class_install_property (gobject_class, PROP_PARSED_LABEL,
    2452                 :            :                    g_param_spec_string ("parsed-label", "Parsed Label", "Parsed item label",
    2453                 :            :                                         "",
    2454                 :            :                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
    2455                 :            : 
    2456                 :            :         /**
    2457                 :            :          * GcrParser:parsed-description:
    2458                 :            :          *
    2459                 :            :          * The description of the type of the currently parsed item. This is generally
    2460                 :            :          * only valid during a [signal@Parser::parsed] signal.
    2461                 :            :          */
    2462                 :          3 :         g_object_class_install_property (gobject_class, PROP_PARSED_DESCRIPTION,
    2463                 :            :                    g_param_spec_string ("parsed-description", "Parsed Description", "Parsed item description",
    2464                 :            :                                         "",
    2465                 :            :                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
    2466                 :            : 
    2467                 :            :         /**
    2468                 :            :          * GcrParser::authenticate:
    2469                 :            :          * @self: the parser
    2470                 :            :          * @count: the number of times this item has been authenticated
    2471                 :            :          *
    2472                 :            :          * This signal is emitted when an item needs to be unlocked or decrypted before
    2473                 :            :          * it can be parsed. The @count argument specifies the number of times
    2474                 :            :          * the signal has been emitted for a given item. This can be used to
    2475                 :            :          * display a message saying the previous password was incorrect.
    2476                 :            :          *
    2477                 :            :          * Typically the gcr_parser_add_password() function is called in
    2478                 :            :          * response to this signal.
    2479                 :            :          *
    2480                 :            :          * If %FALSE is returned, then the authentication was not handled. If
    2481                 :            :          * no handlers return %TRUE then the item is not parsed and an error
    2482                 :            :          * with the code %GCR_ERROR_CANCELLED will be raised.
    2483                 :            :          *
    2484                 :            :          * Returns: Whether the authentication was handled.
    2485                 :            :          */
    2486                 :          3 :         signals[AUTHENTICATE] = g_signal_new ("authenticate", GCR_TYPE_PARSER,
    2487                 :            :                                         G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrParserClass, authenticate),
    2488                 :            :                                         g_signal_accumulator_true_handled, NULL, _gcr_marshal_BOOLEAN__INT,
    2489                 :            :                                         G_TYPE_BOOLEAN, 1, G_TYPE_INT);
    2490                 :            : 
    2491                 :            :         /**
    2492                 :            :          * GcrParser::parsed:
    2493                 :            :          * @self: the parser
    2494                 :            :          *
    2495                 :            :          * This signal is emitted when an item is sucessfully parsed. To access
    2496                 :            :          * the information about the item use the gcr_parser_get_parsed_label(),
    2497                 :            :          * gcr_parser_get_parsed_attributes() and gcr_parser_get_parsed_description()
    2498                 :            :          * functions.
    2499                 :            :          */
    2500                 :          3 :         signals[PARSED] = g_signal_new ("parsed", GCR_TYPE_PARSER,
    2501                 :            :                                         G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GcrParserClass, parsed),
    2502                 :            :                                         NULL, NULL, NULL,
    2503                 :            :                                         G_TYPE_NONE, 0);
    2504                 :            : 
    2505                 :          3 :         init_quarks ();
    2506                 :          3 :         _gcr_initialize_library ();
    2507                 :            : 
    2508                 :            :         /* Check that the format tables are in order */
    2509         [ +  + ]:         84 :         for (i = 1; i < G_N_ELEMENTS (parser_formats); ++i)
    2510         [ -  + ]:         81 :                 g_assert (parser_formats[i].format_id >= parser_formats[i - 1].format_id);
    2511                 :          3 : }
    2512                 :            : 
    2513                 :            : /* -----------------------------------------------------------------------------
    2514                 :            :  * PUBLIC
    2515                 :            :  */
    2516                 :            : 
    2517                 :            : /**
    2518                 :            :  * gcr_parser_new:
    2519                 :            :  *
    2520                 :            :  * Create a new #GcrParser
    2521                 :            :  *
    2522                 :            :  * Returns: (transfer full): a newly allocated #GcrParser
    2523                 :            :  */
    2524                 :            : GcrParser *
    2525                 :        426 : gcr_parser_new (void)
    2526                 :            : {
    2527                 :        426 :         return g_object_new (GCR_TYPE_PARSER, NULL);
    2528                 :            : }
    2529                 :            : 
    2530                 :            : /**
    2531                 :            :  * gcr_parser_add_password:
    2532                 :            :  * @self: The parser
    2533                 :            :  * @password: (nullable): a password to try
    2534                 :            :  *
    2535                 :            :  * Add a password to the set of passwords to try when parsing locked or encrypted
    2536                 :            :  * items. This is usually called from the [signal@Parser::authenticate] signal.
    2537                 :            :  */
    2538                 :            : void
    2539                 :        866 : gcr_parser_add_password (GcrParser *self, const gchar *password)
    2540                 :            : {
    2541   [ -  +  +  -  :        866 :         g_return_if_fail (GCR_IS_PARSER (self));
             +  -  -  + ]
    2542                 :        866 :         g_ptr_array_add (self->pv->passwords, egg_secure_strdup (password));
    2543                 :            : }
    2544                 :            : 
    2545                 :            : /**
    2546                 :            :  * gcr_parser_parse_bytes:
    2547                 :            :  * @self: The parser
    2548                 :            :  * @data: the data to parse
    2549                 :            :  * @error: A location to raise an error on failure.
    2550                 :            :  *
    2551                 :            :  * Parse the data. The [signal@Parser::parsed] and
    2552                 :            :  * [signal@Parser::authenticate] signals may fire during the parsing.
    2553                 :            :  *
    2554                 :            :  * Returns: Whether the data was parsed successfully or not.
    2555                 :            :  */
    2556                 :            : gboolean
    2557                 :        426 : gcr_parser_parse_bytes (GcrParser *self,
    2558                 :            :                         GBytes *data,
    2559                 :            :                         GError **error)
    2560                 :            : {
    2561                 :        426 :         ForeachArgs args = { self, NULL, GCR_ERROR_UNRECOGNIZED };
    2562                 :        426 :         const gchar *message = NULL;
    2563                 :            :         gint i;
    2564                 :            : 
    2565   [ -  +  +  -  :        426 :         g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
             +  -  -  + ]
    2566         [ -  + ]:        426 :         g_return_val_if_fail (data != NULL, FALSE);
    2567   [ +  -  -  + ]:        426 :         g_return_val_if_fail (!error || !*error, FALSE);
    2568                 :            : 
    2569         [ +  + ]:        426 :         if (g_bytes_get_size (data) > 0) {
    2570                 :        424 :                 args.data = g_bytes_ref (data);
    2571                 :            : 
    2572                 :            :                 /* Just the specific formats requested */
    2573         [ +  + ]:        424 :                 if (self->pv->specific_formats) {
    2574                 :        348 :                         g_tree_foreach (self->pv->specific_formats, parser_format_foreach, &args);
    2575                 :            : 
    2576                 :            :                 /* All the 'normal' formats */
    2577         [ +  - ]:         76 :                 } else if (self->pv->normal_formats) {
    2578         [ +  - ]:        422 :                         for (i = 0; i < G_N_ELEMENTS (parser_normal); ++i) {
    2579         [ +  + ]:        422 :                                 if (parser_format_foreach ((gpointer)(parser_normal + i),
    2580                 :        422 :                                                            (gpointer)(parser_normal + i), &args))
    2581                 :         76 :                                         break;
    2582                 :            :                         }
    2583                 :            :                 }
    2584                 :            : 
    2585                 :        424 :                 g_bytes_unref (args.data);
    2586                 :            :         }
    2587                 :            : 
    2588   [ +  -  +  -  :        426 :         switch (args.result) {
                   -  - ]
    2589                 :        424 :         case SUCCESS:
    2590                 :        424 :                 return TRUE;
    2591                 :          0 :         case GCR_ERROR_CANCELLED:
    2592                 :          0 :                 message = _("The operation was cancelled");
    2593                 :          0 :                 break;
    2594                 :          2 :         case GCR_ERROR_UNRECOGNIZED:
    2595                 :          2 :                 message = _("Unrecognized or unsupported data.");
    2596                 :          2 :                 break;
    2597                 :          0 :         case GCR_ERROR_FAILURE:
    2598                 :          0 :                 message = _("Could not parse invalid or corrupted data.");
    2599                 :          0 :                 break;
    2600                 :          0 :         case GCR_ERROR_LOCKED:
    2601                 :          0 :                 message = _("The data is locked");
    2602                 :          0 :                 break;
    2603                 :          0 :         default:
    2604                 :          0 :                 g_assert_not_reached ();
    2605                 :            :                 break;
    2606                 :            :         };
    2607                 :            : 
    2608                 :          2 :         g_set_error_literal (error, GCR_DATA_ERROR, args.result, message);
    2609                 :          2 :         return FALSE;
    2610                 :            : }
    2611                 :            : 
    2612                 :            : /**
    2613                 :            :  * gcr_parser_parse_data:
    2614                 :            :  * @self: The parser
    2615                 :            :  * @data: (array length=n_data): the data to parse
    2616                 :            :  * @n_data: The length of the data
    2617                 :            :  * @error: A location to raise an error on failure.
    2618                 :            :  *
    2619                 :            :  * Parse the data. The [signal@Parser::parsed] and [signal@Parser::authenticate]
    2620                 :            :  * signals may fire during the parsing.
    2621                 :            :  *
    2622                 :            :  * A copy of the data will be made. Use [method@Parser.parse_bytes] to avoid
    2623                 :            :  * this.
    2624                 :            :  *
    2625                 :            :  * Returns: Whether the data was parsed successfully or not.
    2626                 :            :  */
    2627                 :            : gboolean
    2628                 :          2 : gcr_parser_parse_data (GcrParser *self,
    2629                 :            :                        const guchar *data,
    2630                 :            :                        gsize n_data,
    2631                 :            :                        GError **error)
    2632                 :            : {
    2633                 :            :         GBytes *bytes;
    2634                 :            :         gboolean ret;
    2635                 :            : 
    2636   [ -  +  +  -  :          2 :         g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
             +  -  -  + ]
    2637   [ +  +  -  + ]:          2 :         g_return_val_if_fail (data || !n_data, FALSE);
    2638   [ +  -  -  + ]:          2 :         g_return_val_if_fail (!error || !*error, FALSE);
    2639                 :            : 
    2640                 :          2 :         bytes = g_bytes_new (data, n_data);
    2641                 :          2 :         ret = gcr_parser_parse_bytes (self, bytes, error);
    2642                 :          2 :         g_bytes_unref (bytes);
    2643                 :            : 
    2644                 :          2 :         return ret;
    2645                 :            : }
    2646                 :            : 
    2647                 :            : /**
    2648                 :            :  * gcr_parser_format_enable:
    2649                 :            :  * @self: The parser
    2650                 :            :  * @format: The format identifier
    2651                 :            :  *
    2652                 :            :  * Enable parsing of the given format. Use %GCR_FORMAT_ALL to enable all the formats.
    2653                 :            :  */
    2654                 :            : void
    2655                 :        348 : gcr_parser_format_enable (GcrParser *self,
    2656                 :            :                           GcrDataFormat format)
    2657                 :            : {
    2658                 :            :         const ParserFormat *form;
    2659                 :            :         guint i;
    2660                 :            : 
    2661   [ -  +  +  -  :        348 :         g_return_if_fail (GCR_IS_PARSER (self));
             +  -  -  + ]
    2662                 :            : 
    2663         [ +  - ]:        348 :         if (!self->pv->specific_formats)
    2664                 :        348 :                 self->pv->specific_formats = g_tree_new (compare_pointers);
    2665                 :            : 
    2666         [ +  + ]:        348 :         if (format != -1) {
    2667                 :        294 :                 form = parser_format_lookup (format);
    2668         [ -  + ]:        294 :                 g_return_if_fail (form);
    2669                 :        294 :                 g_tree_insert (self->pv->specific_formats,
    2670                 :            :                                (gpointer)form, (gpointer)form);
    2671                 :            :         } else {
    2672         [ +  + ]:       1566 :                 for (i = 0; i < G_N_ELEMENTS (parser_formats); i++) {
    2673                 :       1512 :                         form = &parser_formats[i];
    2674                 :       1512 :                         g_tree_insert (self->pv->specific_formats, (gpointer)form,
    2675                 :            :                                        (gpointer)form);
    2676                 :            :                 }
    2677                 :            :         }
    2678                 :            : }
    2679                 :            : 
    2680                 :            : /**
    2681                 :            :  * gcr_parser_format_disable:
    2682                 :            :  * @self: The parser
    2683                 :            :  * @format: The format identifier
    2684                 :            :  *
    2685                 :            :  * Disable parsing of the given format. Use %GCR_FORMAT_ALL to disable all the formats.
    2686                 :            :  */
    2687                 :            : void
    2688                 :        348 : gcr_parser_format_disable (GcrParser *self,
    2689                 :            :                            GcrDataFormat format)
    2690                 :            : {
    2691                 :            :         ParserFormat *form;
    2692                 :            : 
    2693   [ -  +  +  -  :        348 :         g_return_if_fail (GCR_IS_PARSER (self));
             +  -  -  + ]
    2694                 :            : 
    2695         [ +  - ]:        348 :         if (format == -1) {
    2696         [ -  + ]:        348 :                 if (self->pv->specific_formats)
    2697                 :          0 :                         g_tree_destroy (self->pv->specific_formats);
    2698                 :        348 :                 self->pv->specific_formats = NULL;
    2699                 :        348 :                 self->pv->normal_formats = FALSE;
    2700                 :            :         }
    2701                 :            : 
    2702         [ +  - ]:        348 :         if (!self->pv->specific_formats)
    2703                 :        348 :                 return;
    2704                 :            : 
    2705                 :          0 :         form = parser_format_lookup (format);
    2706         [ #  # ]:          0 :         g_return_if_fail (form);
    2707                 :            : 
    2708                 :          0 :         g_tree_remove (self->pv->specific_formats, form);
    2709                 :            : }
    2710                 :            : 
    2711                 :            : /**
    2712                 :            :  * gcr_parser_format_supported:
    2713                 :            :  * @self: The parser
    2714                 :            :  * @format: The format identifier
    2715                 :            :  *
    2716                 :            :  * Check whether the given format is supported by the parser.
    2717                 :            :  *
    2718                 :            :  * Returns: Whether the format is supported.
    2719                 :            :  */
    2720                 :            : gboolean
    2721                 :          0 : gcr_parser_format_supported (GcrParser *self,
    2722                 :            :                              GcrDataFormat format)
    2723                 :            : {
    2724   [ #  #  #  #  :          0 :         g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
             #  #  #  # ]
    2725         [ #  # ]:          0 :         g_return_val_if_fail (format != GCR_FORMAT_ALL, FALSE);
    2726         [ #  # ]:          0 :         g_return_val_if_fail (format != GCR_FORMAT_INVALID, FALSE);
    2727                 :          0 :         return parser_format_lookup (format) ? TRUE : FALSE;
    2728                 :            : }
    2729                 :            : 
    2730                 :            : /**
    2731                 :            :  * gcr_parser_get_parsed:
    2732                 :            :  * @self: a parser
    2733                 :            :  *
    2734                 :            :  * Get the currently parsed item
    2735                 :            :  *
    2736                 :            :  * Returns: (transfer none): the currently parsed item
    2737                 :            :  */
    2738                 :            : GcrParsed *
    2739                 :          3 : gcr_parser_get_parsed (GcrParser *self)
    2740                 :            : {
    2741   [ -  +  +  -  :          3 :         g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
             +  -  -  + ]
    2742                 :          3 :         return self->pv->parsed;
    2743                 :            : }
    2744                 :            : 
    2745   [ #  #  #  #  :          0 : G_DEFINE_BOXED_TYPE (GcrParsed, gcr_parsed, gcr_parsed_ref, gcr_parsed_unref)
                   #  # ]
    2746                 :            : 
    2747                 :            : /**
    2748                 :            :  * gcr_parser_get_filename:
    2749                 :            :  * @self: a parser item
    2750                 :            :  *
    2751                 :            :  * Get the filename of the parser item.
    2752                 :            :  *
    2753                 :            :  * Returns: the filename set on the parser, or %NULL
    2754                 :            :  */
    2755                 :            : const gchar *
    2756                 :       1467 : gcr_parser_get_filename (GcrParser *self)
    2757                 :            : {
    2758   [ -  +  +  -  :       1467 :         g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
             +  -  -  + ]
    2759                 :       1467 :         return self->pv->filename;
    2760                 :            : }
    2761                 :            : 
    2762                 :            : /**
    2763                 :            :  * gcr_parser_set_filename:
    2764                 :            :  * @self: a parser item
    2765                 :            :  * @filename: (nullable): a string of the filename of the parser item
    2766                 :            :  *
    2767                 :            :  * Sets the filename of the parser item.
    2768                 :            :  */
    2769                 :            : void
    2770                 :          1 : gcr_parser_set_filename (GcrParser *self,
    2771                 :            :                          const gchar *filename)
    2772                 :            : {
    2773   [ -  +  +  -  :          1 :         g_return_if_fail (GCR_IS_PARSER (self));
             +  -  -  + ]
    2774                 :          1 :         g_free (self->pv->filename);
    2775                 :          1 :         self->pv->filename = g_strdup (filename);
    2776                 :            : }
    2777                 :            : 
    2778                 :            : /**
    2779                 :            :  * gcr_parsed_ref:
    2780                 :            :  * @parsed: a parsed item
    2781                 :            :  *
    2782                 :            :  * Add a reference to a parsed item. An item may not be shared across threads
    2783                 :            :  * until it has been referenced at least once.
    2784                 :            :  *
    2785                 :            :  * Returns: (transfer full): the parsed item
    2786                 :            :  */
    2787                 :            : GcrParsed *
    2788                 :          1 : gcr_parsed_ref (GcrParsed *parsed)
    2789                 :            : {
    2790                 :            :         GcrParsed *copy;
    2791                 :            : 
    2792         [ -  + ]:          1 :         g_return_val_if_fail (parsed != NULL, NULL);
    2793                 :            : 
    2794                 :            :         /* Already had a reference */
    2795         [ -  + ]:          1 :         if (g_atomic_int_add (&parsed->refs, 1) >= 1)
    2796                 :          0 :                 return parsed;
    2797                 :            : 
    2798                 :            :         /* If this is the first reference, flatten the stack of parsed */
    2799                 :          1 :         copy = g_new0 (GcrParsed, 1);
    2800                 :          1 :         copy->refs = 1;
    2801                 :          1 :         copy->label = g_strdup (gcr_parsed_get_label (parsed));
    2802                 :          1 :         copy->filename = g_strdup (gcr_parsed_get_filename (parsed));
    2803                 :          1 :         copy->attrs = gcr_parsed_get_attributes (parsed);
    2804                 :          1 :         copy->format = gcr_parsed_get_format (parsed);
    2805         [ +  - ]:          1 :         if (copy->attrs)
    2806                 :          1 :                 gck_attributes_ref (copy->attrs);
    2807                 :          1 :         copy->description = gcr_parsed_get_description (parsed);
    2808                 :          1 :         copy->next = NULL;
    2809                 :            : 
    2810                 :            :         /* Find the block of data to copy */
    2811         [ +  - ]:          1 :         while (parsed != NULL) {
    2812         [ +  - ]:          1 :                 if (parsed->data != NULL) {
    2813                 :          1 :                         copy->data = g_bytes_ref (parsed->data);
    2814                 :          1 :                         copy->sensitive = parsed->sensitive;
    2815                 :          1 :                         break;
    2816                 :            :                 }
    2817                 :          0 :                 parsed = parsed->next;
    2818                 :            :         }
    2819                 :            : 
    2820                 :          1 :         return copy;
    2821                 :            : }
    2822                 :            : 
    2823                 :            : /**
    2824                 :            :  * gcr_parsed_unref:
    2825                 :            :  * @parsed: a parsed item
    2826                 :            :  *
    2827                 :            :  * Unreferences a parsed item which was referenced with gcr_parsed_ref()
    2828                 :            :  */
    2829                 :            : void
    2830                 :          1 : gcr_parsed_unref (gpointer parsed)
    2831                 :            : {
    2832                 :          1 :         GcrParsed *par = parsed;
    2833                 :            : 
    2834         [ -  + ]:          1 :         g_return_if_fail (parsed != NULL);
    2835                 :            : 
    2836         [ +  - ]:          1 :         if (g_atomic_int_dec_and_test (&par->refs)) {
    2837                 :          1 :                 _gcr_parsed_free (parsed);
    2838                 :            :         }
    2839                 :            : }
    2840                 :            : 
    2841                 :            : /**
    2842                 :            :  * gcr_parser_get_parsed_description:
    2843                 :            :  * @self: The parser
    2844                 :            :  *
    2845                 :            :  * Get a description for the type of the currently parsed item. This is generally
    2846                 :            :  * only valid during the [signal@Parser::parsed] signal.
    2847                 :            :  *
    2848                 :            :  * Returns: (nullable): the description for the current item; this is owned by
    2849                 :            :  *          the parser and should not be freed
    2850                 :            :  */
    2851                 :            : const gchar*
    2852                 :        186 : gcr_parser_get_parsed_description (GcrParser *self)
    2853                 :            : {
    2854   [ -  +  +  -  :        186 :         g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
             +  -  -  + ]
    2855         [ -  + ]:        186 :         g_return_val_if_fail (self->pv->parsed != NULL, NULL);
    2856                 :            : 
    2857                 :        186 :         return gcr_parsed_get_description (self->pv->parsed);
    2858                 :            : }
    2859                 :            : 
    2860                 :            : /**
    2861                 :            :  * gcr_parsed_get_description:
    2862                 :            :  * @parsed: a parsed item
    2863                 :            :  *
    2864                 :            :  * Get the descirption for a parsed item.
    2865                 :            :  *
    2866                 :            :  * Returns: (nullable): the description
    2867                 :            :  */
    2868                 :            : const gchar*
    2869                 :        187 : gcr_parsed_get_description (GcrParsed *parsed)
    2870                 :            : {
    2871         [ +  - ]:        187 :         while (parsed != NULL) {
    2872         [ +  - ]:        187 :                 if (parsed->description != NULL)
    2873                 :        187 :                         return parsed->description;
    2874                 :          0 :                 parsed = parsed->next;
    2875                 :            :         }
    2876                 :            : 
    2877                 :          0 :         return NULL;
    2878                 :            : }
    2879                 :            : 
    2880                 :            : /**
    2881                 :            :  * gcr_parser_get_parsed_attributes:
    2882                 :            :  * @self: The parser
    2883                 :            :  *
    2884                 :            :  * Get the attributes which make up the currently parsed item. This is generally
    2885                 :            :  * only valid during the [signal@Parser::parsed] signal.
    2886                 :            :  *
    2887                 :            :  * Returns: (transfer none) (nullable): the attributes for the current item,
    2888                 :            :  *          which are owned by the parser and should not be freed
    2889                 :            :  */
    2890                 :            : GckAttributes *
    2891                 :        350 : gcr_parser_get_parsed_attributes (GcrParser *self)
    2892                 :            : {
    2893   [ -  +  +  -  :        350 :         g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
             +  -  -  + ]
    2894         [ -  + ]:        350 :         g_return_val_if_fail (self->pv->parsed != NULL, NULL);
    2895                 :            : 
    2896                 :        350 :         return gcr_parsed_get_attributes (self->pv->parsed);
    2897                 :            : }
    2898                 :            : 
    2899                 :            : /**
    2900                 :            :  * gcr_parsed_get_attributes:
    2901                 :            :  * @parsed: a parsed item
    2902                 :            :  *
    2903                 :            :  * Get the attributes which make up the parsed item.
    2904                 :            :  *
    2905                 :            :  * Returns: (transfer none) (nullable): the attributes for the item; these
    2906                 :            :  *          are owned by the parsed item and should not be freed
    2907                 :            :  */
    2908                 :            : GckAttributes *
    2909                 :        351 : gcr_parsed_get_attributes (GcrParsed *parsed)
    2910                 :            : {
    2911         [ +  - ]:        351 :         while (parsed != NULL) {
    2912         [ +  - ]:        351 :                 if (parsed->attrs != NULL)
    2913                 :        351 :                         return parsed->attrs;
    2914                 :          0 :                 parsed = parsed->next;
    2915                 :            :         }
    2916                 :            : 
    2917                 :          0 :         return NULL;
    2918                 :            : }
    2919                 :            : 
    2920                 :            : /**
    2921                 :            :  * gcr_parser_get_parsed_label:
    2922                 :            :  * @self: The parser
    2923                 :            :  *
    2924                 :            :  * Get the label of the currently parsed item. This is generally only valid
    2925                 :            :  * during the [signal@Parser::parsed] signal.
    2926                 :            :  *
    2927                 :            :  * Returns: (nullable): the label of the currently parsed item. The value is
    2928                 :            :  *          owned by the parser and should not be freed.
    2929                 :            :  */
    2930                 :            : const gchar*
    2931                 :        525 : gcr_parser_get_parsed_label (GcrParser *self)
    2932                 :            : {
    2933   [ -  +  +  -  :        525 :         g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
             +  -  -  + ]
    2934         [ -  + ]:        525 :         g_return_val_if_fail (self->pv->parsed != NULL, NULL);
    2935                 :            : 
    2936                 :        525 :         return gcr_parsed_get_label (self->pv->parsed);
    2937                 :            : }
    2938                 :            : 
    2939                 :            : /**
    2940                 :            :  * gcr_parsed_get_label:
    2941                 :            :  * @parsed: a parsed item
    2942                 :            :  *
    2943                 :            :  * Get the label for the parsed item.
    2944                 :            :  *
    2945                 :            :  * Returns: (nullable): the label for the item
    2946                 :            :  */
    2947                 :            : const gchar*
    2948                 :        526 : gcr_parsed_get_label (GcrParsed *parsed)
    2949                 :            : {
    2950         [ +  + ]:       1115 :         while (parsed != NULL) {
    2951         [ +  + ]:        720 :                 if (parsed->label != NULL)
    2952                 :        131 :                         return parsed->label;
    2953                 :        589 :                 parsed = parsed->next;
    2954                 :            :         }
    2955                 :            : 
    2956                 :        395 :         return NULL;
    2957                 :            : }
    2958                 :            : 
    2959                 :            : /**
    2960                 :            :  * gcr_parser_get_parsed_block:
    2961                 :            :  * @self: a parser
    2962                 :            :  * @n_block: a location to place the size of the block
    2963                 :            :  *
    2964                 :            :  * Get the raw data block that represents this parsed object. This is only
    2965                 :            :  * valid during the [signal@Parser::parsed] signal.
    2966                 :            :  *
    2967                 :            :  * Returns: (transfer none) (array length=n_block) (nullable): the raw data
    2968                 :            :  *          block of the currently parsed item; the value is owned by the parser
    2969                 :            :  *          and should not be freed
    2970                 :            :  */
    2971                 :            : const guchar *
    2972                 :          2 : gcr_parser_get_parsed_block (GcrParser *self,
    2973                 :            :                              gsize *n_block)
    2974                 :            : {
    2975   [ -  +  +  -  :          2 :         g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
             +  -  -  + ]
    2976         [ -  + ]:          2 :         g_return_val_if_fail (n_block != NULL, NULL);
    2977         [ -  + ]:          2 :         g_return_val_if_fail (self->pv->parsed != NULL, NULL);
    2978                 :            : 
    2979                 :          2 :         return gcr_parsed_get_data (self->pv->parsed, n_block);
    2980                 :            : }
    2981                 :            : 
    2982                 :            : 
    2983                 :            : /**
    2984                 :            :  * gcr_parser_get_parsed_bytes:
    2985                 :            :  * @self: a parser
    2986                 :            :  *
    2987                 :            :  * Get the raw data block that represents this parsed object. This is only
    2988                 :            :  * valid during the [signal@Parser::parsed] signal.
    2989                 :            :  *
    2990                 :            :  * Returns: (transfer none): the raw data block of the currently parsed item
    2991                 :            :  */
    2992                 :            : GBytes *
    2993                 :        188 : gcr_parser_get_parsed_bytes (GcrParser *self)
    2994                 :            : {
    2995                 :        188 :         return gcr_parsed_get_bytes (self->pv->parsed);
    2996                 :            : }
    2997                 :            : 
    2998                 :            : /**
    2999                 :            :  * gcr_parsed_get_data:
    3000                 :            :  * @parsed: a parsed item
    3001                 :            :  * @n_data: location to store size of returned data
    3002                 :            :  *
    3003                 :            :  * Get the raw data block for the parsed item.
    3004                 :            :  *
    3005                 :            :  * Returns: (transfer none) (array length=n_data) (nullable): the raw data of
    3006                 :            :  *          the parsed item, or %NULL
    3007                 :            :  */
    3008                 :            : const guchar *
    3009                 :          4 : gcr_parsed_get_data (GcrParsed *parsed,
    3010                 :            :                      gsize *n_data)
    3011                 :            : {
    3012                 :            :         GBytes *bytes;
    3013                 :            : 
    3014         [ -  + ]:          4 :         g_return_val_if_fail (n_data != NULL, NULL);
    3015                 :            : 
    3016                 :          4 :         bytes = gcr_parsed_get_bytes (parsed);
    3017         [ -  + ]:          4 :         if (bytes == NULL) {
    3018                 :          0 :                 *n_data = 0;
    3019                 :          0 :                 return NULL;
    3020                 :            :         }
    3021                 :            : 
    3022                 :          4 :         return g_bytes_get_data (bytes, n_data);
    3023                 :            : }
    3024                 :            : 
    3025                 :            : /**
    3026                 :            :  * gcr_parsed_get_bytes:
    3027                 :            :  * @parsed: a parsed item
    3028                 :            :  *
    3029                 :            :  * Get the raw data block for the parsed item.
    3030                 :            :  *
    3031                 :            :  * Returns: (transfer none): the raw data of the parsed item, or %NULL
    3032                 :            :  */
    3033                 :            : GBytes *
    3034                 :        194 : gcr_parsed_get_bytes (GcrParsed *parsed)
    3035                 :            : {
    3036         [ +  - ]:        195 :         while (parsed != NULL) {
    3037         [ +  + ]:        195 :                 if (parsed->data != NULL)
    3038                 :        194 :                         return parsed->data;
    3039                 :          1 :                 parsed = parsed->next;
    3040                 :            :         }
    3041                 :            : 
    3042                 :          0 :         return NULL;
    3043                 :            : }
    3044                 :            : 
    3045                 :            : /**
    3046                 :            :  * gcr_parser_get_parsed_format:
    3047                 :            :  * @self: a parser
    3048                 :            :  *
    3049                 :            :  * Get the format of the raw data block that represents this parsed object.
    3050                 :            :  * This corresponds with the data returned from
    3051                 :            :  * [method@Parser.get_parsed_block].
    3052                 :            :  *
    3053                 :            :  * This is only valid during the [signal@Parser::parsed] signal.
    3054                 :            :  *
    3055                 :            :  * Returns: the data format of the currently parsed item
    3056                 :            :  */
    3057                 :            : GcrDataFormat
    3058                 :        186 : gcr_parser_get_parsed_format (GcrParser *self)
    3059                 :            : {
    3060   [ -  +  +  -  :        186 :         g_return_val_if_fail (GCR_IS_PARSER (self), 0);
             +  -  -  + ]
    3061         [ -  + ]:        186 :         g_return_val_if_fail (self->pv->parsed != NULL, 0);
    3062                 :            : 
    3063                 :        186 :         return gcr_parsed_get_format (self->pv->parsed);
    3064                 :            : }
    3065                 :            : 
    3066                 :            : /**
    3067                 :            :  * gcr_parsed_get_format:
    3068                 :            :  * @parsed: a parsed item
    3069                 :            :  *
    3070                 :            :  * Get the format of the parsed item.
    3071                 :            :  *
    3072                 :            :  * Returns: the data format of the item
    3073                 :            :  */
    3074                 :            : GcrDataFormat
    3075                 :        187 : gcr_parsed_get_format (GcrParsed *parsed)
    3076                 :            : {
    3077         [ +  - ]:        188 :         while (parsed != NULL) {
    3078         [ +  + ]:        188 :                 if (parsed->data != NULL)
    3079                 :        187 :                         return parsed->format;
    3080                 :          1 :                 parsed = parsed->next;
    3081                 :            :         }
    3082                 :            : 
    3083                 :          0 :         return 0;
    3084                 :            : }
    3085                 :            : 
    3086                 :            : /**
    3087                 :            :  * gcr_parsed_get_filename:
    3088                 :            :  * @parsed: a parsed item
    3089                 :            :  *
    3090                 :            :  * Get the filename of the parsed item.
    3091                 :            :  *
    3092                 :            :  * Returns: (transfer none): the filename of
    3093                 :            :  *          the parsed item, or %NULL
    3094                 :            :  */
    3095                 :            : const gchar *
    3096                 :          2 : gcr_parsed_get_filename (GcrParsed *parsed)
    3097                 :            : {
    3098         [ -  + ]:          2 :         g_return_val_if_fail (parsed != NULL, NULL);
    3099                 :          2 :         return parsed->filename;
    3100                 :            : }
    3101                 :            : /* ---------------------------------------------------------------------------------
    3102                 :            :  * STREAM PARSING
    3103                 :            :  */
    3104                 :            : 
    3105                 :            : #define GCR_TYPE_PARSING        (gcr_parsing_get_type ())
    3106                 :            : #define GCR_PARSING(obj)        (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_PARSING, GcrParsing))
    3107                 :            : #define GCR_IS_PARSING(obj)     (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_PARSING))
    3108                 :            : 
    3109                 :            : typedef struct _GcrParsing {
    3110                 :            :         GObjectClass parent;
    3111                 :            : 
    3112                 :            :         GcrParser *parser;
    3113                 :            :         gboolean async;
    3114                 :            :         GCancellable *cancel;
    3115                 :            : 
    3116                 :            :         /* Failure information */
    3117                 :            :         GError *error;
    3118                 :            :         gboolean complete;
    3119                 :            : 
    3120                 :            :         /* Operation state */
    3121                 :            :         GInputStream *input;
    3122                 :            :         GByteArray *buffer;
    3123                 :            : 
    3124                 :            :         /* Async callback stuff */
    3125                 :            :         GAsyncReadyCallback callback;
    3126                 :            :         gpointer user_data;
    3127                 :            : 
    3128                 :            : } GcrParsing;
    3129                 :            : 
    3130                 :            : typedef struct _GcrParsingClass {
    3131                 :            :         GObjectClass parent_class;
    3132                 :            : } GcrParsingClass;
    3133                 :            : 
    3134                 :            : /* State forward declarations */
    3135                 :            : static void state_cancelled (GcrParsing *self, gboolean async);
    3136                 :            : static void state_failure (GcrParsing *self, gboolean async);
    3137                 :            : static void state_complete (GcrParsing *self, gboolean async);
    3138                 :            : static void state_parse_buffer (GcrParsing *self, gboolean async);
    3139                 :            : static void state_read_buffer (GcrParsing *self, gboolean async);
    3140                 :            : 
    3141                 :            : /* Other forward declarations */
    3142                 :            : static GType gcr_parsing_get_type (void) G_GNUC_CONST;
    3143                 :            : static void gcr_parsing_async_result_init (GAsyncResultIface *iface);
    3144                 :            : 
    3145   [ +  +  +  -  :         16 : G_DEFINE_TYPE_WITH_CODE (GcrParsing, gcr_parsing, G_TYPE_OBJECT,
                   +  + ]
    3146                 :            :                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, gcr_parsing_async_result_init));
    3147                 :            : 
    3148                 :            : #define BLOCK 4096
    3149                 :            : 
    3150                 :            : static void
    3151                 :          4 : next_state (GcrParsing *self, void (*state) (GcrParsing*, gboolean))
    3152                 :            : {
    3153   [ -  +  +  -  :          4 :         g_assert (GCR_IS_PARSING (self));
             +  -  -  + ]
    3154         [ -  + ]:          4 :         g_assert (state);
    3155                 :            : 
    3156   [ -  +  -  - ]:          4 :         if (self->cancel && g_cancellable_is_cancelled (self->cancel))
    3157                 :          0 :                 state = state_cancelled;
    3158                 :            : 
    3159                 :          4 :         (state) (self, self->async);
    3160                 :          4 : }
    3161                 :            : 
    3162                 :            : static void
    3163                 :          1 : state_complete (GcrParsing *self, gboolean async)
    3164                 :            : {
    3165   [ -  +  +  -  :          1 :         g_assert (GCR_IS_PARSING (self));
             +  -  -  + ]
    3166         [ -  + ]:          1 :         g_assert (!self->complete);
    3167                 :          1 :         self->complete = TRUE;
    3168   [ -  +  -  - ]:          1 :         if (async && self->callback != NULL)
    3169                 :          0 :                 (self->callback) (G_OBJECT (self->parser), G_ASYNC_RESULT (self), self->user_data);
    3170                 :          1 : }
    3171                 :            : 
    3172                 :            : static void
    3173                 :          0 : state_failure (GcrParsing *self, gboolean async)
    3174                 :            : {
    3175   [ #  #  #  #  :          0 :         g_assert (GCR_IS_PARSING (self));
             #  #  #  # ]
    3176         [ #  # ]:          0 :         g_assert (self->error);
    3177                 :          0 :         next_state (self, state_complete);
    3178                 :          0 : }
    3179                 :            : 
    3180                 :            : static void
    3181                 :          0 : state_cancelled (GcrParsing *self, gboolean async)
    3182                 :            : {
    3183   [ #  #  #  #  :          0 :         g_assert (GCR_IS_PARSING (self));
             #  #  #  # ]
    3184   [ #  #  #  # ]:          0 :         if (self->cancel && g_cancellable_is_cancelled (self->cancel))
    3185                 :          0 :                 g_cancellable_cancel (self->cancel);
    3186         [ #  # ]:          0 :         if (self->error)
    3187                 :          0 :                 g_error_free (self->error);
    3188                 :          0 :         self->error = g_error_new_literal (GCR_DATA_ERROR, GCR_ERROR_CANCELLED, _("The operation was cancelled"));
    3189                 :          0 :         next_state (self, state_failure);
    3190                 :          0 : }
    3191                 :            : 
    3192                 :            : static void
    3193                 :          1 : state_parse_buffer (GcrParsing *self, gboolean async)
    3194                 :            : {
    3195                 :          1 :         GError *error = NULL;
    3196                 :            :         GBytes *bytes;
    3197                 :            :         gboolean ret;
    3198                 :            : 
    3199   [ -  +  +  -  :          1 :         g_assert (GCR_IS_PARSING (self));
             +  -  -  + ]
    3200         [ -  + ]:          1 :         g_assert (self->buffer);
    3201                 :            : 
    3202                 :          1 :         bytes = g_byte_array_free_to_bytes (self->buffer);
    3203                 :          1 :         self->buffer = NULL;
    3204                 :          1 :         ret = gcr_parser_parse_bytes (self->parser, bytes, &error);
    3205                 :          1 :         g_bytes_unref (bytes);
    3206                 :            : 
    3207         [ +  - ]:          1 :         if (ret == TRUE) {
    3208                 :          1 :                 next_state (self, state_complete);
    3209                 :            :         } else {
    3210                 :          0 :                 g_propagate_error (&self->error, error);
    3211                 :          0 :                 next_state (self, state_failure);
    3212                 :            :         }
    3213                 :          1 : }
    3214                 :            : 
    3215                 :            : static void
    3216                 :          2 : complete_read_buffer (GcrParsing *self, gssize count, GError *error)
    3217                 :            : {
    3218   [ -  +  +  -  :          2 :         g_assert (GCR_IS_PARSING (self));
             +  -  -  + ]
    3219         [ -  + ]:          2 :         g_assert (self->buffer);
    3220                 :            : 
    3221                 :            :         /* A failure */
    3222         [ -  + ]:          2 :         if (count == -1) {
    3223                 :          0 :                 g_propagate_error (&self->error, error);
    3224                 :          0 :                 next_state (self, state_failure);
    3225                 :            :         } else {
    3226                 :            : 
    3227   [ +  -  +  - ]:          2 :                 g_return_if_fail (count >= 0 && count <= BLOCK);
    3228                 :          2 :                 g_byte_array_set_size (self->buffer, self->buffer->len - (BLOCK - count));
    3229                 :            : 
    3230                 :            :                 /* Finished reading */
    3231         [ +  + ]:          2 :                 if (count == 0)
    3232                 :          1 :                         next_state (self, state_parse_buffer);
    3233                 :            : 
    3234                 :            :                 /* Read the next block */
    3235                 :            :                 else
    3236                 :          1 :                         next_state (self, state_read_buffer);
    3237                 :            :         }
    3238                 :            : 
    3239                 :            : }
    3240                 :            : 
    3241                 :            : static void
    3242                 :          0 : on_read_buffer (GObject *obj, GAsyncResult *res, gpointer user_data)
    3243                 :            : {
    3244                 :          0 :         GError *error = NULL;
    3245                 :            :         gssize count;
    3246                 :            : 
    3247                 :          0 :         count = g_input_stream_read_finish (G_INPUT_STREAM (obj), res, &error);
    3248                 :          0 :         complete_read_buffer (user_data, count, error);
    3249                 :          0 : }
    3250                 :            : 
    3251                 :            : static void
    3252                 :          2 : state_read_buffer (GcrParsing *self, gboolean async)
    3253                 :            : {
    3254                 :          2 :         GError *error = NULL;
    3255                 :            :         gssize count;
    3256                 :            :         gsize at;
    3257                 :            : 
    3258   [ -  +  +  -  :          2 :         g_assert (GCR_IS_PARSING (self));
             +  -  -  + ]
    3259   [ -  +  +  -  :          2 :         g_assert (G_IS_INPUT_STREAM (self->input));
             -  +  -  + ]
    3260                 :            : 
    3261         [ +  + ]:          2 :         if (!self->buffer)
    3262                 :          1 :                 self->buffer = g_byte_array_sized_new (BLOCK);
    3263                 :            : 
    3264                 :          2 :         at = self->buffer->len;
    3265                 :          2 :         g_byte_array_set_size (self->buffer, at + BLOCK);
    3266                 :            : 
    3267         [ -  + ]:          2 :         if (async) {
    3268                 :          0 :                 g_input_stream_read_async (self->input, self->buffer->data + at,
    3269                 :            :                                            BLOCK, G_PRIORITY_DEFAULT, self->cancel,
    3270                 :            :                                            on_read_buffer, self);
    3271                 :            :         } else {
    3272                 :          2 :                 count = g_input_stream_read (self->input, self->buffer->data + at,
    3273                 :            :                                              BLOCK, self->cancel, &error);
    3274                 :          2 :                 complete_read_buffer (self, count, error);
    3275                 :            :         }
    3276                 :          2 : }
    3277                 :            : 
    3278                 :            : static void
    3279                 :          1 : gcr_parsing_init (GcrParsing *self)
    3280                 :            : {
    3281                 :            : 
    3282                 :          1 : }
    3283                 :            : 
    3284                 :            : static void
    3285                 :          1 : gcr_parsing_finalize (GObject *obj)
    3286                 :            : {
    3287                 :          1 :         GcrParsing *self = GCR_PARSING (obj);
    3288                 :            : 
    3289                 :          1 :         g_object_unref (self->parser);
    3290                 :          1 :         self->parser = NULL;
    3291                 :            : 
    3292                 :          1 :         g_object_unref (self->input);
    3293                 :          1 :         self->input = NULL;
    3294                 :            : 
    3295         [ -  + ]:          1 :         if (self->cancel)
    3296                 :          0 :                 g_object_unref (self->cancel);
    3297                 :          1 :         self->cancel = NULL;
    3298                 :            : 
    3299                 :          1 :         g_clear_error (&self->error);
    3300                 :            : 
    3301         [ -  + ]:          1 :         if (self->buffer)
    3302                 :          0 :                 g_byte_array_free (self->buffer, TRUE);
    3303                 :          1 :         self->buffer = NULL;
    3304                 :            : 
    3305                 :          1 :         G_OBJECT_CLASS (gcr_parsing_parent_class)->finalize (obj);
    3306                 :          1 : }
    3307                 :            : 
    3308                 :            : static void
    3309                 :          1 : gcr_parsing_class_init (GcrParsingClass *klass)
    3310                 :            : {
    3311                 :          1 :         G_OBJECT_CLASS (klass)->finalize = gcr_parsing_finalize;
    3312                 :          1 : }
    3313                 :            : 
    3314                 :            : static gpointer
    3315                 :          0 : gcr_parsing_real_get_user_data (GAsyncResult *base)
    3316                 :            : {
    3317   [ #  #  #  #  :          0 :         g_return_val_if_fail (GCR_IS_PARSING (base), NULL);
             #  #  #  # ]
    3318                 :          0 :         return GCR_PARSING (base)->user_data;
    3319                 :            : }
    3320                 :            : 
    3321                 :            : static GObject*
    3322                 :          0 : gcr_parsing_real_get_source_object (GAsyncResult *base)
    3323                 :            : {
    3324   [ #  #  #  #  :          0 :         g_return_val_if_fail (GCR_IS_PARSING (base), NULL);
             #  #  #  # ]
    3325                 :          0 :         return G_OBJECT (GCR_PARSING (base)->parser);
    3326                 :            : }
    3327                 :            : 
    3328                 :            : static void
    3329                 :          1 : gcr_parsing_async_result_init (GAsyncResultIface *iface)
    3330                 :            : {
    3331                 :          1 :         iface->get_source_object = gcr_parsing_real_get_source_object;
    3332                 :          1 :         iface->get_user_data = gcr_parsing_real_get_user_data;
    3333                 :          1 : }
    3334                 :            : 
    3335                 :            : static GcrParsing*
    3336                 :          1 : gcr_parsing_new (GcrParser *parser, GInputStream *input, GCancellable *cancel)
    3337                 :            : {
    3338                 :            :         GcrParsing *self;
    3339                 :            : 
    3340   [ -  +  +  -  :          1 :         g_assert (GCR_IS_PARSER (parser));
             +  -  -  + ]
    3341   [ -  +  +  -  :          1 :         g_assert (G_IS_INPUT_STREAM (input));
             -  +  -  + ]
    3342                 :            : 
    3343                 :          1 :         self = g_object_new (GCR_TYPE_PARSING, NULL);
    3344                 :          1 :         self->parser = g_object_ref (parser);
    3345                 :          1 :         self->input = g_object_ref (input);
    3346         [ -  + ]:          1 :         if (cancel)
    3347                 :          0 :                 self->cancel = g_object_ref (cancel);
    3348                 :            : 
    3349                 :          1 :         return self;
    3350                 :            : }
    3351                 :            : 
    3352                 :            : /**
    3353                 :            :  * gcr_parser_parse_stream:
    3354                 :            :  * @self: The parser
    3355                 :            :  * @input: The input stream
    3356                 :            :  * @cancellable: An optional cancellation object
    3357                 :            :  * @error: A location to raise an error on failure
    3358                 :            :  *
    3359                 :            :  * Parse items from the data in a #GInputStream. This function may block while
    3360                 :            :  * reading from the input stream. Use [method@Parser.parse_stream_async] for
    3361                 :            :  * a non-blocking variant.
    3362                 :            :  *
    3363                 :            :  * The [signal@Parser::parsed] and [signal@Parser::authenticate] signals
    3364                 :            :  * may fire during the parsing.
    3365                 :            :  *
    3366                 :            :  * Returns: Whether the parsing completed successfully or not.
    3367                 :            :  */
    3368                 :            : gboolean
    3369                 :          1 : gcr_parser_parse_stream (GcrParser *self, GInputStream *input, GCancellable *cancellable,
    3370                 :            :                          GError **error)
    3371                 :            : {
    3372                 :            :         GcrParsing *parsing;
    3373                 :            :         gboolean result;
    3374                 :            : 
    3375   [ -  +  +  -  :          1 :         g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
             +  -  -  + ]
    3376   [ -  +  +  -  :          1 :         g_return_val_if_fail (G_IS_INPUT_STREAM (input), FALSE);
             -  +  -  + ]
    3377   [ +  -  -  + ]:          1 :         g_return_val_if_fail (!error || !*error, FALSE);
    3378                 :            : 
    3379                 :          1 :         parsing = gcr_parsing_new (self, input, cancellable);
    3380                 :          1 :         parsing->async = FALSE;
    3381                 :            : 
    3382                 :          1 :         next_state (parsing, state_read_buffer);
    3383         [ -  + ]:          1 :         g_assert (parsing->complete);
    3384                 :            : 
    3385                 :          1 :         result = gcr_parser_parse_stream_finish (self, G_ASYNC_RESULT (parsing), error);
    3386                 :          1 :         g_object_unref (parsing);
    3387                 :            : 
    3388                 :          1 :         return result;
    3389                 :            : }
    3390                 :            : 
    3391                 :            : /**
    3392                 :            :  * gcr_parser_parse_stream_async:
    3393                 :            :  * @self: The parser
    3394                 :            :  * @input: The input stream
    3395                 :            :  * @cancellable: An optional cancellation object
    3396                 :            :  * @callback: Called when the operation result is ready.
    3397                 :            :  * @user_data: Data to pass to callback
    3398                 :            :  *
    3399                 :            :  * Parse items from the data in a #GInputStream. This function completes
    3400                 :            :  * asyncronously and doesn't block.
    3401                 :            :  *
    3402                 :            :  * The [signal@Parser::parsed] and [signal@Parser::authenticate] signals
    3403                 :            :  * may fire during the parsing.
    3404                 :            :  */
    3405                 :            : void
    3406                 :          0 : gcr_parser_parse_stream_async (GcrParser *self, GInputStream *input, GCancellable *cancellable,
    3407                 :            :                                GAsyncReadyCallback callback, gpointer user_data)
    3408                 :            : {
    3409                 :            :         GcrParsing *parsing;
    3410                 :            : 
    3411   [ #  #  #  #  :          0 :         g_return_if_fail (GCR_IS_PARSER (self));
             #  #  #  # ]
    3412   [ #  #  #  #  :          0 :         g_return_if_fail (G_IS_INPUT_STREAM (input));
             #  #  #  # ]
    3413                 :            : 
    3414                 :          0 :         parsing = gcr_parsing_new (self, input, cancellable);
    3415                 :          0 :         parsing->async = TRUE;
    3416                 :          0 :         parsing->callback = callback;
    3417                 :          0 :         parsing->user_data = user_data;
    3418                 :            : 
    3419                 :          0 :         next_state (parsing, state_read_buffer);
    3420                 :            : }
    3421                 :            : 
    3422                 :            : /**
    3423                 :            :  * gcr_parser_parse_stream_finish:
    3424                 :            :  * @self: The parser
    3425                 :            :  * @result:The operation result
    3426                 :            :  * @error: A location to raise an error on failure
    3427                 :            :  *
    3428                 :            :  * Complete an operation to parse a stream.
    3429                 :            :  *
    3430                 :            :  * Returns: Whether the parsing completed successfully or not.
    3431                 :            :  */
    3432                 :            : gboolean
    3433                 :          1 : gcr_parser_parse_stream_finish (GcrParser *self, GAsyncResult *result, GError **error)
    3434                 :            : {
    3435                 :            :         GcrParsing *parsing;
    3436                 :            : 
    3437   [ -  +  +  -  :          1 :         g_return_val_if_fail (GCR_IS_PARSING (result), FALSE);
             +  -  -  + ]
    3438   [ +  -  -  + ]:          1 :         g_return_val_if_fail (!error || !*error, FALSE);
    3439                 :            : 
    3440                 :          1 :         parsing = GCR_PARSING (result);
    3441         [ -  + ]:          1 :         g_return_val_if_fail (parsing->complete, FALSE);
    3442                 :            : 
    3443         [ -  + ]:          1 :         if (parsing->error) {
    3444                 :          0 :                 g_propagate_error (error, parsing->error);
    3445                 :          0 :                 return FALSE;
    3446                 :            :         }
    3447                 :            : 
    3448                 :          1 :         return TRUE;
    3449                 :            : }

Generated by: LCOV version 1.14