LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-info.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 77.7 % 103 80
Test Date: 2026-03-04 09:14:58 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * pgp-info.c
       3              :  *    Provide info about PGP data.
       4              :  *
       5              :  * Copyright (c) 2005 Marko Kreen
       6              :  * All rights reserved.
       7              :  *
       8              :  * Redistribution and use in source and binary forms, with or without
       9              :  * modification, are permitted provided that the following conditions
      10              :  * are met:
      11              :  * 1. Redistributions of source code must retain the above copyright
      12              :  *    notice, this list of conditions and the following disclaimer.
      13              :  * 2. Redistributions in binary form must reproduce the above copyright
      14              :  *    notice, this list of conditions and the following disclaimer in the
      15              :  *    documentation and/or other materials provided with the distribution.
      16              :  *
      17              :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      18              :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19              :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20              :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      21              :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22              :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23              :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24              :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25              :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26              :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27              :  * SUCH DAMAGE.
      28              :  *
      29              :  * contrib/pgcrypto/pgp-info.c
      30              :  */
      31              : #include "postgres.h"
      32              : 
      33              : #include "mbuf.h"
      34              : #include "pgp.h"
      35              : #include "px.h"
      36              : 
      37              : static int
      38           10 : read_pubkey_keyid(PullFilter *pkt, uint8 *keyid_buf)
      39              : {
      40              :     int         res;
      41           10 :     PGP_PubKey *pk = NULL;
      42              : 
      43           10 :     res = _pgp_read_public_key(pkt, &pk);
      44           10 :     if (res < 0)
      45            0 :         goto err;
      46              : 
      47              :     /* skip secret key part, if it exists */
      48           10 :     res = pgp_skip_packet(pkt);
      49           10 :     if (res < 0)
      50            0 :         goto err;
      51              : 
      52              :     /* is it encryption key */
      53           10 :     switch (pk->algo)
      54              :     {
      55           10 :         case PGP_PUB_ELG_ENCRYPT:
      56              :         case PGP_PUB_RSA_ENCRYPT:
      57              :         case PGP_PUB_RSA_ENCRYPT_SIGN:
      58           10 :             memcpy(keyid_buf, pk->key_id, 8);
      59           10 :             res = 1;
      60           10 :             break;
      61            0 :         default:
      62            0 :             res = 0;
      63              :     }
      64              : 
      65           10 : err:
      66           10 :     pgp_key_free(pk);
      67           10 :     return res;
      68              : }
      69              : 
      70              : static int
      71            5 : read_pubenc_keyid(PullFilter *pkt, uint8 *keyid_buf)
      72              : {
      73              :     uint8       ver;
      74              :     int         res;
      75              : 
      76            5 :     GETBYTE(pkt, ver);
      77            5 :     if (ver != 3)
      78            0 :         return -1;
      79              : 
      80            5 :     res = pullf_read_fixed(pkt, 8, keyid_buf);
      81            5 :     if (res < 0)
      82            0 :         return res;
      83              : 
      84            5 :     return pgp_skip_packet(pkt);
      85              : }
      86              : 
      87              : static const char hextbl[] = "0123456789ABCDEF";
      88              : 
      89              : static int
      90           15 : print_key(uint8 *keyid, char *dst)
      91              : {
      92              :     int         i;
      93              :     unsigned    c;
      94              : 
      95          135 :     for (i = 0; i < 8; i++)
      96              :     {
      97          120 :         c = keyid[i];
      98          120 :         *dst++ = hextbl[(c >> 4) & 0x0F];
      99          120 :         *dst++ = hextbl[c & 0x0F];
     100              :     }
     101           15 :     *dst = 0;
     102           15 :     return 8 * 2;
     103              : }
     104              : 
     105              : static const uint8 any_key[] =
     106              : {0, 0, 0, 0, 0, 0, 0, 0};
     107              : 
     108              : /*
     109              :  * dst should have room for 17 bytes
     110              :  */
     111              : int
     112           17 : pgp_get_keyid(MBuf *pgp_data, char *dst)
     113              : {
     114              :     int         res;
     115              :     PullFilter *src;
     116           17 :     PullFilter *pkt = NULL;
     117              :     int         len;
     118              :     uint8       tag;
     119           17 :     int         got_pub_key = 0,
     120           17 :                 got_symenc_key = 0,
     121           17 :                 got_pubenc_key = 0;
     122           17 :     int         got_data = 0;
     123              :     uint8       keyid_buf[8];
     124           17 :     int         got_main_key = 0;
     125              : 
     126              : 
     127           17 :     res = pullf_create_mbuf_reader(&src, pgp_data);
     128           17 :     if (res < 0)
     129            0 :         return res;
     130              : 
     131              :     while (1)
     132              :     {
     133           78 :         res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
     134           78 :         if (res <= 0)
     135           12 :             break;
     136           66 :         res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
     137           66 :         if (res < 0)
     138            0 :             break;
     139              : 
     140           66 :         switch (tag)
     141              :         {
     142           12 :             case PGP_PKT_SECRET_KEY:
     143              :             case PGP_PKT_PUBLIC_KEY:
     144              :                 /* main key is for signing, so ignore it */
     145           12 :                 if (!got_main_key)
     146              :                 {
     147           12 :                     got_main_key = 1;
     148           12 :                     res = pgp_skip_packet(pkt);
     149              :                 }
     150              :                 else
     151            0 :                     res = PXE_PGP_MULTIPLE_KEYS;
     152           12 :                 break;
     153           10 :             case PGP_PKT_SECRET_SUBKEY:
     154              :             case PGP_PKT_PUBLIC_SUBKEY:
     155           10 :                 res = read_pubkey_keyid(pkt, keyid_buf);
     156           10 :                 if (res < 0)
     157            0 :                     break;
     158           10 :                 if (res > 0)
     159           10 :                     got_pub_key++;
     160           10 :                 break;
     161            5 :             case PGP_PKT_PUBENCRYPTED_SESSKEY:
     162            5 :                 got_pubenc_key++;
     163            5 :                 res = read_pubenc_keyid(pkt, keyid_buf);
     164            5 :                 break;
     165            5 :             case PGP_PKT_SYMENCRYPTED_DATA:
     166              :             case PGP_PKT_SYMENCRYPTED_DATA_MDC:
     167              :                 /* don't skip it, just stop */
     168            5 :                 got_data = 1;
     169            5 :                 break;
     170            0 :             case PGP_PKT_SYMENCRYPTED_SESSKEY:
     171            0 :                 got_symenc_key++;
     172              :                 pg_fallthrough;
     173           34 :             case PGP_PKT_SIGNATURE:
     174              :             case PGP_PKT_MARKER:
     175              :             case PGP_PKT_TRUST:
     176              :             case PGP_PKT_USER_ID:
     177              :             case PGP_PKT_USER_ATTR:
     178              :             case PGP_PKT_PRIV_61:
     179           34 :                 res = pgp_skip_packet(pkt);
     180           34 :                 break;
     181            0 :             default:
     182            0 :                 res = PXE_PGP_CORRUPT_DATA;
     183              :         }
     184              : 
     185           66 :         if (pkt)
     186           66 :             pullf_free(pkt);
     187           66 :         pkt = NULL;
     188              : 
     189           66 :         if (res < 0 || got_data)
     190              :             break;
     191              :     }
     192              : 
     193           17 :     pullf_free(src);
     194           17 :     if (pkt)
     195            0 :         pullf_free(pkt);
     196              : 
     197           17 :     if (res < 0)
     198            0 :         return res;
     199              : 
     200              :     /* now check sanity */
     201           17 :     if (got_pub_key && got_pubenc_key)
     202            0 :         res = PXE_PGP_CORRUPT_DATA;
     203              : 
     204           17 :     if (got_pub_key > 1)
     205            0 :         res = PXE_PGP_MULTIPLE_KEYS;
     206              : 
     207           17 :     if (got_pubenc_key > 1)
     208            0 :         res = PXE_PGP_MULTIPLE_KEYS;
     209              : 
     210              :     /*
     211              :      * if still ok, look what we got
     212              :      */
     213           17 :     if (res >= 0)
     214              :     {
     215           17 :         if (got_pubenc_key || got_pub_key)
     216              :         {
     217           30 :             if (memcmp(keyid_buf, any_key, 8) == 0)
     218              :             {
     219            0 :                 memcpy(dst, "ANYKEY", 7);
     220            0 :                 res = 6;
     221              :             }
     222              :             else
     223           15 :                 res = print_key(keyid_buf, dst);
     224              :         }
     225            2 :         else if (got_symenc_key)
     226              :         {
     227            0 :             memcpy(dst, "SYMKEY", 7);
     228            0 :             res = 6;
     229              :         }
     230              :         else
     231            2 :             res = PXE_PGP_NO_USABLE_KEY;
     232              :     }
     233              : 
     234           17 :     return res;
     235              : }
        

Generated by: LCOV version 2.0-1