LCOV - code coverage report
Current view: top level - gcr - gcr-openpgp.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 479 621 77.1 %
Date: 2022-09-04 10:20:22 Functions: 34 36 94.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 264 450 58.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * gnome-keyring
       3                 :            :  *
       4                 :            :  * Copyright (C) 2011 Collabora Ltd.
       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                 :            :  * Author: Stef Walter <stefw@collabora.co.uk>
      20                 :            :  */
      21                 :            : 
      22                 :            : #include "config.h"
      23                 :            : 
      24                 :            : #include "gcr-openpgp.h"
      25                 :            : #include "gcr-internal.h"
      26                 :            : #include "gcr-record.h"
      27                 :            : #include "gcr-types.h"
      28                 :            : 
      29                 :            : #include "egg/egg-hex.h"
      30                 :            : 
      31                 :            : #include <gcrypt.h>
      32                 :            : 
      33                 :            : #include <string.h>
      34                 :            : 
      35                 :            : typedef enum {
      36                 :            :         OPENPGP_PKT_RESERVED = 0,
      37                 :            :         OPENPGP_PKT_PUBKEY_ENC = 1,
      38                 :            :         OPENPGP_PKT_SIGNATURE = 2,
      39                 :            :         OPENPGP_PKT_ONEPASS_SIG = 4,
      40                 :            :         OPENPGP_PKT_SECRET_KEY = 5,
      41                 :            :         OPENPGP_PKT_PUBLIC_KEY = 6,
      42                 :            :         OPENPGP_PKT_SECRET_SUBKEY = 7,
      43                 :            :         OPENPGP_PKT_COMPRESSED = 8,
      44                 :            :         OPENPGP_PKT_MARKER = 10,
      45                 :            :         OPENPGP_PKT_LITERAL = 11,
      46                 :            :         OPENPGP_PKT_RING_TRUST = 12,
      47                 :            :         OPENPGP_PKT_USER_ID = 13,
      48                 :            :         OPENPGP_PKT_PUBLIC_SUBKEY = 14,
      49                 :            :         OPENPGP_PKT_OLD_COMMENT = 16,
      50                 :            :         OPENPGP_PKT_ATTRIBUTE = 17,
      51                 :            :         OPENPGP_PKT_MDC = 19
      52                 :            : } OpenpgpPktType;
      53                 :            : 
      54                 :            : typedef enum {
      55                 :            :         OPENPGP_SIG_CREATION = 2,
      56                 :            :         OPENPGP_SIG_EXPIRY = 3,
      57                 :            :         OPENPGP_SIG_EXPORTABLE = 4,
      58                 :            :         OPENPGP_SIG_TRUST = 5,
      59                 :            :         OPENPGP_SIG_REGULAR_EXPRESSION = 6,
      60                 :            :         OPENPGP_SIG_REVOCABLE = 7,
      61                 :            :         OPENPGP_SIG_KEY_EXPIRY = 9,
      62                 :            :         OPENPGP_SIG_SYMMETRIC_ALGOS = 11,
      63                 :            :         OPENPGP_SIG_REVOCATION_KEY = 12,
      64                 :            :         OPENPGP_SIG_ISSUER = 16,
      65                 :            :         OPENPGP_SIG_NOTATION_DATA = 20,
      66                 :            :         OPENPGP_SIG_HASH_ALGOS = 21,
      67                 :            :         OPENPGP_SIG_COMPRESSION_ALGOS = 22,
      68                 :            :         OPENPGP_SIG_KEYSERVER_PREFS = 23,
      69                 :            :         OPENPGP_SIG_PREFERRED_KEYSERVER = 24,
      70                 :            :         OPENPGP_SIG_PRIMARY_USERID = 25,
      71                 :            :         OPENPGP_SIG_POLICY_URI = 26,
      72                 :            :         OPENPGP_SIG_KEY_FLAGS = 27,
      73                 :            :         OPENPGP_SIG_SIGNER_USERID = 28,
      74                 :            :         OPENPGP_SIG_REVOCATION_REASON = 29,
      75                 :            :         OPENPGP_SIG_FEATURES = 30,
      76                 :            :         OPENPGP_SIG_TARGET = 31,
      77                 :            :         OPENPGP_SIG_EMBEDDED_SIGNATURE = 32,
      78                 :            : } OpenpgpSigPacket;
      79                 :            : 
      80                 :            : static gboolean
      81                 :       3430 : read_byte (const guchar **at,
      82                 :            :            const guchar *end,
      83                 :            :            guint8 *result)
      84                 :            : {
      85         [ -  + ]:       3430 :         g_assert (at);
      86         [ -  + ]:       3430 :         if (*at == end)
      87                 :          0 :                 *at = NULL;
      88         [ -  + ]:       3430 :         if (*at == NULL)
      89                 :          0 :                 return FALSE;
      90         [ +  - ]:       3430 :         if (result)
      91                 :       3430 :                 *result = *(*at);
      92                 :       3430 :         (*at)++;
      93                 :       3430 :         return TRUE;
      94                 :            : }
      95                 :            : 
      96                 :            : static gboolean
      97                 :       1832 : read_bytes (const guchar **at,
      98                 :            :             const guchar *end,
      99                 :            :             gpointer buffer,
     100                 :            :             gsize length)
     101                 :            : {
     102         [ -  + ]:       1832 :         g_assert (at);
     103         [ -  + ]:       1832 :         if (*at + length > end)
     104                 :          0 :                 *at = NULL;
     105         [ -  + ]:       1832 :         if (*at == NULL)
     106                 :          0 :                 return FALSE;
     107         [ +  + ]:       1832 :         if (buffer != NULL)
     108                 :       1398 :                 memcpy (buffer, *at, length);
     109                 :       1832 :         (*at) += length;
     110                 :       1832 :         return TRUE;
     111                 :            : }
     112                 :            : 
     113                 :            : static gboolean
     114                 :        303 : read_uint32 (const guchar **at,
     115                 :            :              const guchar *end,
     116                 :            :              guint32 *value)
     117                 :            : {
     118                 :            :         guchar buf[4];
     119         [ -  + ]:        303 :         g_assert (at);
     120         [ -  + ]:        303 :         if (!read_bytes (at, end, buf, 4))
     121                 :          0 :                 return FALSE;
     122         [ +  - ]:        303 :         if (value)
     123                 :        303 :                 *value = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
     124                 :        303 :         return TRUE;
     125                 :            : }
     126                 :            : 
     127                 :            : static gboolean
     128                 :        963 : read_uint16 (const guchar **at,
     129                 :            :              const guchar *end,
     130                 :            :              guint16 *value)
     131                 :            : {
     132                 :            :         guchar buf[2];
     133         [ -  + ]:        963 :         g_assert (at);
     134         [ -  + ]:        963 :         if (!read_bytes (at, end, buf, 2))
     135                 :          0 :                 return FALSE;
     136         [ +  - ]:        963 :         if (value)
     137                 :        963 :                 *value = buf[0] << 8 | buf[1];
     138                 :        963 :         return TRUE;
     139                 :            : }
     140                 :            : 
     141                 :            : static gboolean
     142                 :        434 : read_mpi (const guchar **at,
     143                 :            :           const guchar *end,
     144                 :            :           guint16 *bits,
     145                 :            :           guchar **value)
     146                 :            : {
     147                 :            :         gsize bytes;
     148                 :            :         guint16 b;
     149         [ -  + ]:        434 :         g_assert (at);
     150         [ +  + ]:        434 :         if (!bits)
     151                 :        350 :                 bits = &b;
     152         [ -  + ]:        434 :         if (!read_uint16 (at, end, bits))
     153                 :          0 :                 return FALSE;
     154                 :        434 :         bytes = (*bits + 7) / 8;
     155         [ -  + ]:        434 :         if (bytes == 0)
     156                 :          0 :                 return FALSE;
     157         [ -  + ]:        434 :         if (value)
     158                 :          0 :                 *value = g_malloc (bytes);
     159   [ -  +  -  + ]:        434 :         if (!read_bytes (at, end, value ? *value : NULL, bytes)) {
     160         [ #  # ]:          0 :                 if (value)
     161                 :          0 :                         g_free (*value);
     162                 :          0 :                 return FALSE;
     163                 :            :         }
     164                 :        434 :         return TRUE;
     165                 :            : }
     166                 :            : 
     167                 :            : static gboolean
     168                 :        843 : read_new_length (const guchar **at,
     169                 :            :                  const guchar *end,
     170                 :            :                  gsize *pkt_len)
     171                 :            : {
     172                 :            :         guint8 c, c1;
     173                 :            :         guint32 val;
     174                 :            : 
     175         [ -  + ]:        843 :         if (!read_byte (at, end, &c))
     176                 :          0 :                 return FALSE;
     177         [ +  + ]:        843 :         if (c < 192) {
     178                 :        822 :                 *pkt_len = c;
     179   [ +  -  +  + ]:         21 :         } else if (c >= 192 && c <= 223) {
     180         [ -  + ]:         12 :                 if (!read_byte (at, end, &c1))
     181                 :          0 :                         return FALSE;
     182                 :         12 :                 *pkt_len = ((c - 192) << 8) + c1 + 192;
     183         [ +  - ]:          9 :         } else if (c == 255) {
     184         [ -  + ]:          9 :                 if (!read_uint32 (at, end, &val))
     185                 :          0 :                         return FALSE;
     186                 :          9 :                 *pkt_len = val;
     187                 :            :         } else {
     188                 :            :                 /* We don't support partial length */
     189                 :          0 :                 return FALSE;
     190                 :            :         }
     191                 :            : 
     192                 :        843 :         return TRUE;
     193                 :            : }
     194                 :            : 
     195                 :            : static gboolean
     196                 :        522 : read_old_length (const guchar **at,
     197                 :            :                  const guchar *end,
     198                 :            :                  guchar ctb,
     199                 :            :                  gsize *pkt_len)
     200                 :            : {
     201                 :        522 :         gsize llen = ctb & 0x03;
     202                 :            :         guint16 v16;
     203                 :            :         guint32 v32;
     204                 :            :         guint8 c;
     205                 :            : 
     206         [ +  + ]:        522 :         if (llen == 0) {
     207         [ -  + ]:        380 :                 if (!read_byte (at, end, &c))
     208                 :          0 :                         return FALSE;
     209                 :        380 :                 *pkt_len = c;
     210         [ +  - ]:        142 :         } else if (llen == 1) {
     211         [ -  + ]:        142 :                 if (!read_uint16 (at, end, &v16))
     212                 :          0 :                         return FALSE;
     213                 :        142 :                 *pkt_len = v16;
     214         [ #  # ]:          0 :         } else if (llen == 2) {
     215         [ #  # ]:          0 :                 if (!read_uint32 (at, end, &v32))
     216                 :          0 :                         return FALSE;
     217                 :          0 :                 *pkt_len = v32;
     218                 :            :         } else {
     219                 :          0 :                 *pkt_len = end - *at;
     220                 :            :         }
     221                 :            : 
     222                 :        522 :         return TRUE;
     223                 :            : }
     224                 :            : 
     225                 :            : static GcrDataError
     226                 :        574 : read_openpgp_packet (const guchar **at,
     227                 :            :                      const guchar *end,
     228                 :            :                      guint8 *pkt_type,
     229                 :            :                      gsize *length)
     230                 :            : {
     231                 :            :         gboolean new_ctb;
     232                 :            :         guint8 ctb;
     233                 :            :         gboolean ret;
     234                 :            : 
     235         [ -  + ]:        574 :         if (!read_byte (at, end, &ctb))
     236                 :          0 :                 return GCR_ERROR_UNRECOGNIZED;
     237         [ +  + ]:        574 :         if (!(ctb & 0x80))
     238                 :         40 :                 return GCR_ERROR_UNRECOGNIZED;
     239                 :            : 
     240                 :            :         /* RFC2440 packet format. */
     241         [ +  + ]:        534 :         if (ctb & 0x40) {
     242                 :         12 :                 *pkt_type = ctb & 0x3f;
     243                 :         12 :                 new_ctb = TRUE;
     244                 :            : 
     245                 :            :         /* the old RFC1991 packet format. */
     246                 :            :         } else {
     247                 :        522 :                 *pkt_type = ctb & 0x3f;
     248                 :        522 :                 *pkt_type >>= 2;
     249                 :        522 :                 new_ctb = FALSE;
     250                 :            :         }
     251                 :            : 
     252         [ -  + ]:        534 :         if (*pkt_type > 63)
     253                 :          0 :                 return GCR_ERROR_UNRECOGNIZED;
     254                 :            : 
     255         [ +  + ]:        534 :         if (new_ctb)
     256                 :         12 :                 ret = read_new_length (at, end, length);
     257                 :            :         else
     258                 :        522 :                 ret = read_old_length (at, end, ctb, length);
     259         [ -  + ]:        534 :         if (!ret)
     260                 :          0 :                 return GCR_ERROR_UNRECOGNIZED;
     261                 :            : 
     262         [ -  + ]:        534 :         if ((*at) + *length > end)
     263                 :          0 :                 return GCR_ERROR_FAILURE;
     264                 :            : 
     265                 :        534 :         return GCR_SUCCESS;
     266                 :            : }
     267                 :            : 
     268                 :            : static gchar *
     269                 :         90 : hash_user_id_or_attribute (const guchar *beg,
     270                 :            :                            const guchar *end)
     271                 :            : {
     272                 :         90 :         guint8 digest[20] = { 0, };
     273                 :            : 
     274         [ -  + ]:         90 :         g_assert (beg != NULL);
     275         [ -  + ]:         90 :         g_assert (end > beg);
     276                 :            : 
     277                 :         90 :         gcry_md_hash_buffer (GCRY_MD_RMD160, digest, beg, end - beg);
     278                 :         90 :         return egg_hex_encode_full (digest, sizeof (digest), TRUE, NULL, 0);
     279                 :            : }
     280                 :            : 
     281                 :            : static gboolean
     282                 :          0 : parse_v3_rsa_bits_and_keyid (const guchar **at,
     283                 :            :                              const guchar *end,
     284                 :            :                              guint16 *bits,
     285                 :            :                              gchar **keyid)
     286                 :            : {
     287                 :            :         guchar *n;
     288                 :            :         gsize bytes;
     289                 :            : 
     290         [ #  # ]:          0 :         g_assert (bits);
     291         [ #  # ]:          0 :         g_assert (keyid);
     292                 :            : 
     293                 :            :         /* Read in the modulus */
     294         [ #  # ]:          0 :         if (!read_mpi (at, end, bits, &n))
     295                 :          0 :                 return FALSE;
     296                 :            : 
     297                 :            :         /* Last 64-bits of modulus are keyid */
     298                 :          0 :         bytes = (*bits + 7) / 8;
     299         [ #  # ]:          0 :         if (bytes < 8) {
     300                 :          0 :                 g_free (n);
     301                 :          0 :                 return FALSE;
     302                 :            :         }
     303                 :            : 
     304                 :          0 :         *keyid = egg_hex_encode_full (n + (bytes - 8), 8, TRUE, NULL, 0);
     305                 :          0 :         return TRUE;
     306                 :            : }
     307                 :            : 
     308                 :            : static gchar *
     309                 :         84 : hash_v4_keyid (const guchar *data,
     310                 :            :                const guchar *end,
     311                 :            :                gchar **fingerprint)
     312                 :            : {
     313                 :            :         gcry_md_hd_t mdh;
     314                 :            :         gcry_error_t gcry;
     315                 :            :         guchar header[3];
     316                 :            :         guint8 *digest;
     317                 :            :         gchar *keyid;
     318                 :            :         gsize len;
     319                 :            : 
     320                 :            :         /*
     321                 :            :          * Both primary and subkeys use the public key tag byte
     322                 :            :          * 0x99 to construct the hash. So we skip over that here.
     323                 :            :          */
     324                 :            : 
     325         [ -  + ]:         84 :         g_assert (data != NULL);
     326         [ -  + ]:         84 :         g_assert (end > data);
     327                 :            : 
     328                 :         84 :         len = end - data;
     329         [ -  + ]:         84 :         g_return_val_if_fail (len < G_MAXUSHORT, NULL);
     330                 :            : 
     331                 :         84 :         header[0] = 0x99;
     332                 :         84 :         header[1] = len >> 8 & 0xff;
     333                 :         84 :         header[2] = len & 0xff;
     334                 :            : 
     335                 :         84 :         gcry = gcry_md_open (&mdh, GCRY_MD_SHA1, 0);
     336         [ -  + ]:         84 :         g_return_val_if_fail (gcry == 0, NULL);
     337                 :            : 
     338                 :         84 :         gcry_md_write (mdh, header, 3);
     339                 :         84 :         gcry_md_write (mdh, data, len);
     340                 :            : 
     341                 :         84 :         digest = gcry_md_read (mdh, 0);
     342                 :         84 :         keyid = egg_hex_encode_full (digest + 12, 8, TRUE, NULL, 0);
     343         [ +  - ]:         84 :         if (fingerprint)
     344                 :         84 :                 *fingerprint = egg_hex_encode_full (digest, 20, TRUE, NULL, 0);
     345                 :         84 :         gcry_md_close (mdh);
     346                 :            : 
     347                 :         84 :         return keyid;
     348                 :            : }
     349                 :            : 
     350                 :            : static gboolean
     351                 :         84 : parse_v4_algo_bits (const guchar **at,
     352                 :            :                     const guchar *end,
     353                 :            :                     guint8 algo,
     354                 :            :                     guint16 *bits)
     355                 :            : {
     356   [ +  +  +  - ]:         84 :         switch (algo) {
     357                 :         51 :         case GCR_OPENPGP_ALGO_RSA:
     358                 :            :         case GCR_OPENPGP_ALGO_RSA_E:
     359                 :            :         case GCR_OPENPGP_ALGO_RSA_S:
     360   [ +  -  -  + ]:        102 :                 if (!read_mpi (at, end, bits, NULL) ||
     361                 :         51 :                     !read_mpi (at, end, NULL, NULL))
     362                 :          0 :                         return FALSE;
     363                 :         51 :                 return TRUE;
     364                 :         27 :         case GCR_OPENPGP_ALGO_DSA:
     365   [ +  -  +  - ]:         54 :                 if (!read_mpi (at, end, bits, NULL) ||
     366         [ +  - ]:         54 :                     !read_mpi (at, end, NULL, NULL) ||
     367         [ -  + ]:         54 :                     !read_mpi (at, end, NULL, NULL) ||
     368                 :         27 :                     !read_mpi (at, end, NULL, NULL))
     369                 :          0 :                         return FALSE;
     370                 :         27 :                 return TRUE;
     371                 :          6 :         case GCR_OPENPGP_ALGO_ELG_E:
     372   [ +  -  +  - ]:         12 :                 if (!read_mpi (at, end, bits, NULL) ||
     373         [ -  + ]:         12 :                     !read_mpi (at, end, NULL, NULL) ||
     374                 :          6 :                     !read_mpi (at, end, NULL, NULL))
     375                 :          0 :                         return FALSE;
     376                 :          6 :                 return TRUE;
     377                 :          0 :         default: /* Unsupported key */
     378                 :          0 :                 return FALSE;
     379                 :            :         }
     380                 :            : }
     381                 :            : 
     382                 :            : static const gchar *
     383                 :         72 : default_caps_for_algo (guint8 algo)
     384                 :            : {
     385   [ +  -  -  +  :         72 :         switch (algo) {
                   +  - ]
     386                 :         39 :         case GCR_OPENPGP_ALGO_RSA:
     387                 :         39 :                 return "cse";
     388                 :          0 :         case GCR_OPENPGP_ALGO_RSA_E:
     389                 :          0 :                 return "e";
     390                 :          0 :         case GCR_OPENPGP_ALGO_RSA_S:
     391                 :          0 :                 return "s";
     392                 :          6 :         case GCR_OPENPGP_ALGO_ELG_E:
     393                 :          6 :                 return "e";
     394                 :         27 :         case GCR_OPENPGP_ALGO_DSA:
     395                 :         27 :                 return "sca";
     396                 :          0 :         default:
     397                 :          0 :                 return "";
     398                 :            :         }
     399                 :            : }
     400                 :            : 
     401                 :            : static gboolean
     402                 :         84 : parse_public_key_or_subkey (GQuark schema,
     403                 :            :                             guint n_columns,
     404                 :            :                             const guchar *beg,
     405                 :            :                             const guchar **at,
     406                 :            :                             const guchar *end,
     407                 :            :                             GcrOpenpgpParseFlags flags,
     408                 :            :                             GPtrArray *records)
     409                 :            : {
     410                 :         84 :         gchar *fingerprint = NULL;
     411                 :            :         gchar *keyid;
     412                 :            :         GcrRecord *record;
     413                 :            :         guint8 version;
     414                 :            :         guint32 timestamp;
     415                 :         84 :         guint16 ndays = 0;
     416                 :            :         guint8 algo;
     417                 :            :         guint16 bits;
     418                 :            :         gulong expiry;
     419                 :            :         const guchar *data;
     420                 :            : 
     421                 :            :         /* Start of actual key data in packet */
     422                 :         84 :         data = *at;
     423                 :            : 
     424                 :            :         /* First byte is version */
     425         [ -  + ]:         84 :         if (!read_byte (at, end, &version))
     426                 :          0 :                 return FALSE;
     427   [ +  -  -  + ]:         84 :         if (version < 2 || version > 4)
     428                 :          0 :                 return FALSE;
     429                 :            : 
     430                 :            :         /* Next a 4 byte create date */
     431         [ -  + ]:         84 :         if (!read_uint32 (at, end, &timestamp))
     432                 :          0 :                 return FALSE;
     433                 :            :         /* If version 2 or 3, validity days comes next */
     434         [ -  + ]:         84 :         if (version < 4) {
     435         [ #  # ]:          0 :                 if (!read_uint16 (at, end, &ndays))
     436                 :          0 :                         return FALSE;
     437                 :            :         }
     438                 :            : 
     439                 :            :         /* Algorithm */
     440         [ -  + ]:         84 :         if (!read_byte (at, end, &algo))
     441                 :          0 :                 return FALSE;
     442                 :            : 
     443                 :            :         /* For version 2 and 3, only RSA, keyid is low 64-bits of modulus */
     444         [ -  + ]:         84 :         if (version < 4) {
     445         [ #  # ]:          0 :                 if (!parse_v3_rsa_bits_and_keyid (at, end, &bits, &keyid))
     446                 :          0 :                         return FALSE;
     447                 :            : 
     448                 :            :         /* For version 4 */
     449                 :            :         } else {
     450         [ -  + ]:         84 :                 if (!parse_v4_algo_bits (at, end, algo, &bits))
     451                 :          0 :                         return FALSE;
     452                 :         84 :                 keyid = hash_v4_keyid (data, *at, &fingerprint);
     453                 :            :         }
     454                 :            : 
     455                 :         84 :         record = _gcr_record_new (schema, n_columns, ':');
     456                 :         84 :         _gcr_record_set_uint (record, GCR_RECORD_KEY_BITS, bits);
     457                 :         84 :         _gcr_record_set_uint (record, GCR_RECORD_KEY_ALGO, algo);
     458                 :         84 :         _gcr_record_take_raw (record, GCR_RECORD_KEY_KEYID, keyid);
     459                 :         84 :         _gcr_record_set_ulong (record, GCR_RECORD_KEY_TIMESTAMP, timestamp);
     460   [ +  +  +  + ]:         84 :         if (schema != GCR_RECORD_SCHEMA_SEC && schema != GCR_RECORD_SCHEMA_SSB)
     461                 :         72 :                 _gcr_record_set_raw (record, GCR_RECORD_PUB_CAPS, default_caps_for_algo (algo));
     462                 :            : 
     463         [ -  + ]:         84 :         if (ndays > 0) {
     464                 :          0 :                 expiry = (gulong)timestamp + ((gulong)ndays * 86400);
     465                 :          0 :                 _gcr_record_set_ulong (record, GCR_RECORD_KEY_EXPIRY, expiry);
     466                 :            :         }
     467                 :            : 
     468                 :         84 :         g_ptr_array_add (records, record);
     469                 :            : 
     470   [ +  -  +  +  :         84 :         if (fingerprint && (schema == GCR_RECORD_SCHEMA_PUB || schema == GCR_RECORD_SCHEMA_SEC)) {
                   +  + ]
     471                 :         42 :                 record = _gcr_record_new (GCR_RECORD_SCHEMA_FPR, GCR_RECORD_FPR_MAX, ':');
     472                 :         42 :                 _gcr_record_take_raw (record, GCR_RECORD_FPR_FINGERPRINT, fingerprint);
     473                 :         42 :                 g_ptr_array_add (records, record);
     474                 :         42 :                 fingerprint = NULL;
     475                 :            :         }
     476                 :            : 
     477                 :         84 :         g_free (fingerprint);
     478                 :         84 :         return TRUE;
     479                 :            : }
     480                 :            : 
     481                 :            : static gboolean
     482                 :         12 : parse_secret_key_or_subkey (GQuark schema,
     483                 :            :                             const guchar *beg,
     484                 :            :                             const guchar **at,
     485                 :            :                             const guchar *end,
     486                 :            :                             GcrOpenpgpParseFlags flags,
     487                 :            :                             GPtrArray *records)
     488                 :            : {
     489                 :            :         /*
     490                 :            :          * Identical to a public key, with extra crap after it. The
     491                 :            :          * extra crap is hard to parse and doesn't add anything to
     492                 :            :          * the records, so just skip over it.
     493                 :            :          *
     494                 :            :          * Also don't print out trust, that doesn't make sense for
     495                 :            :          * secret keys.
     496                 :            :          */
     497                 :            : 
     498         [ -  + ]:         12 :         if (!parse_public_key_or_subkey (schema, GCR_RECORD_SEC_MAX,
     499                 :            :                                          beg, at, end, flags, records))
     500                 :          0 :                 return FALSE;
     501                 :            : 
     502                 :         12 :         *at = end;
     503                 :         12 :         return TRUE;
     504                 :            : }
     505                 :            : 
     506                 :            : static gboolean
     507                 :         75 : parse_user_id (const guchar *beg,
     508                 :            :                const guchar **at,
     509                 :            :                const guchar *end,
     510                 :            :                GcrOpenpgpParseFlags flags,
     511                 :            :                GPtrArray *records)
     512                 :            : {
     513                 :            :         gchar *string;
     514                 :            :         GcrRecord *record;
     515                 :            :         gchar *fingerprint;
     516                 :            : 
     517         [ -  + ]:         75 :         g_assert (at);
     518   [ +  -  +  -  :         75 :         if (!*at || !end || *at > end)
                   -  + ]
     519                 :          0 :                 return FALSE;
     520                 :            : 
     521                 :         75 :         string = g_strndup ((gchar *)*at, end - *at);
     522                 :            : 
     523                 :         75 :         fingerprint = hash_user_id_or_attribute (*at, end);
     524                 :         75 :         record = _gcr_record_new (GCR_RECORD_SCHEMA_UID, GCR_RECORD_UID_MAX, ':');
     525                 :         75 :         _gcr_record_take_raw (record, GCR_RECORD_UID_FINGERPRINT, fingerprint);
     526                 :         75 :         _gcr_record_set_string (record, GCR_RECORD_UID_USERID, string);
     527                 :         75 :         g_free (string);
     528                 :            : 
     529                 :         75 :         g_ptr_array_add (records, record);
     530                 :            : 
     531                 :         75 :         *at = end;
     532                 :         75 :         return TRUE;
     533                 :            : }
     534                 :            : 
     535                 :            : static gboolean
     536                 :          6 : parse_user_attribute_packet (const guchar *beg,
     537                 :            :                              const guchar **at,
     538                 :            :                              const guchar *end,
     539                 :            :                              guchar subpkt_type,
     540                 :            :                              GPtrArray *records)
     541                 :            : {
     542                 :            :         GcrRecord *record;
     543                 :            :         gchar *fingerprint;
     544                 :            : 
     545                 :          6 :         record = _gcr_record_new (GCR_RECORD_SCHEMA_XA1, GCR_RECORD_XA1_MAX, ':');
     546                 :          6 :         _gcr_record_set_uint (record, GCR_RECORD_XA1_LENGTH, end - *at);
     547                 :          6 :         _gcr_record_set_uint (record, GCR_RECORD_XA1_TYPE, subpkt_type);
     548                 :          6 :         fingerprint = hash_user_id_or_attribute (*at, end);
     549                 :          6 :         _gcr_record_take_raw (record, GCR_RECORD_XA1_FINGERPRINT, fingerprint);
     550                 :          6 :         _gcr_record_set_base64 (record, GCR_RECORD_XA1_DATA, *at, end - *at);
     551                 :            : 
     552                 :          6 :         g_ptr_array_add (records, record);
     553                 :            : 
     554                 :          6 :         *at = end;
     555                 :          6 :         return TRUE;
     556                 :            : }
     557                 :            : 
     558                 :            : static gboolean
     559                 :          9 : parse_user_attribute (const guchar *beg,
     560                 :            :                       const guchar **at,
     561                 :            :                       const guchar *end,
     562                 :            :                       GcrOpenpgpParseFlags flags,
     563                 :            :                       GPtrArray *records)
     564                 :            : {
     565                 :            :         gsize subpkt_len;
     566                 :          9 :         guint count = 0;
     567                 :            :         const guchar *start;
     568                 :            :         const guchar *subpkt_beg;
     569                 :            :         guint8 subpkt_type;
     570                 :            :         gchar *fingerprint;
     571                 :            :         gchar *string;
     572                 :            :         GcrRecord *record;
     573                 :            : 
     574                 :          9 :         start = *at;
     575         [ +  + ]:         18 :         while (*at != end) {
     576                 :          9 :                 subpkt_beg = *at;
     577                 :            : 
     578   [ +  -  -  + ]:         18 :                 if (!read_new_length (at, end, &subpkt_len) ||
     579                 :          9 :                     !read_byte (at, end, &subpkt_type))
     580                 :          0 :                         return FALSE;
     581                 :            : 
     582                 :          9 :                 count++;
     583                 :            : 
     584         [ +  + ]:          9 :                 if (flags & GCR_OPENPGP_PARSE_ATTRIBUTES) {
     585         [ -  + ]:          6 :                         if (!parse_user_attribute_packet (subpkt_beg, at,
     586                 :          6 :                                                           *at + (subpkt_len - 1),
     587                 :            :                                                           subpkt_type, records))
     588                 :          0 :                                 return FALSE;
     589                 :            : 
     590                 :            :                 /* We already progressed one extra byte for the subpkt_type */
     591                 :            :                 } else {
     592                 :          3 :                         *at += (subpkt_len - 1);
     593                 :            :                 }
     594                 :            :         }
     595                 :            : 
     596                 :          9 :         fingerprint = hash_user_id_or_attribute (start, end);
     597                 :          9 :         string = g_strdup_printf ("%d %d", count, (guint)(*at - start));
     598                 :          9 :         record = _gcr_record_new (GCR_RECORD_SCHEMA_UAT, GCR_RECORD_UAT_MAX, ':');
     599                 :          9 :         _gcr_record_take_raw (record, GCR_RECORD_UAT_FINGERPRINT, fingerprint);
     600                 :          9 :         _gcr_record_take_raw (record, GCR_RECORD_UAT_COUNT_SIZE, string);
     601                 :            : 
     602                 :          9 :         g_ptr_array_add (records, record);
     603                 :          9 :         return TRUE;
     604                 :            : }
     605                 :            : 
     606                 :            : static gboolean
     607                 :        129 : skip_signature_mpis (const guchar **at,
     608                 :            :                      const guchar *end,
     609                 :            :                      guint8 algo)
     610                 :            : {
     611      [ +  +  - ]:        129 :         switch (algo) {
     612                 :            : 
     613                 :            :         /* RSA signature value */
     614                 :         52 :         case GCR_OPENPGP_ALGO_RSA:
     615                 :         52 :                 return read_mpi (at, end, NULL, NULL);
     616                 :            : 
     617                 :            :         /* DSA values r and s */
     618                 :         77 :         case GCR_OPENPGP_ALGO_DSA:
     619   [ +  -  +  - ]:        154 :                 return read_mpi (at, end, NULL, NULL) &&
     620                 :         77 :                        read_mpi (at, end, NULL, NULL);
     621                 :          0 :         default:
     622                 :          0 :                 return FALSE;
     623                 :            :         }
     624                 :            : }
     625                 :            : 
     626                 :            : static gboolean
     627                 :          0 : parse_v3_signature (const guchar **at,
     628                 :            :                     const guchar *end,
     629                 :            :                     GcrOpenpgpParseFlags flags,
     630                 :            :                     GPtrArray *records)
     631                 :            : {
     632                 :            :         guchar keyid[8];
     633                 :            :         guint8 sig_type;
     634                 :            :         guint8 sig_len;
     635                 :            :         guint32 sig_time;
     636                 :            :         guint8 key_algo;
     637                 :            :         guint8 hash_algo;
     638                 :            :         guint16 left_bits;
     639                 :            :         GcrRecord *record;
     640                 :            :         gchar *value;
     641                 :            : 
     642   [ #  #  #  # ]:          0 :         if (!read_byte (at, end, &sig_len) || sig_len != 5)
     643                 :          0 :                 return FALSE;
     644                 :            : 
     645   [ #  #  #  # ]:          0 :         if (!read_byte (at, end, &sig_type) ||
     646         [ #  # ]:          0 :             !read_uint32 (at, end, &sig_time) ||
     647         [ #  # ]:          0 :             !read_bytes (at, end, keyid, 8) ||
     648         [ #  # ]:          0 :             !read_byte (at, end, &key_algo) ||
     649         [ #  # ]:          0 :             !read_byte (at, end, &hash_algo) ||
     650         [ #  # ]:          0 :             !read_uint16 (at, end, &left_bits) ||
     651                 :          0 :             !skip_signature_mpis (at, end, key_algo))
     652                 :          0 :                 return FALSE;
     653                 :            : 
     654         [ #  # ]:          0 :         if (flags & GCR_OPENPGP_PARSE_SIGNATURES) {
     655                 :          0 :                 record = _gcr_record_new (GCR_RECORD_SCHEMA_SIG, GCR_RECORD_SIG_MAX, ':');
     656                 :          0 :                 _gcr_record_set_uint (record, GCR_RECORD_SIG_ALGO, key_algo);
     657                 :          0 :                 value = egg_hex_encode_full (keyid, sizeof (keyid), TRUE, NULL, 0);
     658                 :          0 :                 _gcr_record_take_raw (record, GCR_RECORD_SIG_KEYID, value);
     659                 :          0 :                 _gcr_record_set_ulong (record, GCR_RECORD_SIG_TIMESTAMP, sig_time);
     660                 :          0 :                 value = g_strdup_printf ("%02xx", (guint)sig_type);
     661                 :          0 :                 _gcr_record_take_raw (record, GCR_RECORD_SIG_CLASS, value);
     662                 :          0 :                 g_ptr_array_add (records, record);
     663                 :            :         }
     664                 :            : 
     665                 :          0 :         return TRUE;
     666                 :            : }
     667                 :            : 
     668                 :            : typedef struct {
     669                 :            :         gulong key_expiry;
     670                 :            :         gboolean exportable;
     671                 :            :         gboolean primary;
     672                 :            :         guint8 key_flags;
     673                 :            :         GcrRecord *revocation;
     674                 :            : } SigSubpacket;
     675                 :            : 
     676                 :            : static gboolean
     677                 :          3 : parse_v4_signature_revocation (const guchar **at,
     678                 :            :                                const guchar *end,
     679                 :            :                                GcrRecord *revocation)
     680                 :            : {
     681                 :            :         guchar fingerprint[20];
     682                 :            :         gchar *value;
     683                 :            :         guint8 klass;
     684                 :            :         guint8 algo;
     685                 :            : 
     686   [ +  -  +  - ]:          6 :         if (!read_byte (at, end, &klass) ||
     687         [ -  + ]:          6 :             !read_byte (at, end, &algo) ||
     688                 :          3 :             !read_bytes (at, end, fingerprint, 20))
     689                 :          0 :                 return FALSE;
     690                 :            : 
     691                 :          3 :         _gcr_record_set_uint (revocation, GCR_RECORD_RVK_ALGO, algo);
     692                 :          3 :         value = egg_hex_encode_full (fingerprint, 20, TRUE, NULL, 0);
     693                 :          3 :         _gcr_record_take_raw (revocation, GCR_RECORD_RVK_FINGERPRINT, value);
     694                 :          3 :         value = g_strdup_printf ("%02X", (guint)klass);
     695                 :          3 :         _gcr_record_take_raw (revocation, GCR_RECORD_RVK_CLASS, value);
     696                 :            : 
     697                 :          3 :         return TRUE;
     698                 :            : }
     699                 :            : 
     700                 :            : static gboolean
     701                 :        822 : parse_v4_signature_subpacket (const guchar **at,
     702                 :            :                               const guchar *end,
     703                 :            :                               guint8 sub_type,
     704                 :            :                               GcrRecord *record,
     705                 :            :                               SigSubpacket *subpkt)
     706                 :            : {
     707                 :            :         guchar keyid[8];
     708                 :            :         guint32 when;
     709                 :            :         guint8 byte;
     710                 :            :         gboolean critical;
     711                 :            :         gchar *value;
     712                 :            : 
     713                 :        822 :         critical = (sub_type & 0x80) ? TRUE : FALSE;
     714                 :        822 :         sub_type &= ~0xC0;
     715                 :            : 
     716   [ +  +  +  -  :        822 :         switch (sub_type) {
          -  +  +  -  +  
                   +  + ]
     717                 :        129 :         case OPENPGP_SIG_CREATION:
     718         [ -  + ]:        129 :                 if (!read_uint32 (at, end, &when))
     719                 :          0 :                         return FALSE;
     720                 :        129 :                 _gcr_record_set_ulong (record, GCR_RECORD_SIG_TIMESTAMP, when);
     721                 :        129 :                 return TRUE;
     722                 :        129 :         case OPENPGP_SIG_ISSUER:
     723         [ -  + ]:        129 :                 if (!read_bytes (at, end, keyid, 8))
     724                 :          0 :                         return FALSE;
     725                 :        129 :                 value = egg_hex_encode_full (keyid, 8, TRUE, NULL, 0);
     726                 :        129 :                 _gcr_record_take_raw (record, GCR_RECORD_SIG_KEYID, value);
     727                 :        129 :                 return TRUE;
     728                 :         81 :         case OPENPGP_SIG_KEY_EXPIRY:
     729         [ -  + ]:         81 :                 if (!read_uint32 (at, end, &when))
     730                 :          0 :                         return FALSE;
     731                 :         81 :                 subpkt->key_expiry = when;
     732                 :         81 :                 return TRUE;
     733                 :          0 :         case OPENPGP_SIG_EXPIRY:
     734         [ #  # ]:          0 :                 if (!read_uint32 (at, end, &when))
     735                 :          0 :                         return FALSE;
     736                 :          0 :                 _gcr_record_set_ulong (record, GCR_RECORD_SIG_EXPIRY, when);
     737                 :          0 :                 return TRUE;
     738                 :          0 :         case OPENPGP_SIG_EXPORTABLE:
     739         [ #  # ]:          0 :                 if (!read_byte (at, end, &byte))
     740                 :          0 :                         return FALSE;
     741   [ #  #  #  # ]:          0 :                 if (byte != 0 && byte != 1)
     742                 :          0 :                         return FALSE;
     743                 :          0 :                 subpkt->exportable = (byte == 0 ? FALSE : TRUE);
     744                 :          0 :                 return TRUE;
     745                 :            : 
     746                 :         13 :         case OPENPGP_SIG_PRIMARY_USERID:
     747         [ -  + ]:         13 :                 if (!read_byte (at, end, &byte))
     748                 :          0 :                         return FALSE;
     749   [ +  -  -  + ]:         13 :                 if (byte != 0 && byte != 1)
     750                 :          0 :                         return FALSE;
     751                 :         13 :                 subpkt->primary = byte;
     752                 :         13 :                 return TRUE;
     753                 :            : 
     754                 :         87 :         case OPENPGP_SIG_KEY_FLAGS:
     755         [ -  + ]:         87 :                 if (!read_byte (at, end, &byte))
     756                 :          0 :                         return FALSE;
     757                 :         87 :                 *at = end; /* N octets of flags */
     758                 :         87 :                 subpkt->key_flags = byte;
     759                 :         87 :                 return TRUE;
     760                 :            : 
     761                 :          0 :         case OPENPGP_SIG_SIGNER_USERID:
     762                 :          0 :                 value = g_strndup ((gchar *)*at, end - *at);
     763                 :          0 :                 _gcr_record_set_string (record, GCR_RECORD_SIG_USERID, value);
     764                 :          0 :                 g_free (value);
     765                 :          0 :                 return TRUE;
     766                 :            : 
     767                 :          3 :         case OPENPGP_SIG_REVOCATION_KEY:
     768                 :          3 :                 _gcr_record_free (subpkt->revocation);
     769                 :          3 :                 subpkt->revocation = _gcr_record_new (GCR_RECORD_SCHEMA_RVK, GCR_RECORD_RVK_MAX, ':');
     770                 :          3 :                 return parse_v4_signature_revocation (at, end, subpkt->revocation);
     771                 :            : 
     772                 :            :         /* Ignored */
     773                 :        354 :         case OPENPGP_SIG_SYMMETRIC_ALGOS:
     774                 :            :         case OPENPGP_SIG_HASH_ALGOS:
     775                 :            :         case OPENPGP_SIG_COMPRESSION_ALGOS:
     776                 :            :         case OPENPGP_SIG_REVOCABLE:
     777                 :            :         case OPENPGP_SIG_TRUST:
     778                 :            :         case OPENPGP_SIG_REGULAR_EXPRESSION:
     779                 :            :         case OPENPGP_SIG_NOTATION_DATA:
     780                 :            :         case OPENPGP_SIG_KEYSERVER_PREFS:
     781                 :            :         case OPENPGP_SIG_PREFERRED_KEYSERVER:
     782                 :            :         case OPENPGP_SIG_POLICY_URI:
     783                 :            :         case OPENPGP_SIG_REVOCATION_REASON:
     784                 :            :         case OPENPGP_SIG_FEATURES:
     785                 :            :         case OPENPGP_SIG_TARGET:
     786                 :            :         case OPENPGP_SIG_EMBEDDED_SIGNATURE:
     787                 :        354 :                 *at = end;
     788                 :        354 :                 return TRUE;
     789                 :            : 
     790                 :            :         /* Unrecognized */
     791                 :         26 :         default:
     792                 :            :                 /* Critical, but not recognized */
     793         [ -  + ]:         26 :                 if (critical)
     794                 :          0 :                         return FALSE;
     795                 :         26 :                 *at = end;
     796                 :         26 :                 return TRUE;
     797                 :            :         }
     798                 :            : 
     799                 :            : }
     800                 :            : 
     801                 :            : static gboolean
     802                 :        258 : parse_v4_signature_subpackets (const guchar **at,
     803                 :            :                                const guchar *end,
     804                 :            :                                GcrRecord *record,
     805                 :            :                                SigSubpacket *subpkt)
     806                 :            : {
     807                 :            :         gsize length;
     808                 :            :         guint8 sub_type;
     809                 :            :         const guchar *stop;
     810                 :            : 
     811         [ +  + ]:       1080 :         while (*at != end) {
     812   [ +  -  +  - ]:       1644 :                 if (!read_new_length (at, end, &length) ||
     813                 :        822 :                     !read_byte (at, end, &sub_type) ||
     814         [ -  + ]:        822 :                     length == 0)
     815                 :          0 :                         return FALSE;
     816                 :            : 
     817                 :            :                 /* The length includes the sub_type */
     818                 :        822 :                 length--;
     819                 :        822 :                 stop = *at + length;
     820         [ -  + ]:        822 :                 if (stop > end)
     821                 :          0 :                         return FALSE;
     822                 :            : 
     823                 :            :                 /* Actually parse the sub packets */
     824         [ -  + ]:        822 :                 if (!parse_v4_signature_subpacket (at, stop, sub_type, record, subpkt))
     825                 :          0 :                         return FALSE;
     826         [ -  + ]:        822 :                 if (*at != stop)
     827                 :          0 :                         return FALSE;
     828                 :            :         }
     829                 :            : 
     830                 :        258 :         return TRUE;
     831                 :            : }
     832                 :            : 
     833                 :            : static GcrRecord *
     834                 :         75 : uid_or_uat_find_for_self_signature (GPtrArray *records,
     835                 :            :                                     guint8 sig_type)
     836                 :            : {
     837                 :            :         GcrRecord *record;
     838                 :            :         GQuark schema;
     839                 :            : 
     840         [ -  + ]:         75 :         if (records->len == 0)
     841                 :          0 :                 return NULL;
     842                 :            : 
     843         [ +  - ]:         75 :         switch (sig_type) {
     844                 :            :         /* Generic certification of a key or userid */
     845                 :         75 :         case 0x10: case 0x11: case 0x12: case 0x13:
     846                 :         75 :                 record = records->pdata[records->len - 1];
     847                 :         75 :                 schema = _gcr_record_get_schema (record);
     848   [ +  +  +  - ]:         84 :                 if (schema == GCR_RECORD_SCHEMA_UID ||
     849                 :          9 :                     schema == GCR_RECORD_SCHEMA_UAT)
     850                 :         75 :                         return record;
     851                 :          0 :                 return NULL;
     852                 :            : 
     853                 :          0 :         default:
     854                 :          0 :                 return NULL;
     855                 :            :         }
     856                 :            : 
     857                 :            : }
     858                 :            : 
     859                 :            : static GcrRecord *
     860                 :        129 : key_or_sub_find_for_self_signature (GPtrArray *records,
     861                 :            :                                     guint8 sig_type,
     862                 :            :                                     const gchar *keyid)
     863                 :            : {
     864                 :            :         GcrRecord *record;
     865                 :            :         const gchar *check;
     866                 :            :         GQuark schema;
     867                 :            :         gint i;
     868                 :            : 
     869         [ -  + ]:        129 :         if (records->len == 0)
     870                 :          0 :                 return NULL;
     871                 :            : 
     872      [ +  +  + ]:        129 :         switch (sig_type) {
     873                 :            :         /* Generic certification of a key or userid */
     874                 :         84 :         case 0x10: case 0x11: case 0x12: case 0x13:
     875         [ +  - ]:        426 :                 for (i = records->len - 1; i >= 0; i--) {
     876                 :        426 :                         record = records->pdata[i];
     877                 :        426 :                         schema = _gcr_record_get_schema (record);
     878   [ +  +  +  + ]:        426 :                         if (schema == GCR_RECORD_SCHEMA_PUB || schema == GCR_RECORD_SCHEMA_SEC) {
     879                 :         84 :                                 check = _gcr_record_get_raw (record, GCR_RECORD_KEY_KEYID);
     880   [ +  -  +  - ]:         84 :                                 return (check != NULL && g_str_equal (check, keyid)) ? record : NULL;
     881                 :            :                         }
     882                 :            :                 }
     883                 :          0 :                 return NULL;
     884                 :            : 
     885                 :            :         /* (Primary) Subkey Binding Signature */
     886                 :         42 :         case 0x18: case 0x19:
     887                 :         42 :                 record = records->pdata[records->len - 1];
     888                 :         42 :                 schema = _gcr_record_get_schema (record);
     889         [ +  + ]:         42 :                 if (schema == GCR_RECORD_SCHEMA_SUB)
     890                 :         36 :                         return record;
     891                 :          6 :                 return NULL;
     892                 :            : 
     893                 :          3 :         default:
     894                 :          3 :                 return NULL;
     895                 :            :         }
     896                 :            : }
     897                 :            : 
     898                 :            : static void
     899                 :         81 : pub_or_sub_set_key_caps (GcrRecord *record,
     900                 :            :                          guint8 key_flags)
     901                 :            : {
     902                 :            :         GString *string;
     903                 :            :         GQuark schema;
     904                 :            : 
     905                 :         81 :         schema = _gcr_record_get_schema (record);
     906   [ +  +  -  + ]:         81 :         if (schema == GCR_RECORD_SCHEMA_SEC || schema == GCR_RECORD_SCHEMA_SSB)
     907                 :          9 :                 return;
     908                 :            : 
     909                 :         72 :         string = g_string_sized_new (8);
     910         [ +  + ]:         72 :         if (key_flags & 0x02)
     911                 :         49 :                 g_string_append_c (string, 's');
     912         [ +  + ]:         72 :         if (key_flags & 0x01)
     913                 :         42 :                 g_string_append_c (string, 'c');
     914   [ +  +  -  + ]:         72 :         if (key_flags & 0x04 || key_flags & 0x08)
     915                 :         23 :                 g_string_append_c (string, 'e');
     916         [ -  + ]:         72 :         if (key_flags & 0x20)
     917                 :          0 :                 g_string_append_c (string, 'a');
     918                 :            : 
     919                 :         72 :         _gcr_record_take_raw (record, GCR_RECORD_PUB_CAPS,
     920                 :            :                               g_string_free (string, FALSE));
     921                 :            : }
     922                 :            : 
     923                 :            : static gboolean
     924                 :        129 : parse_v4_signature (const guchar **at,
     925                 :            :                     const guchar *end,
     926                 :            :                     GcrOpenpgpParseFlags flags,
     927                 :            :                     GPtrArray *records)
     928                 :            : {
     929                 :            :         guint8 sig_type;
     930                 :            :         guint8 key_algo;
     931                 :            :         guint8 hash_algo;
     932                 :            :         guint16 hashed_len;
     933                 :            :         guint16 unhashed_len;
     934                 :            :         guint16 left_bits;
     935                 :            :         GcrRecord *record;
     936                 :            :         GcrRecord *key, *uid;
     937                 :            :         const gchar *keyid;
     938                 :            :         gchar *value;
     939                 :            :         const guchar *stop;
     940                 :            :         gulong timestamp;
     941                 :            : 
     942                 :            :         /* Information to transfer back onto the key record */
     943                 :        129 :         SigSubpacket subpkt = { 0, };
     944                 :        129 :         subpkt.exportable = 1;
     945                 :            : 
     946   [ +  -  +  - ]:        258 :         if (!read_byte (at, end, &sig_type) ||
     947         [ +  - ]:        258 :             !read_byte (at, end, &key_algo) ||
     948         [ -  + ]:        258 :             !read_byte (at, end, &hash_algo) ||
     949                 :        129 :             !read_uint16 (at, end, &hashed_len))
     950                 :          0 :                 return FALSE;
     951                 :            : 
     952                 :            :         /* Hashed subpackets which we use */
     953                 :        129 :         record = _gcr_record_new (GCR_RECORD_SCHEMA_SIG, GCR_RECORD_SIG_MAX, ':');
     954                 :        129 :         stop = *at + hashed_len;
     955   [ +  -  -  + ]:        258 :         if (stop > end ||
     956                 :        129 :             !parse_v4_signature_subpackets (at, stop, record, &subpkt)) {
     957                 :          0 :                 _gcr_record_free (record);
     958                 :          0 :                 _gcr_record_free (subpkt.revocation);
     959                 :          0 :                 return FALSE;
     960                 :            :         }
     961                 :            : 
     962                 :            :         /* Includes unhashed subpackets, which we skip over */
     963         [ -  + ]:        129 :         if (!read_uint16 (at, end, &unhashed_len)) {
     964                 :          0 :                 _gcr_record_free (record);
     965                 :          0 :                 _gcr_record_free (subpkt.revocation);
     966                 :          0 :                 return FALSE;
     967                 :            :         }
     968                 :            : 
     969                 :        129 :         stop = *at + unhashed_len;
     970   [ +  -  +  - ]:        258 :         if (stop > end ||
     971         [ +  - ]:        258 :             !parse_v4_signature_subpackets (at, stop, record, &subpkt) ||
     972         [ -  + ]:        258 :             !read_uint16 (at, end, &left_bits) ||
     973                 :        129 :             !skip_signature_mpis (at, end, key_algo)) {
     974                 :          0 :                 _gcr_record_free (record);
     975                 :          0 :                 _gcr_record_free (subpkt.revocation);
     976                 :          0 :                 return FALSE;
     977                 :            :         }
     978                 :            : 
     979         [ +  + ]:        129 :         if (subpkt.revocation) {
     980                 :          3 :                 g_ptr_array_add (records, subpkt.revocation);
     981                 :          3 :                 subpkt.revocation = NULL;
     982                 :            :         }
     983                 :            : 
     984                 :            :         /* Fill in information on previous key or subkey */
     985                 :        129 :         keyid = _gcr_record_get_raw (record, GCR_RECORD_SIG_KEYID);
     986                 :        129 :         key = key_or_sub_find_for_self_signature (records, sig_type, keyid);
     987         [ +  + ]:        129 :         if (key != NULL) {
     988         [ +  + ]:        120 :                 if (subpkt.key_expiry != 0) {
     989         [ +  - ]:         78 :                         if (_gcr_record_get_ulong (key, GCR_RECORD_KEY_TIMESTAMP, &timestamp))
     990                 :         78 :                                 _gcr_record_set_ulong (key, GCR_RECORD_KEY_EXPIRY, timestamp + subpkt.key_expiry);
     991                 :            :                 }
     992         [ +  + ]:        120 :                 if (subpkt.key_flags != 0)
     993                 :         81 :                         pub_or_sub_set_key_caps (key, subpkt.key_flags);
     994                 :            :         }
     995                 :            : 
     996   [ +  +  +  + ]:        129 :         if (key && _gcr_record_get_schema (key) == GCR_RECORD_SCHEMA_PUB) {
     997                 :         75 :                 uid = uid_or_uat_find_for_self_signature (records, sig_type);
     998         [ +  - ]:         75 :                 if (uid != NULL) {
     999         [ +  - ]:         75 :                         if (_gcr_record_get_ulong (record, GCR_RECORD_SIG_TIMESTAMP, &timestamp))
    1000                 :         75 :                                 _gcr_record_set_ulong (uid, GCR_RECORD_UID_TIMESTAMP, timestamp);
    1001                 :            :                 }
    1002                 :            :         }
    1003                 :            : 
    1004         [ +  + ]:        129 :         if (flags & GCR_OPENPGP_PARSE_SIGNATURES) {
    1005                 :         89 :                 _gcr_record_set_uint (record, GCR_RECORD_SIG_ALGO, key_algo);
    1006                 :         89 :                 value = g_strdup_printf ("%02x%s", (guint)sig_type,
    1007         [ +  - ]:         89 :                                          subpkt.exportable ? "x" : "l");
    1008                 :         89 :                 _gcr_record_take_raw (record, GCR_RECORD_SIG_CLASS, value);
    1009                 :         89 :                 g_ptr_array_add (records, record);
    1010                 :            :         } else {
    1011                 :         40 :                 _gcr_record_free (record);
    1012                 :            :         }
    1013                 :            : 
    1014                 :        129 :         return TRUE;
    1015                 :            : }
    1016                 :            : 
    1017                 :            : static gboolean
    1018                 :        129 : parse_signature (const guchar *beg,
    1019                 :            :                  const guchar **at,
    1020                 :            :                  const guchar *end,
    1021                 :            :                  GcrOpenpgpParseFlags flags,
    1022                 :            :                  GPtrArray *records)
    1023                 :            : {
    1024                 :            :         guint8 version;
    1025                 :            : 
    1026         [ -  + ]:        129 :         if (!read_byte (at, end, &version))
    1027                 :          0 :                 return FALSE;
    1028                 :            : 
    1029         [ -  + ]:        129 :         if (version == 3)
    1030                 :          0 :                 return parse_v3_signature (at, end, flags, records);
    1031         [ +  - ]:        129 :         else if (version == 4)
    1032                 :        129 :                 return parse_v4_signature (at, end, flags, records);
    1033                 :            :         else
    1034                 :          0 :                 return FALSE;
    1035                 :            : }
    1036                 :            : 
    1037                 :            : static GcrDataFormat
    1038                 :        390 : parse_openpgp_packet (const guchar *beg,
    1039                 :            :                       const guchar *at,
    1040                 :            :                       const guchar *end,
    1041                 :            :                       guint8 pkt_type,
    1042                 :            :                       GcrOpenpgpParseFlags flags,
    1043                 :            :                       GPtrArray *records)
    1044                 :            : {
    1045                 :            :         gboolean ret;
    1046                 :            : 
    1047   [ +  +  +  +  :        390 :         switch (pkt_type) {
             +  +  +  +  
                      - ]
    1048                 :         36 :         case OPENPGP_PKT_PUBLIC_KEY:
    1049                 :         36 :                 ret = parse_public_key_or_subkey (GCR_RECORD_SCHEMA_PUB, GCR_RECORD_PUB_MAX,
    1050                 :            :                                                   beg, &at, end, flags, records);
    1051                 :         36 :                 break;
    1052                 :         36 :         case OPENPGP_PKT_PUBLIC_SUBKEY:
    1053                 :         36 :                 ret = parse_public_key_or_subkey (GCR_RECORD_SCHEMA_SUB, GCR_RECORD_PUB_MAX,
    1054                 :            :                                                   beg, &at, end, flags, records);
    1055                 :         36 :                 break;
    1056                 :         75 :         case OPENPGP_PKT_USER_ID:
    1057                 :         75 :                 ret = parse_user_id (beg, &at, end, flags, records);
    1058                 :         75 :                 break;
    1059                 :          9 :         case OPENPGP_PKT_ATTRIBUTE:
    1060                 :          9 :                 ret = parse_user_attribute (beg, &at, end, flags, records);
    1061                 :          9 :                 break;
    1062                 :        129 :         case OPENPGP_PKT_SIGNATURE:
    1063                 :        129 :                 ret = parse_signature (beg, &at, end, flags, records);
    1064                 :        129 :                 break;
    1065                 :          6 :         case OPENPGP_PKT_SECRET_KEY:
    1066                 :          6 :                 ret = parse_secret_key_or_subkey (GCR_RECORD_SCHEMA_SEC,
    1067                 :            :                                                   beg, &at, end, flags, records);
    1068                 :          6 :                 break;
    1069                 :          6 :         case OPENPGP_PKT_SECRET_SUBKEY:
    1070                 :          6 :                 ret = parse_secret_key_or_subkey (GCR_RECORD_SCHEMA_SSB,
    1071                 :            :                                                   beg, &at, end, flags, records);
    1072                 :          6 :                 break;
    1073                 :            : 
    1074                 :            :         /* Stuff we don't want to be meddling with right now */
    1075                 :         93 :         case OPENPGP_PKT_RING_TRUST:
    1076                 :         93 :                 return GCR_SUCCESS;
    1077                 :            : 
    1078                 :            :         /* Ignore packets we don't understand */
    1079                 :          0 :         default:
    1080                 :          0 :                 return GCR_SUCCESS;
    1081                 :            :         }
    1082                 :            : 
    1083                 :            :         /* Key packet had extra data */
    1084   [ +  -  -  + ]:        297 :         if (ret == TRUE && at != end)
    1085                 :          0 :                 ret = FALSE;
    1086                 :            : 
    1087         [ +  - ]:        297 :         return ret ? GCR_SUCCESS : GCR_ERROR_FAILURE;
    1088                 :            : }
    1089                 :            : 
    1090                 :            : static void
    1091                 :         24 : append_key_capabilities (GString *string,
    1092                 :            :                          const gchar *caps)
    1093                 :            : {
    1094                 :            :         guint i;
    1095                 :            :         gchar cap;
    1096                 :            : 
    1097         [ +  + ]:         66 :         for (i = 0; caps[i] != 0; i++) {
    1098                 :         42 :                 cap = g_ascii_toupper (caps[i]);
    1099         [ +  + ]:         42 :                 if (!strchr (string->str, cap))
    1100                 :         36 :                         g_string_append_c (string, cap);
    1101                 :            :         }
    1102                 :         24 : }
    1103                 :            : 
    1104                 :            : static void
    1105                 :         12 : normalize_capabilities (GPtrArray *records)
    1106                 :            : {
    1107                 :            :         GString *string;
    1108                 :            :         GQuark schema;
    1109                 :            :         const gchar *caps;
    1110                 :            :         guint i;
    1111                 :            : 
    1112                 :            :         /* Gather the capabilities of all subkeys into the primary key */
    1113                 :         12 :         string = g_string_new (_gcr_record_get_raw (records->pdata[0], GCR_RECORD_PUB_CAPS));
    1114         [ +  + ]:        117 :         for (i = 0; i < records->len; i++) {
    1115                 :        105 :                 schema = _gcr_record_get_schema (records->pdata[i]);
    1116   [ +  +  +  + ]:        105 :                 if (schema == GCR_RECORD_SCHEMA_PUB || schema == GCR_RECORD_SCHEMA_SUB) {
    1117                 :         24 :                         caps = _gcr_record_get_raw (records->pdata[i], GCR_RECORD_PUB_CAPS);
    1118                 :         24 :                         append_key_capabilities (string, caps);
    1119                 :            :                 }
    1120                 :            :         }
    1121                 :         12 :         _gcr_record_take_raw (records->pdata[0], GCR_RECORD_PUB_CAPS,
    1122                 :            :                               g_string_free (string, FALSE));
    1123                 :         12 : }
    1124                 :            : 
    1125                 :            : static gboolean
    1126                 :         36 : check_key_expiry (GcrRecord *record)
    1127                 :            : {
    1128                 :            :         gulong expiry;
    1129                 :            :         time_t current;
    1130                 :            : 
    1131         [ +  - ]:         36 :         if (_gcr_record_get_ulong (record, GCR_RECORD_KEY_EXPIRY, &expiry)) {
    1132         [ +  + ]:         36 :                 if (expiry == 0)
    1133                 :         12 :                         return FALSE;
    1134                 :         24 :                 current = time (NULL);
    1135         [ +  - ]:         24 :                 if (current > expiry)
    1136                 :         24 :                         return TRUE;
    1137                 :            :         }
    1138                 :            : 
    1139                 :          0 :         return FALSE;
    1140                 :            : }
    1141                 :            : 
    1142                 :            : static void
    1143                 :        134 : normalize_key_records (GPtrArray *records)
    1144                 :            : {
    1145                 :            :         GQuark schema;
    1146                 :        134 :         guchar trust = 0;
    1147                 :            :         const gchar *prev;
    1148                 :        134 :         gboolean force = FALSE;
    1149                 :            :         guint i;
    1150                 :            : 
    1151         [ +  + ]:        134 :         if (records->len == 0)
    1152                 :         92 :                 return;
    1153                 :            : 
    1154                 :         42 :         schema = _gcr_record_get_schema (records->pdata[0]);
    1155         [ +  + ]:         42 :         if (schema == GCR_RECORD_SCHEMA_PUB) {
    1156                 :            : 
    1157         [ +  + ]:         36 :                 if (check_key_expiry (records->pdata[0])) {
    1158                 :         24 :                         trust = 'e';
    1159                 :         24 :                         force = TRUE;
    1160                 :            : 
    1161                 :            :                 /* Mark public keys as unknown trust */
    1162                 :            :                 } else {
    1163                 :         12 :                         normalize_capabilities (records);
    1164                 :         12 :                         trust = 'o';
    1165                 :         12 :                         force = FALSE;
    1166                 :            :                 }
    1167                 :            : 
    1168                 :            :                 /* Ownertrust unknown, new to system */
    1169                 :         36 :                 _gcr_record_set_char (records->pdata[0], GCR_RECORD_KEY_OWNERTRUST, 'o');
    1170                 :            : 
    1171         [ +  - ]:          6 :         } else if (schema == GCR_RECORD_SCHEMA_SEC) {
    1172                 :            : 
    1173                 :            :                 /* Trust doesn't make sense for secret keys */
    1174                 :          6 :                 trust = 0;
    1175                 :          6 :                 force = FALSE;
    1176                 :            :         }
    1177                 :            : 
    1178                 :            : 
    1179                 :            :         /* Setup default trust if necessary */
    1180         [ +  + ]:         42 :         if (trust != 0) {
    1181         [ +  + ]:        307 :                 for (i = 0; i < records->len; i++) {
    1182         [ +  + ]:        271 :                         if (!force) {
    1183                 :        105 :                                 prev = _gcr_record_get_raw (records->pdata[i], GCR_RECORD_TRUST);
    1184   [ +  -  -  + ]:        105 :                                 if (prev != NULL && prev[0])
    1185                 :          0 :                                         continue;
    1186                 :            :                         }
    1187                 :        271 :                         schema = _gcr_record_get_schema (records->pdata[i]);
    1188   [ +  +  +  + ]:        271 :                         if (schema != GCR_RECORD_SCHEMA_SIG && schema != GCR_RECORD_SCHEMA_FPR)
    1189                 :        156 :                                 _gcr_record_set_char (records->pdata[i], GCR_RECORD_TRUST, trust);
    1190                 :            :                 }
    1191                 :            :         }
    1192                 :            : }
    1193                 :            : 
    1194                 :            : typedef struct {
    1195                 :            :         GcrOpenpgpCallback callback;
    1196                 :            :         gpointer user_data;
    1197                 :            :         guint count;
    1198                 :            :         GBytes *backing;
    1199                 :            :         GPtrArray *records;
    1200                 :            : } openpgp_parse_closure;
    1201                 :            : 
    1202                 :            : static void
    1203                 :         76 : openpgp_parse_free (gpointer data)
    1204                 :            : {
    1205                 :         76 :         openpgp_parse_closure *closure = data;
    1206                 :         76 :         g_ptr_array_unref (closure->records);
    1207                 :         76 :         g_bytes_unref (closure->backing);
    1208                 :         76 :         g_free (closure);
    1209                 :         76 : }
    1210                 :            : 
    1211                 :            : static void
    1212                 :        134 : maybe_emit_openpgp_block (openpgp_parse_closure *closure,
    1213                 :            :                           const guchar *block,
    1214                 :            :                           const guchar *end)
    1215                 :            : {
    1216                 :            :         GBytes *outer;
    1217                 :            :         gsize length;
    1218                 :            :         GPtrArray *records;
    1219                 :            : 
    1220   [ +  +  -  + ]:        134 :         if (block == NULL || block == end)
    1221                 :         76 :                 return;
    1222                 :            : 
    1223         [ -  + ]:         58 :         g_assert (end != NULL);
    1224         [ -  + ]:         58 :         g_assert (end > block);
    1225                 :            : 
    1226                 :         58 :         length = end - block;
    1227                 :         58 :         closure->count++;
    1228                 :            : 
    1229                 :         58 :         records = closure->records;
    1230                 :         58 :         closure->records = g_ptr_array_new_with_free_func (_gcr_record_free);
    1231                 :            : 
    1232                 :         58 :         outer = g_bytes_new_with_free_func (block, length, (GDestroyNotify)g_bytes_unref,
    1233                 :         58 :                                               g_bytes_ref (closure->backing));
    1234         [ +  + ]:         58 :         if (closure->callback)
    1235                 :         42 :                 (closure->callback) (records, outer, closure->user_data);
    1236                 :         58 :         g_bytes_unref (outer);
    1237                 :            : 
    1238                 :         58 :         g_ptr_array_unref (records);
    1239                 :            : }
    1240                 :            : 
    1241                 :            : guint
    1242                 :         76 : _gcr_openpgp_parse (GBytes *data,
    1243                 :            :                     GcrOpenpgpParseFlags flags,
    1244                 :            :                     GcrOpenpgpCallback callback,
    1245                 :            :                     gpointer user_data)
    1246                 :            : {
    1247                 :            :         openpgp_parse_closure *closure;
    1248                 :            :         const guchar *at;
    1249                 :            :         const guchar *beg;
    1250                 :            :         const guchar *end;
    1251                 :            :         const guchar *block;
    1252                 :            :         guint8 pkt_type;
    1253                 :            :         GcrDataError res;
    1254                 :            :         gsize length;
    1255                 :            :         gboolean new_key;
    1256                 :            :         guint ret;
    1257                 :            : 
    1258         [ -  + ]:         76 :         g_return_val_if_fail (data != NULL, 0);
    1259                 :            : 
    1260                 :            :         /* For libgcrypt */
    1261                 :         76 :         _gcr_initialize_library ();
    1262                 :            : 
    1263                 :         76 :         at = g_bytes_get_data (data, NULL);
    1264                 :         76 :         end = at + g_bytes_get_size (data);
    1265                 :         76 :         block = NULL;
    1266                 :            : 
    1267                 :         76 :         closure = g_new0 (openpgp_parse_closure, 1);
    1268                 :         76 :         closure->callback = callback;
    1269                 :         76 :         closure->user_data = user_data;
    1270                 :         76 :         closure->backing = g_bytes_ref (data);
    1271                 :         76 :         closure->records = g_ptr_array_new_with_free_func (_gcr_record_free);
    1272                 :            : 
    1273   [ +  -  +  + ]:        610 :         while (at != NULL && at != end) {
    1274                 :        574 :                 beg = at;
    1275                 :        574 :                 res = read_openpgp_packet (&at, end, &pkt_type, &length);
    1276                 :            : 
    1277         [ +  + ]:        574 :                 if (res == GCR_SUCCESS) {
    1278         [ +  + ]:       1018 :                         new_key = (pkt_type == OPENPGP_PKT_PUBLIC_KEY ||
    1279         [ +  + ]:        484 :                                    pkt_type == OPENPGP_PKT_SECRET_KEY);
    1280   [ +  -  +  + ]:        534 :                         if (flags & GCR_OPENPGP_PARSE_KEYS && new_key)
    1281                 :         58 :                                 normalize_key_records (closure->records);
    1282                 :            :                         /* Start of a new set of packets, per key */
    1283   [ +  -  +  + ]:        534 :                         if (!(flags & GCR_OPENPGP_PARSE_KEYS) || new_key) {
    1284                 :         58 :                                 maybe_emit_openpgp_block (closure, block, beg);
    1285                 :         58 :                                 block = beg;
    1286                 :            :                         }
    1287         [ +  + ]:        534 :                         if (!(flags & GCR_OPENPGP_PARSE_NO_RECORDS))
    1288                 :        390 :                                 parse_openpgp_packet (beg, at, at + length, pkt_type,
    1289                 :            :                                                       flags, closure->records);
    1290                 :            :                 }
    1291                 :            : 
    1292         [ +  + ]:        574 :                 if (res != GCR_SUCCESS) {
    1293   [ -  +  -  - ]:         40 :                         if (block != NULL && block != beg)
    1294                 :          0 :                                 maybe_emit_openpgp_block (closure, block, beg);
    1295                 :         40 :                         block = NULL;
    1296                 :         40 :                         break;
    1297                 :            :                 }
    1298                 :            : 
    1299                 :        534 :                 at += length;
    1300                 :            :         }
    1301                 :            : 
    1302         [ +  - ]:         76 :         if (flags & GCR_OPENPGP_PARSE_KEYS)
    1303                 :         76 :                 normalize_key_records (closure->records);
    1304                 :         76 :         maybe_emit_openpgp_block (closure, block, at);
    1305                 :         76 :         ret = closure->count;
    1306                 :         76 :         openpgp_parse_free (closure);
    1307                 :         76 :         return ret;
    1308                 :            : }

Generated by: LCOV version 1.14