LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-pubenc.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 84.1 % 113 95
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 5 5
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 57.4 % 47 27

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * pgp-pubenc.c
       3                 :             :  *    Encrypt session key with public 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-pubenc.c
      30                 :             :  */
      31                 :             : #include "postgres.h"
      32                 :             : 
      33                 :             : #include "pgp.h"
      34                 :             : #include "px.h"
      35                 :             : 
      36                 :             : /*
      37                 :             :  * padded msg: 02 || non-zero pad bytes || 00 || msg
      38                 :             :  */
      39                 :             : static int
      40                 :           6 : pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
      41                 :             : {
      42                 :             :     uint8      *buf,
      43                 :             :                *p;
      44                 :           6 :     int         pad_len = res_len - 2 - data_len;
      45                 :             : 
      46         [ -  + ]:           6 :     if (pad_len < 8)
      47                 :           0 :         return PXE_BUG;
      48                 :             : 
      49                 :           6 :     buf = palloc(res_len);
      50                 :           6 :     buf[0] = 0x02;
      51                 :             : 
      52         [ -  + ]:           6 :     if (!pg_strong_random(buf + 1, pad_len))
      53                 :             :     {
      54                 :           0 :         pfree(buf);
      55                 :           0 :         return PXE_NO_RANDOM;
      56                 :             :     }
      57                 :             : 
      58                 :             :     /* pad must not contain zero bytes */
      59                 :           6 :     p = buf + 1;
      60         [ +  + ]:        1282 :     while (p < buf + 1 + pad_len)
      61                 :             :     {
      62         [ +  + ]:        1276 :         if (*p == 0)
      63                 :             :         {
      64         [ -  + ]:          11 :             if (!pg_strong_random(p, 1))
      65                 :             :             {
      66                 :           0 :                 px_memset(buf, 0, res_len);
      67                 :           0 :                 pfree(buf);
      68                 :           0 :                 return PXE_NO_RANDOM;
      69                 :             :             }
      70                 :             :         }
      71         [ +  - ]:        1276 :         if (*p != 0)
      72                 :        1276 :             p++;
      73                 :             :     }
      74                 :             : 
      75                 :           6 :     buf[pad_len + 1] = 0;
      76                 :           6 :     memcpy(buf + pad_len + 2, data, data_len);
      77                 :           6 :     *res_p = buf;
      78                 :             : 
      79                 :           6 :     return 0;
      80                 :             : }
      81                 :             : 
      82                 :             : static int
      83                 :           6 : create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
      84                 :             : {
      85                 :             :     uint8      *secmsg;
      86                 :             :     int         res,
      87                 :             :                 i;
      88                 :           6 :     unsigned    cksum = 0;
      89                 :           6 :     int         klen = ctx->sess_key_len;
      90                 :           6 :     uint8      *padded = NULL;
      91                 :           6 :     PGP_MPI    *m = NULL;
      92                 :             : 
      93                 :             :     /* calc checksum */
      94         [ +  + ]:         102 :     for (i = 0; i < klen; i++)
      95                 :          96 :         cksum += ctx->sess_key[i];
      96                 :             : 
      97                 :             :     /*
      98                 :             :      * create "secret message"
      99                 :             :      */
     100                 :           6 :     secmsg = palloc(klen + 3);
     101                 :           6 :     secmsg[0] = ctx->cipher_algo;
     102                 :           6 :     memcpy(secmsg + 1, ctx->sess_key, klen);
     103                 :           6 :     secmsg[klen + 1] = (cksum >> 8) & 0xFF;
     104                 :           6 :     secmsg[klen + 2] = cksum & 0xFF;
     105                 :             : 
     106                 :             :     /*
     107                 :             :      * now create a large integer of it
     108                 :             :      */
     109                 :           6 :     res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
     110         [ +  - ]:           6 :     if (res >= 0)
     111                 :             :     {
     112                 :             :         /* first byte will be 0x02 */
     113                 :           6 :         int         full_bits = full_bytes * 8 - 6;
     114                 :             : 
     115                 :           6 :         res = pgp_mpi_create(padded, full_bits, &m);
     116                 :             :     }
     117                 :             : 
     118         [ +  - ]:           6 :     if (padded)
     119                 :             :     {
     120                 :           6 :         px_memset(padded, 0, full_bytes);
     121                 :           6 :         pfree(padded);
     122                 :             :     }
     123                 :           6 :     px_memset(secmsg, 0, klen + 3);
     124                 :           6 :     pfree(secmsg);
     125                 :             : 
     126         [ +  - ]:           6 :     if (res >= 0)
     127                 :           6 :         *msg_p = m;
     128                 :             : 
     129                 :           6 :     return res;
     130                 :             : }
     131                 :             : 
     132                 :             : static int
     133                 :           5 : encrypt_and_write_elgamal(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
     134                 :             : {
     135                 :             :     int         res;
     136                 :           5 :     PGP_MPI    *m = NULL,
     137                 :           5 :                *c1 = NULL,
     138                 :           5 :                *c2 = NULL;
     139                 :             : 
     140                 :             :     /* create padded msg */
     141                 :           5 :     res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
     142         [ -  + ]:           5 :     if (res < 0)
     143                 :           0 :         goto err;
     144                 :             : 
     145                 :             :     /* encrypt it */
     146                 :           5 :     res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
     147         [ -  + ]:           5 :     if (res < 0)
     148                 :           0 :         goto err;
     149                 :             : 
     150                 :             :     /* write out */
     151                 :           5 :     res = pgp_mpi_write(pkt, c1);
     152         [ -  + ]:           5 :     if (res < 0)
     153                 :           0 :         goto err;
     154                 :           5 :     res = pgp_mpi_write(pkt, c2);
     155                 :             : 
     156                 :           5 : err:
     157                 :           5 :     pgp_mpi_free(m);
     158                 :           5 :     pgp_mpi_free(c1);
     159                 :           5 :     pgp_mpi_free(c2);
     160                 :           5 :     return res;
     161                 :             : }
     162                 :             : 
     163                 :             : static int
     164                 :           1 : encrypt_and_write_rsa(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
     165                 :             : {
     166                 :             :     int         res;
     167                 :           1 :     PGP_MPI    *m = NULL,
     168                 :           1 :                *c = NULL;
     169                 :             : 
     170                 :             :     /* create padded msg */
     171                 :           1 :     res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
     172         [ -  + ]:           1 :     if (res < 0)
     173                 :           0 :         goto err;
     174                 :             : 
     175                 :             :     /* encrypt it */
     176                 :           1 :     res = pgp_rsa_encrypt(pk, m, &c);
     177         [ -  + ]:           1 :     if (res < 0)
     178                 :           0 :         goto err;
     179                 :             : 
     180                 :             :     /* write out */
     181                 :           1 :     res = pgp_mpi_write(pkt, c);
     182                 :             : 
     183                 :           1 : err:
     184                 :           1 :     pgp_mpi_free(m);
     185                 :           1 :     pgp_mpi_free(c);
     186                 :           1 :     return res;
     187                 :             : }
     188                 :             : 
     189                 :             : int
     190                 :           6 : pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
     191                 :             : {
     192                 :             :     int         res;
     193                 :           6 :     PGP_PubKey *pk = ctx->pub_key;
     194                 :           6 :     uint8       ver = 3;
     195                 :           6 :     PushFilter *pkt = NULL;
     196                 :             :     uint8       algo;
     197                 :             : 
     198         [ -  + ]:           6 :     if (pk == NULL)
     199                 :             :     {
     200                 :           0 :         px_debug("no pubkey?\n");
     201                 :           0 :         return PXE_BUG;
     202                 :             :     }
     203                 :             : 
     204                 :           6 :     algo = pk->algo;
     205                 :             : 
     206                 :             :     /*
     207                 :             :      * now write packet
     208                 :             :      */
     209                 :           6 :     res = pgp_create_pkt_writer(dst, PGP_PKT_PUBENCRYPTED_SESSKEY, &pkt);
     210         [ -  + ]:           6 :     if (res < 0)
     211                 :           0 :         goto err;
     212                 :           6 :     res = pushf_write(pkt, &ver, 1);
     213         [ -  + ]:           6 :     if (res < 0)
     214                 :           0 :         goto err;
     215                 :           6 :     res = pushf_write(pkt, pk->key_id, 8);
     216         [ -  + ]:           6 :     if (res < 0)
     217                 :           0 :         goto err;
     218                 :           6 :     res = pushf_write(pkt, &algo, 1);
     219         [ -  + ]:           6 :     if (res < 0)
     220                 :           0 :         goto err;
     221                 :             : 
     222      [ +  +  - ]:           6 :     switch (algo)
     223                 :             :     {
     224                 :           5 :         case PGP_PUB_ELG_ENCRYPT:
     225                 :           5 :             res = encrypt_and_write_elgamal(ctx, pk, pkt);
     226                 :           5 :             break;
     227                 :           1 :         case PGP_PUB_RSA_ENCRYPT:
     228                 :             :         case PGP_PUB_RSA_ENCRYPT_SIGN:
     229                 :           1 :             res = encrypt_and_write_rsa(ctx, pk, pkt);
     230                 :           1 :             break;
     231                 :             :     }
     232         [ -  + ]:           6 :     if (res < 0)
     233                 :           0 :         goto err;
     234                 :             : 
     235                 :             :     /*
     236                 :             :      * done, signal packet end
     237                 :             :      */
     238                 :           6 :     res = pushf_flush(pkt);
     239                 :           6 : err:
     240         [ +  - ]:           6 :     if (pkt)
     241                 :           6 :         pushf_free(pkt);
     242                 :             : 
     243                 :           6 :     return res;
     244                 :             : }
        

Generated by: LCOV version 2.0-1