LCOV - differential code coverage report
Current view: top level - contrib/pgcrypto - pgp-pubdec.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 74.3 % 101 75 26 75
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 5 5 5
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*
       2                 :  * pgp-pubdec.c
       3                 :  *    Decrypt public-key encrypted session key.
       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-pubdec.c
      30                 :  */
      31                 : #include "postgres.h"
      32                 : 
      33                 : #include "pgp.h"
      34                 : #include "px.h"
      35                 : 
      36                 : /*
      37                 :  * padded msg = 02 || PS || 00 || M
      38                 :  * PS - pad bytes
      39                 :  * M - msg
      40                 :  */
      41                 : static uint8 *
      42 CBC          13 : check_eme_pkcs1_v15(uint8 *data, int len)
      43                 : {
      44              13 :     uint8      *data_end = data + len;
      45              13 :     uint8      *p = data;
      46              13 :     int         rnd = 0;
      47                 : 
      48              13 :     if (len < 1 + 8 + 1)
      49 UBC           0 :         return NULL;
      50                 : 
      51 CBC          13 :     if (*p++ != 2)
      52 UBC           0 :         return NULL;
      53                 : 
      54 CBC        2911 :     while (p < data_end && *p)
      55                 :     {
      56            2898 :         p++;
      57            2898 :         rnd++;
      58                 :     }
      59                 : 
      60              13 :     if (p == data_end)
      61 UBC           0 :         return NULL;
      62 CBC          13 :     if (*p != 0)
      63 UBC           0 :         return NULL;
      64 CBC          13 :     if (rnd < 8)
      65 UBC           0 :         return NULL;
      66 CBC          13 :     return p + 1;
      67                 : }
      68                 : 
      69                 : /*
      70                 :  * secret message: 1 byte algo, sesskey, 2 byte cksum
      71                 :  * ignore algo in cksum
      72                 :  */
      73                 : static int
      74              13 : control_cksum(uint8 *msg, int msglen)
      75                 : {
      76                 :     int         i;
      77                 :     unsigned    my_cksum,
      78                 :                 got_cksum;
      79                 : 
      80              13 :     if (msglen < 3)
      81 UBC           0 :         return PXE_PGP_WRONG_KEY;
      82                 : 
      83 CBC          13 :     my_cksum = 0;
      84             237 :     for (i = 1; i < msglen - 2; i++)
      85             224 :         my_cksum += msg[i];
      86              13 :     my_cksum &= 0xFFFF;
      87              13 :     got_cksum = ((unsigned) (msg[msglen - 2]) << 8) + msg[msglen - 1];
      88              13 :     if (my_cksum != got_cksum)
      89                 :     {
      90 UBC           0 :         px_debug("pubenc cksum failed");
      91               0 :         return PXE_PGP_WRONG_KEY;
      92                 :     }
      93 CBC          13 :     return 0;
      94                 : }
      95                 : 
      96                 : static int
      97               9 : decrypt_elgamal(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
      98                 : {
      99                 :     int         res;
     100               9 :     PGP_MPI    *c1 = NULL;
     101               9 :     PGP_MPI    *c2 = NULL;
     102                 : 
     103               9 :     if (pk->algo != PGP_PUB_ELG_ENCRYPT)
     104 UBC           0 :         return PXE_PGP_WRONG_KEY;
     105                 : 
     106                 :     /* read elgamal encrypted data */
     107 CBC           9 :     res = pgp_mpi_read(pkt, &c1);
     108               9 :     if (res < 0)
     109 UBC           0 :         goto out;
     110 CBC           9 :     res = pgp_mpi_read(pkt, &c2);
     111               9 :     if (res < 0)
     112 UBC           0 :         goto out;
     113                 : 
     114                 :     /* decrypt */
     115 CBC           9 :     res = pgp_elgamal_decrypt(pk, c1, c2, m_p);
     116                 : 
     117               9 : out:
     118               9 :     pgp_mpi_free(c1);
     119               9 :     pgp_mpi_free(c2);
     120               9 :     return res;
     121                 : }
     122                 : 
     123                 : static int
     124               4 : decrypt_rsa(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
     125                 : {
     126                 :     int         res;
     127                 :     PGP_MPI    *c;
     128                 : 
     129               4 :     if (pk->algo != PGP_PUB_RSA_ENCRYPT
     130               4 :         && pk->algo != PGP_PUB_RSA_ENCRYPT_SIGN)
     131 UBC           0 :         return PXE_PGP_WRONG_KEY;
     132                 : 
     133                 :     /* read rsa encrypted data */
     134 CBC           4 :     res = pgp_mpi_read(pkt, &c);
     135               4 :     if (res < 0)
     136 UBC           0 :         return res;
     137                 : 
     138                 :     /* decrypt */
     139 CBC           4 :     res = pgp_rsa_decrypt(pk, c, m_p);
     140                 : 
     141               4 :     pgp_mpi_free(c);
     142               4 :     return res;
     143                 : }
     144                 : 
     145                 : /* key id is missing - user is expected to try all keys */
     146                 : static const uint8
     147                 :             any_key[] = {0, 0, 0, 0, 0, 0, 0, 0};
     148                 : 
     149                 : int
     150              14 : pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
     151                 : {
     152                 :     int         ver;
     153                 :     int         algo;
     154                 :     int         res;
     155                 :     uint8       key_id[8];
     156                 :     PGP_PubKey *pk;
     157                 :     uint8      *msg;
     158                 :     int         msglen;
     159                 :     PGP_MPI    *m;
     160                 : 
     161              14 :     pk = ctx->pub_key;
     162              14 :     if (pk == NULL)
     163                 :     {
     164 UBC           0 :         px_debug("no pubkey?");
     165               0 :         return PXE_BUG;
     166                 :     }
     167                 : 
     168 CBC          14 :     GETBYTE(pkt, ver);
     169              14 :     if (ver != 3)
     170                 :     {
     171 UBC           0 :         px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
     172               0 :         return PXE_PGP_CORRUPT_DATA;
     173                 :     }
     174                 : 
     175                 :     /*
     176                 :      * check if keyid's match - user-friendly msg
     177                 :      */
     178 CBC          14 :     res = pullf_read_fixed(pkt, 8, key_id);
     179              14 :     if (res < 0)
     180 UBC           0 :         return res;
     181 CBC          14 :     if (memcmp(key_id, any_key, 8) != 0
     182              14 :         && memcmp(key_id, pk->key_id, 8) != 0)
     183                 :     {
     184               1 :         px_debug("key_id's does not match");
     185               1 :         return PXE_PGP_WRONG_KEY;
     186                 :     }
     187                 : 
     188                 :     /*
     189                 :      * Decrypt
     190                 :      */
     191              13 :     GETBYTE(pkt, algo);
     192              13 :     switch (algo)
     193                 :     {
     194               9 :         case PGP_PUB_ELG_ENCRYPT:
     195               9 :             res = decrypt_elgamal(pk, pkt, &m);
     196               9 :             break;
     197               4 :         case PGP_PUB_RSA_ENCRYPT:
     198                 :         case PGP_PUB_RSA_ENCRYPT_SIGN:
     199               4 :             res = decrypt_rsa(pk, pkt, &m);
     200               4 :             break;
     201 UBC           0 :         default:
     202               0 :             res = PXE_PGP_UNKNOWN_PUBALGO;
     203                 :     }
     204 CBC          13 :     if (res < 0)
     205 UBC           0 :         return res;
     206                 : 
     207                 :     /*
     208                 :      * extract message
     209                 :      */
     210 CBC          13 :     msg = check_eme_pkcs1_v15(m->data, m->bytes);
     211              13 :     if (msg == NULL)
     212                 :     {
     213 UBC           0 :         px_debug("check_eme_pkcs1_v15 failed");
     214               0 :         res = PXE_PGP_WRONG_KEY;
     215               0 :         goto out;
     216                 :     }
     217 CBC          13 :     msglen = m->bytes - (msg - m->data);
     218                 : 
     219              13 :     res = control_cksum(msg, msglen);
     220              13 :     if (res < 0)
     221 UBC           0 :         goto out;
     222                 : 
     223                 :     /*
     224                 :      * got sesskey
     225                 :      */
     226 CBC          13 :     ctx->cipher_algo = *msg;
     227              13 :     ctx->sess_key_len = msglen - 3;
     228              13 :     memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len);
     229                 : 
     230              13 : out:
     231              13 :     pgp_mpi_free(m);
     232              13 :     if (res < 0)
     233 UBC           0 :         return res;
     234 CBC          13 :     return pgp_expect_packet_end(pkt);
     235                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a