LCOV - differential code coverage report
Current view: top level - contrib/pgcrypto - pgp-s2k.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 91.2 % 148 135 13 135
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 7 7 7
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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 CBC           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              83 : 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              83 :     unsigned    preload = 0;
     133                 :     unsigned    remain,
     134                 :                 c,
     135                 :                 curcnt,
     136                 :                 count;
     137                 : 
     138              83 :     count = s2k_decode_count(s2k->iter);
     139                 : 
     140              83 :     md_rlen = px_md_result_size(md);
     141                 : 
     142              83 :     remain = s2k->key_len;
     143              83 :     dst = s2k->key;
     144             179 :     while (remain > 0)
     145                 :     {
     146              96 :         px_md_reset(md);
     147                 : 
     148              96 :         if (preload)
     149                 :         {
     150              13 :             memset(buf, 0, preload);
     151              13 :             px_md_update(md, buf, preload);
     152                 :         }
     153              96 :         preload++;
     154                 : 
     155              96 :         px_md_update(md, s2k->salt, PGP_S2K_SALT);
     156              96 :         px_md_update(md, key, key_len);
     157              96 :         curcnt = PGP_S2K_SALT + key_len;
     158                 : 
     159        12719390 :         while (curcnt < count)
     160                 :         {
     161        12719363 :             if (curcnt + PGP_S2K_SALT < count)
     162        12719294 :                 c = PGP_S2K_SALT;
     163                 :             else
     164              69 :                 c = count - curcnt;
     165        12719363 :             px_md_update(md, s2k->salt, c);
     166        12719363 :             curcnt += c;
     167                 : 
     168        12719363 :             if (curcnt + key_len < count)
     169        12719267 :                 c = key_len;
     170              96 :             else if (curcnt < count)
     171              27 :                 c = count - curcnt;
     172                 :             else
     173              69 :                 break;
     174        12719294 :             px_md_update(md, key, c);
     175        12719294 :             curcnt += c;
     176                 :         }
     177              96 :         px_md_finish(md, buf);
     178                 : 
     179              96 :         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              83 :             memcpy(dst, buf, remain);
     188              83 :             remain = 0;
     189                 :         }
     190                 :     }
     191              83 :     px_memset(buf, 0, sizeof(buf));
     192              83 :     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 UBC           0 :     return 255;
     220                 : }
     221                 : 
     222                 : int
     223 CBC          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 UBC           0 :                 return PXE_NO_RANDOM;
     238 CBC           1 :             break;
     239              28 :         case PGP_S2K_ISALTED:
     240              28 :             if (!pg_strong_random(s2k->salt, PGP_S2K_SALT))
     241 UBC           0 :                 return PXE_NO_RANDOM;
     242 CBC          28 :             if (!pg_strong_random(&tmp, 1))
     243 UBC           0 :                 return PXE_NO_RANDOM;
     244 CBC          28 :             s2k->iter = decide_s2k_iter(tmp, count);
     245              28 :             break;
     246 UBC           0 :         default:
     247               0 :             res = PXE_PGP_BAD_S2K_MODE;
     248                 :     }
     249 CBC          30 :     return res;
     250                 : }
     251                 : 
     252                 : int
     253              63 : pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
     254                 : {
     255              63 :     int         res = 0;
     256                 : 
     257              63 :     GETBYTE(src, s2k->mode);
     258              63 :     GETBYTE(src, s2k->digest_algo);
     259              63 :     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              55 :         case 3:
     267              55 :             res = pullf_read_fixed(src, 8, s2k->salt);
     268              55 :             if (res < 0)
     269 UBC           0 :                 break;
     270 CBC          55 :             GETBYTE(src, s2k->iter);
     271              55 :             break;
     272 UBC           0 :         default:
     273               0 :             res = PXE_PGP_BAD_S2K_MODE;
     274                 :     }
     275 CBC          63 :     return res;
     276                 : }
     277                 : 
     278                 : int
     279              93 : pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
     280                 : {
     281                 :     int         res;
     282                 :     PX_MD      *md;
     283                 : 
     284              93 :     s2k->key_len = pgp_get_cipher_key_size(cipher);
     285              93 :     if (s2k->key_len <= 0)
     286 UBC           0 :         return PXE_PGP_UNSUPPORTED_CIPHER;
     287                 : 
     288 CBC          93 :     res = pgp_load_digest(s2k->digest_algo, &md);
     289              93 :     if (res < 0)
     290 UBC           0 :         return res;
     291                 : 
     292 CBC          93 :     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              83 :         case 3:
     301              83 :             res = calc_s2k_iter_salted(s2k, md, key, key_len);
     302              83 :             break;
     303 UBC           0 :         default:
     304               0 :             res = PXE_PGP_BAD_S2K_MODE;
     305                 :     }
     306 CBC          93 :     px_md_free(md);
     307              93 :     return res;
     308                 : }
        

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