LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-s2k.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 166 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 7 0
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.3.2-1