LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-cfb.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 99 104 95.2 %
Date: 2020-06-01 10:07:15 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * pgp-cfb.c
       3             :  *    Implements both normal and PGP-specific CFB mode.
       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-cfb.c
      30             :  */
      31             : 
      32             : #include "postgres.h"
      33             : 
      34             : #include "pgp.h"
      35             : #include "px.h"
      36             : 
      37             : typedef int (*mix_data_t) (PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
      38             : 
      39             : struct PGP_CFB
      40             : {
      41             :     PX_Cipher  *ciph;
      42             :     int         block_size;
      43             :     int         pos;
      44             :     int         block_no;
      45             :     int         resync;
      46             :     uint8       fr[PGP_MAX_BLOCK];
      47             :     uint8       fre[PGP_MAX_BLOCK];
      48             :     uint8       encbuf[PGP_MAX_BLOCK];
      49             : };
      50             : 
      51             : int
      52         236 : pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len,
      53             :                int resync, uint8 *iv)
      54             : {
      55             :     int         res;
      56             :     PX_Cipher  *ciph;
      57             :     PGP_CFB    *ctx;
      58             : 
      59         236 :     res = pgp_load_cipher(algo, &ciph);
      60         236 :     if (res < 0)
      61           0 :         return res;
      62             : 
      63         236 :     res = px_cipher_init(ciph, key, key_len, NULL);
      64         236 :     if (res < 0)
      65             :     {
      66           0 :         px_cipher_free(ciph);
      67           0 :         return res;
      68             :     }
      69             : 
      70         236 :     ctx = px_alloc(sizeof(*ctx));
      71         236 :     memset(ctx, 0, sizeof(*ctx));
      72         236 :     ctx->ciph = ciph;
      73         236 :     ctx->block_size = px_cipher_block_size(ciph);
      74         236 :     ctx->resync = resync;
      75             : 
      76         236 :     if (iv)
      77           8 :         memcpy(ctx->fr, iv, ctx->block_size);
      78             : 
      79         236 :     *ctx_p = ctx;
      80         236 :     return 0;
      81             : }
      82             : 
      83             : void
      84         236 : pgp_cfb_free(PGP_CFB *ctx)
      85             : {
      86         236 :     px_cipher_free(ctx->ciph);
      87         236 :     px_memset(ctx, 0, sizeof(*ctx));
      88         236 :     px_free(ctx);
      89         236 : }
      90             : 
      91             : /*
      92             :  * Data processing for normal CFB.  (PGP_PKT_SYMENCRYPTED_DATA_MDC)
      93             :  */
      94             : static int
      95        8502 : mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
      96             : {
      97             :     int         i;
      98             : 
      99      143574 :     for (i = ctx->pos; i < ctx->pos + len; i++)
     100      135072 :         *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
     101        8502 :     ctx->pos += len;
     102        8502 :     return len;
     103             : }
     104             : 
     105             : static int
     106       10318 : mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
     107             : {
     108             :     int         i;
     109             : 
     110      152850 :     for (i = ctx->pos; i < ctx->pos + len; i++)
     111             :     {
     112      142532 :         ctx->encbuf[i] = *data++;
     113      142532 :         *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
     114             :     }
     115       10318 :     ctx->pos += len;
     116       10318 :     return len;
     117             : }
     118             : 
     119             : /*
     120             :  * Data processing for old PGP CFB mode. (PGP_PKT_SYMENCRYPTED_DATA)
     121             :  *
     122             :  * The goal is to hide the horror from the rest of the code,
     123             :  * thus its all concentrated here.
     124             :  */
     125             : static int
     126           6 : mix_encrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
     127             : {
     128             :     int         i,
     129             :                 n;
     130             : 
     131             :     /* block #2 is 2 bytes long */
     132           6 :     if (ctx->block_no == 2)
     133             :     {
     134           2 :         n = 2 - ctx->pos;
     135           2 :         if (len < n)
     136           0 :             n = len;
     137           6 :         for (i = ctx->pos; i < ctx->pos + n; i++)
     138           4 :             *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
     139             : 
     140           2 :         ctx->pos += n;
     141           2 :         len -= n;
     142             : 
     143           2 :         if (ctx->pos == 2)
     144             :         {
     145           2 :             memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
     146           2 :             memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
     147           2 :             ctx->pos = 0;
     148           2 :             return n;
     149             :         }
     150             :     }
     151          66 :     for (i = ctx->pos; i < ctx->pos + len; i++)
     152          62 :         *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
     153           4 :     ctx->pos += len;
     154           4 :     return len;
     155             : }
     156             : 
     157             : static int
     158          36 : mix_decrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
     159             : {
     160             :     int         i,
     161             :                 n;
     162             : 
     163             :     /* block #2 is 2 bytes long */
     164          36 :     if (ctx->block_no == 2)
     165             :     {
     166           4 :         n = 2 - ctx->pos;
     167           4 :         if (len < n)
     168           0 :             n = len;
     169          12 :         for (i = ctx->pos; i < ctx->pos + n; i++)
     170             :         {
     171           8 :             ctx->encbuf[i] = *data++;
     172           8 :             *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
     173             :         }
     174           4 :         ctx->pos += n;
     175           4 :         len -= n;
     176             : 
     177           4 :         if (ctx->pos == 2)
     178             :         {
     179           4 :             memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
     180           4 :             memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
     181           4 :             ctx->pos = 0;
     182           4 :             return n;
     183             :         }
     184             :     }
     185         180 :     for (i = ctx->pos; i < ctx->pos + len; i++)
     186             :     {
     187         148 :         ctx->encbuf[i] = *data++;
     188         148 :         *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
     189             :     }
     190          32 :     ctx->pos += len;
     191          32 :     return len;
     192             : }
     193             : 
     194             : /*
     195             :  * common code for both encrypt and decrypt.
     196             :  */
     197             : static int
     198        1586 : cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst,
     199             :             mix_data_t mix_data)
     200             : {
     201             :     int         n;
     202             :     int         res;
     203             : 
     204        2908 :     while (len > 0 && ctx->pos > 0)
     205             :     {
     206        1322 :         n = ctx->block_size - ctx->pos;
     207        1322 :         if (len < n)
     208         978 :             n = len;
     209             : 
     210        1322 :         n = mix_data(ctx, data, n, dst);
     211        1322 :         data += n;
     212        1322 :         dst += n;
     213        1322 :         len -= n;
     214             : 
     215        1322 :         if (ctx->pos == ctx->block_size)
     216             :         {
     217         344 :             memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
     218         344 :             ctx->pos = 0;
     219             :         }
     220             :     }
     221             : 
     222       19126 :     while (len > 0)
     223             :     {
     224       17540 :         px_cipher_encrypt(ctx->ciph, ctx->fr, ctx->block_size, ctx->fre);
     225       17540 :         if (ctx->block_no < 5)
     226         988 :             ctx->block_no++;
     227             : 
     228       17540 :         n = ctx->block_size;
     229       17540 :         if (len < n)
     230         584 :             n = len;
     231             : 
     232       17540 :         res = mix_data(ctx, data, n, dst);
     233       17540 :         data += res;
     234       17540 :         dst += res;
     235       17540 :         len -= res;
     236             : 
     237       17540 :         if (ctx->pos == ctx->block_size)
     238             :         {
     239       16954 :             memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
     240       16954 :             ctx->pos = 0;
     241             :         }
     242             :     }
     243        1586 :     return 0;
     244             : }
     245             : 
     246             : /*
     247             :  * public interface
     248             :  */
     249             : 
     250             : int
     251         102 : pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
     252             : {
     253         102 :     mix_data_t  mix = ctx->resync ? mix_encrypt_resync : mix_encrypt_normal;
     254             : 
     255         102 :     return cfb_process(ctx, data, len, dst, mix);
     256             : }
     257             : 
     258             : int
     259        1484 : pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
     260             : {
     261        1484 :     mix_data_t  mix = ctx->resync ? mix_decrypt_resync : mix_decrypt_normal;
     262             : 
     263        1484 :     return cfb_process(ctx, data, len, dst, mix);
     264             : }

Generated by: LCOV version 1.13