LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-s2k.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 91.2 % 148 135
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 7 7
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 79.0 % 62 49

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * pgp-s2k.c
       3                 :             :  *    OpenPGP string2key functions.
       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-s2k.c
      30                 :             :  */
      31                 :             : 
      32                 :             : #include "postgres.h"
      33                 :             : 
      34                 :             : #include "pgp.h"
      35                 :             : #include "px.h"
      36                 :             : 
      37                 :             : static int
      38                 :           5 : calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
      39                 :             :                 unsigned key_len)
      40                 :             : {
      41                 :             :     unsigned    md_rlen;
      42                 :             :     uint8       buf[PGP_MAX_DIGEST];
      43                 :             :     unsigned    preload;
      44                 :             :     unsigned    remain;
      45                 :           5 :     uint8      *dst = s2k->key;
      46                 :             : 
      47                 :           5 :     md_rlen = px_md_result_size(md);
      48                 :             : 
      49                 :           5 :     remain = s2k->key_len;
      50                 :           5 :     preload = 0;
      51         [ +  + ]:          12 :     while (remain > 0)
      52                 :             :     {
      53                 :           7 :         px_md_reset(md);
      54                 :             : 
      55         [ +  + ]:           7 :         if (preload)
      56                 :             :         {
      57                 :           2 :             memset(buf, 0, preload);
      58                 :           2 :             px_md_update(md, buf, preload);
      59                 :             :         }
      60                 :           7 :         preload++;
      61                 :             : 
      62                 :           7 :         px_md_update(md, key, key_len);
      63                 :           7 :         px_md_finish(md, buf);
      64                 :             : 
      65         [ +  + ]:           7 :         if (remain > md_rlen)
      66                 :             :         {
      67                 :           2 :             memcpy(dst, buf, md_rlen);
      68                 :           2 :             dst += md_rlen;
      69                 :           2 :             remain -= md_rlen;
      70                 :             :         }
      71                 :             :         else
      72                 :             :         {
      73                 :           5 :             memcpy(dst, buf, remain);
      74                 :           5 :             remain = 0;
      75                 :             :         }
      76                 :             :     }
      77                 :           5 :     px_memset(buf, 0, sizeof(buf));
      78                 :           5 :     return 0;
      79                 :             : }
      80                 :             : 
      81                 :             : static int
      82                 :           5 : calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
      83                 :             : {
      84                 :             :     unsigned    md_rlen;
      85                 :             :     uint8       buf[PGP_MAX_DIGEST];
      86                 :           5 :     unsigned    preload = 0;
      87                 :             :     uint8      *dst;
      88                 :             :     unsigned    remain;
      89                 :             : 
      90                 :           5 :     md_rlen = px_md_result_size(md);
      91                 :             : 
      92                 :           5 :     dst = s2k->key;
      93                 :           5 :     remain = s2k->key_len;
      94         [ +  + ]:          12 :     while (remain > 0)
      95                 :             :     {
      96                 :           7 :         px_md_reset(md);
      97                 :             : 
      98         [ +  + ]:           7 :         if (preload > 0)
      99                 :             :         {
     100                 :           2 :             memset(buf, 0, preload);
     101                 :           2 :             px_md_update(md, buf, preload);
     102                 :             :         }
     103                 :           7 :         preload++;
     104                 :             : 
     105                 :           7 :         px_md_update(md, s2k->salt, PGP_S2K_SALT);
     106                 :           7 :         px_md_update(md, key, key_len);
     107                 :           7 :         px_md_finish(md, buf);
     108                 :             : 
     109         [ +  + ]:           7 :         if (remain > md_rlen)
     110                 :             :         {
     111                 :           2 :             memcpy(dst, buf, md_rlen);
     112                 :           2 :             remain -= md_rlen;
     113                 :           2 :             dst += md_rlen;
     114                 :             :         }
     115                 :             :         else
     116                 :             :         {
     117                 :           5 :             memcpy(dst, buf, remain);
     118                 :           5 :             remain = 0;
     119                 :             :         }
     120                 :             :     }
     121                 :           5 :     px_memset(buf, 0, sizeof(buf));
     122                 :           5 :     return 0;
     123                 :             : }
     124                 :             : 
     125                 :             : static int
     126                 :          84 : calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
     127                 :             :                      unsigned key_len)
     128                 :             : {
     129                 :             :     unsigned    md_rlen;
     130                 :             :     uint8       buf[PGP_MAX_DIGEST];
     131                 :             :     uint8      *dst;
     132                 :          84 :     unsigned    preload = 0;
     133                 :             :     unsigned    remain,
     134                 :             :                 c,
     135                 :             :                 curcnt,
     136                 :             :                 count;
     137                 :             : 
     138                 :          84 :     count = s2k_decode_count(s2k->iter);
     139                 :             : 
     140                 :          84 :     md_rlen = px_md_result_size(md);
     141                 :             : 
     142                 :          84 :     remain = s2k->key_len;
     143                 :          84 :     dst = s2k->key;
     144         [ +  + ]:         181 :     while (remain > 0)
     145                 :             :     {
     146                 :          97 :         px_md_reset(md);
     147                 :             : 
     148         [ +  + ]:          97 :         if (preload)
     149                 :             :         {
     150                 :          13 :             memset(buf, 0, preload);
     151                 :          13 :             px_md_update(md, buf, preload);
     152                 :             :         }
     153                 :          97 :         preload++;
     154                 :             : 
     155                 :          97 :         px_md_update(md, s2k->salt, PGP_S2K_SALT);
     156                 :          97 :         px_md_update(md, key, key_len);
     157                 :          97 :         curcnt = PGP_S2K_SALT + key_len;
     158                 :             : 
     159         [ +  + ]:    12757698 :         while (curcnt < count)
     160                 :             :         {
     161         [ +  + ]:    12757672 :             if (curcnt + PGP_S2K_SALT < count)
     162                 :    12757601 :                 c = PGP_S2K_SALT;
     163                 :             :             else
     164                 :          71 :                 c = count - curcnt;
     165                 :    12757672 :             px_md_update(md, s2k->salt, c);
     166                 :    12757672 :             curcnt += c;
     167                 :             : 
     168         [ +  + ]:    12757672 :             if (curcnt + key_len < count)
     169                 :    12757575 :                 c = key_len;
     170         [ +  + ]:          97 :             else if (curcnt < count)
     171                 :          26 :                 c = count - curcnt;
     172                 :             :             else
     173                 :          71 :                 break;
     174                 :    12757601 :             px_md_update(md, key, c);
     175                 :    12757601 :             curcnt += c;
     176                 :             :         }
     177                 :          97 :         px_md_finish(md, buf);
     178                 :             : 
     179         [ +  + ]:          97 :         if (remain > md_rlen)
     180                 :             :         {
     181                 :          13 :             memcpy(dst, buf, md_rlen);
     182                 :          13 :             remain -= md_rlen;
     183                 :          13 :             dst += md_rlen;
     184                 :             :         }
     185                 :             :         else
     186                 :             :         {
     187                 :          84 :             memcpy(dst, buf, remain);
     188                 :          84 :             remain = 0;
     189                 :             :         }
     190                 :             :     }
     191                 :          84 :     px_memset(buf, 0, sizeof(buf));
     192                 :          84 :     return 0;
     193                 :             : }
     194                 :             : 
     195                 :             : /*
     196                 :             :  * Decide PGP_S2K_ISALTED iteration count (in OpenPGP one-byte representation)
     197                 :             :  *
     198                 :             :  * Too small: weak
     199                 :             :  * Too big: slow
     200                 :             :  * gpg defaults to 96 => 65536 iters
     201                 :             :  *
     202                 :             :  * For our default (count=-1) we let it float a bit: 96 + 32 => between 65536
     203                 :             :  * and 262144 iterations.
     204                 :             :  *
     205                 :             :  * Otherwise, find the smallest number which provides at least the specified
     206                 :             :  * iteration count.
     207                 :             :  */
     208                 :             : static uint8
     209                 :          28 : decide_s2k_iter(unsigned rand_byte, int count)
     210                 :             : {
     211                 :             :     int         iter;
     212                 :             : 
     213         [ +  + ]:          28 :     if (count == -1)
     214                 :          26 :         return 96 + (rand_byte & 0x1F);
     215                 :             :     /* this is a bit brute-force, but should be quick enough */
     216         [ +  - ]:         257 :     for (iter = 0; iter <= 255; iter++)
     217         [ +  + ]:         257 :         if (s2k_decode_count(iter) >= count)
     218                 :           2 :             return iter;
     219                 :           0 :     return 255;
     220                 :             : }
     221                 :             : 
     222                 :             : int
     223                 :          30 : pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count)
     224                 :             : {
     225                 :          30 :     int         res = 0;
     226                 :             :     uint8       tmp;
     227                 :             : 
     228                 :          30 :     s2k->mode = mode;
     229                 :          30 :     s2k->digest_algo = digest_algo;
     230                 :             : 
     231   [ +  +  +  - ]:          30 :     switch (s2k->mode)
     232                 :             :     {
     233                 :           1 :         case PGP_S2K_SIMPLE:
     234                 :           1 :             break;
     235                 :           1 :         case PGP_S2K_SALTED:
     236         [ -  + ]:           1 :             if (!pg_strong_random(s2k->salt, PGP_S2K_SALT))
     237                 :           0 :                 return PXE_NO_RANDOM;
     238                 :           1 :             break;
     239                 :          28 :         case PGP_S2K_ISALTED:
     240         [ -  + ]:          28 :             if (!pg_strong_random(s2k->salt, PGP_S2K_SALT))
     241                 :           0 :                 return PXE_NO_RANDOM;
     242         [ -  + ]:          28 :             if (!pg_strong_random(&tmp, 1))
     243                 :           0 :                 return PXE_NO_RANDOM;
     244                 :          28 :             s2k->iter = decide_s2k_iter(tmp, count);
     245                 :          28 :             break;
     246                 :           0 :         default:
     247                 :           0 :             res = PXE_PGP_BAD_S2K_MODE;
     248                 :             :     }
     249                 :          30 :     return res;
     250                 :             : }
     251                 :             : 
     252                 :             : int
     253                 :          64 : pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
     254                 :             : {
     255                 :          64 :     int         res = 0;
     256                 :             : 
     257         [ -  + ]:          64 :     GETBYTE(src, s2k->mode);
     258         [ -  + ]:          64 :     GETBYTE(src, s2k->digest_algo);
     259   [ +  +  +  - ]:          64 :     switch (s2k->mode)
     260                 :             :     {
     261                 :           4 :         case 0:
     262                 :           4 :             break;
     263                 :           4 :         case 1:
     264                 :           4 :             res = pullf_read_fixed(src, 8, s2k->salt);
     265                 :           4 :             break;
     266                 :          56 :         case 3:
     267                 :          56 :             res = pullf_read_fixed(src, 8, s2k->salt);
     268         [ -  + ]:          56 :             if (res < 0)
     269                 :           0 :                 break;
     270         [ -  + ]:          56 :             GETBYTE(src, s2k->iter);
     271                 :          56 :             break;
     272                 :           0 :         default:
     273                 :           0 :             res = PXE_PGP_BAD_S2K_MODE;
     274                 :             :     }
     275                 :          64 :     return res;
     276                 :             : }
     277                 :             : 
     278                 :             : int
     279                 :          94 : pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
     280                 :             : {
     281                 :             :     int         res;
     282                 :             :     PX_MD      *md;
     283                 :             : 
     284                 :          94 :     s2k->key_len = pgp_get_cipher_key_size(cipher);
     285         [ -  + ]:          94 :     if (s2k->key_len <= 0)
     286                 :           0 :         return PXE_PGP_UNSUPPORTED_CIPHER;
     287                 :             : 
     288                 :          94 :     res = pgp_load_digest(s2k->digest_algo, &md);
     289         [ -  + ]:          94 :     if (res < 0)
     290                 :           0 :         return res;
     291                 :             : 
     292   [ +  +  +  - ]:          94 :     switch (s2k->mode)
     293                 :             :     {
     294                 :           5 :         case 0:
     295                 :           5 :             res = calc_s2k_simple(s2k, md, key, key_len);
     296                 :           5 :             break;
     297                 :           5 :         case 1:
     298                 :           5 :             res = calc_s2k_salted(s2k, md, key, key_len);
     299                 :           5 :             break;
     300                 :          84 :         case 3:
     301                 :          84 :             res = calc_s2k_iter_salted(s2k, md, key, key_len);
     302                 :          84 :             break;
     303                 :           0 :         default:
     304                 :           0 :             res = PXE_PGP_BAD_S2K_MODE;
     305                 :             :     }
     306                 :          94 :     px_md_free(md);
     307                 :          94 :     return res;
     308                 :             : }
        

Generated by: LCOV version 2.0-1