LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-pubdec.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 75 101 74.3 %
Date: 2024-04-20 05:11:05 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          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          26 : check_eme_pkcs1_v15(uint8 *data, int len)
      43             : {
      44          26 :     uint8      *data_end = data + len;
      45          26 :     uint8      *p = data;
      46          26 :     int         rnd = 0;
      47             : 
      48          26 :     if (len < 1 + 8 + 1)
      49           0 :         return NULL;
      50             : 
      51          26 :     if (*p++ != 2)
      52           0 :         return NULL;
      53             : 
      54        5822 :     while (p < data_end && *p)
      55             :     {
      56        5796 :         p++;
      57        5796 :         rnd++;
      58             :     }
      59             : 
      60          26 :     if (p == data_end)
      61           0 :         return NULL;
      62          26 :     if (*p != 0)
      63           0 :         return NULL;
      64          26 :     if (rnd < 8)
      65           0 :         return NULL;
      66          26 :     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          26 : control_cksum(uint8 *msg, int msglen)
      75             : {
      76             :     int         i;
      77             :     unsigned    my_cksum,
      78             :                 got_cksum;
      79             : 
      80          26 :     if (msglen < 3)
      81           0 :         return PXE_PGP_WRONG_KEY;
      82             : 
      83          26 :     my_cksum = 0;
      84         474 :     for (i = 1; i < msglen - 2; i++)
      85         448 :         my_cksum += msg[i];
      86          26 :     my_cksum &= 0xFFFF;
      87          26 :     got_cksum = ((unsigned) (msg[msglen - 2]) << 8) + msg[msglen - 1];
      88          26 :     if (my_cksum != got_cksum)
      89             :     {
      90           0 :         px_debug("pubenc cksum failed");
      91           0 :         return PXE_PGP_WRONG_KEY;
      92             :     }
      93          26 :     return 0;
      94             : }
      95             : 
      96             : static int
      97          18 : decrypt_elgamal(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
      98             : {
      99             :     int         res;
     100          18 :     PGP_MPI    *c1 = NULL;
     101          18 :     PGP_MPI    *c2 = NULL;
     102             : 
     103          18 :     if (pk->algo != PGP_PUB_ELG_ENCRYPT)
     104           0 :         return PXE_PGP_WRONG_KEY;
     105             : 
     106             :     /* read elgamal encrypted data */
     107          18 :     res = pgp_mpi_read(pkt, &c1);
     108          18 :     if (res < 0)
     109           0 :         goto out;
     110          18 :     res = pgp_mpi_read(pkt, &c2);
     111          18 :     if (res < 0)
     112           0 :         goto out;
     113             : 
     114             :     /* decrypt */
     115          18 :     res = pgp_elgamal_decrypt(pk, c1, c2, m_p);
     116             : 
     117          18 : out:
     118          18 :     pgp_mpi_free(c1);
     119          18 :     pgp_mpi_free(c2);
     120          18 :     return res;
     121             : }
     122             : 
     123             : static int
     124           8 : decrypt_rsa(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
     125             : {
     126             :     int         res;
     127             :     PGP_MPI    *c;
     128             : 
     129           8 :     if (pk->algo != PGP_PUB_RSA_ENCRYPT
     130           8 :         && pk->algo != PGP_PUB_RSA_ENCRYPT_SIGN)
     131           0 :         return PXE_PGP_WRONG_KEY;
     132             : 
     133             :     /* read rsa encrypted data */
     134           8 :     res = pgp_mpi_read(pkt, &c);
     135           8 :     if (res < 0)
     136           0 :         return res;
     137             : 
     138             :     /* decrypt */
     139           8 :     res = pgp_rsa_decrypt(pk, c, m_p);
     140             : 
     141           8 :     pgp_mpi_free(c);
     142           8 :     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          28 : 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          28 :     pk = ctx->pub_key;
     162          28 :     if (pk == NULL)
     163             :     {
     164           0 :         px_debug("no pubkey?");
     165           0 :         return PXE_BUG;
     166             :     }
     167             : 
     168          28 :     GETBYTE(pkt, ver);
     169          28 :     if (ver != 3)
     170             :     {
     171           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          28 :     res = pullf_read_fixed(pkt, 8, key_id);
     179          28 :     if (res < 0)
     180           0 :         return res;
     181          28 :     if (memcmp(key_id, any_key, 8) != 0
     182          28 :         && memcmp(key_id, pk->key_id, 8) != 0)
     183             :     {
     184           2 :         px_debug("key_id's does not match");
     185           2 :         return PXE_PGP_WRONG_KEY;
     186             :     }
     187             : 
     188             :     /*
     189             :      * Decrypt
     190             :      */
     191          26 :     GETBYTE(pkt, algo);
     192          26 :     switch (algo)
     193             :     {
     194          18 :         case PGP_PUB_ELG_ENCRYPT:
     195          18 :             res = decrypt_elgamal(pk, pkt, &m);
     196          18 :             break;
     197           8 :         case PGP_PUB_RSA_ENCRYPT:
     198             :         case PGP_PUB_RSA_ENCRYPT_SIGN:
     199           8 :             res = decrypt_rsa(pk, pkt, &m);
     200           8 :             break;
     201           0 :         default:
     202           0 :             res = PXE_PGP_UNKNOWN_PUBALGO;
     203             :     }
     204          26 :     if (res < 0)
     205           0 :         return res;
     206             : 
     207             :     /*
     208             :      * extract message
     209             :      */
     210          26 :     msg = check_eme_pkcs1_v15(m->data, m->bytes);
     211          26 :     if (msg == NULL)
     212             :     {
     213           0 :         px_debug("check_eme_pkcs1_v15 failed");
     214           0 :         res = PXE_PGP_WRONG_KEY;
     215           0 :         goto out;
     216             :     }
     217          26 :     msglen = m->bytes - (msg - m->data);
     218             : 
     219          26 :     res = control_cksum(msg, msglen);
     220          26 :     if (res < 0)
     221           0 :         goto out;
     222             : 
     223             :     /*
     224             :      * got sesskey
     225             :      */
     226          26 :     ctx->cipher_algo = *msg;
     227          26 :     ctx->sess_key_len = msglen - 3;
     228          26 :     memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len);
     229             : 
     230          26 : out:
     231          26 :     pgp_mpi_free(m);
     232          26 :     if (res < 0)
     233           0 :         return res;
     234          26 :     return pgp_expect_packet_end(pkt);
     235             : }

Generated by: LCOV version 1.14