mirror of
https://github.com/postgres/postgres.git
synced 2025-07-23 03:21:12 +03:00
config
contrib
adminpack
auth_delay
auto_explain
btree_gin
btree_gist
chkpass
citext
cube
dblink
dict_int
dict_xsyn
dummy_seclabel
earthdistance
file_fdw
fuzzystrmatch
hstore
intagg
intarray
isn
lo
ltree
oid2name
pageinspect
passwordcheck
pg_archivecleanup
pg_buffercache
pg_freespacemap
pg_standby
pg_stat_statements
pg_test_fsync
pg_test_timing
pg_trgm
pg_upgrade
pg_upgrade_support
pgbench
pgcrypto
expected
sql
.gitignore
Makefile
blf.c
blf.h
crypt-blowfish.c
crypt-des.c
crypt-gensalt.c
crypt-md5.c
fortuna.c
fortuna.h
imath.c
imath.h
internal-sha2.c
internal.c
mbuf.c
mbuf.h
md5.c
md5.h
openssl.c
pgcrypto--1.0.sql
pgcrypto--unpackaged--1.0.sql
pgcrypto.c
pgcrypto.control
pgcrypto.h
pgp-armor.c
pgp-cfb.c
pgp-compress.c
pgp-decrypt.c
pgp-encrypt.c
pgp-info.c
pgp-mpi-internal.c
pgp-mpi-openssl.c
pgp-mpi.c
pgp-pgsql.c
pgp-pubdec.c
pgp-pubenc.c
pgp-pubkey.c
pgp-s2k.c
pgp.c
pgp.h
px-crypt.c
px-crypt.h
px-hmac.c
px.c
px.h
random.c
rijndael.c
rijndael.h
rijndael.tbl
sha1.c
sha1.h
sha2.c
sha2.h
pgrowlocks
pgstattuple
seg
sepgsql
spi
sslinfo
start-scripts
tablefunc
tcn
test_parser
tsearch2
unaccent
uuid-ossp
vacuumlo
xml2
Makefile
README
contrib-global.mk
doc
src
.gitignore
COPYRIGHT
GNUmakefile.in
Makefile
README
README.git
aclocal.m4
configure
configure.in
266 lines
5.7 KiB
C
266 lines
5.7 KiB
C
/*
|
|
* pgp-cfb.c
|
|
* Implements both normal and PGP-specific CFB mode.
|
|
*
|
|
* Copyright (c) 2005 Marko Kreen
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* contrib/pgcrypto/pgp-cfb.c
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "mbuf.h"
|
|
#include "px.h"
|
|
#include "pgp.h"
|
|
|
|
typedef int (*mix_data_t) (PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
|
|
|
|
struct PGP_CFB
|
|
{
|
|
PX_Cipher *ciph;
|
|
int block_size;
|
|
int pos;
|
|
int block_no;
|
|
int resync;
|
|
uint8 fr[PGP_MAX_BLOCK];
|
|
uint8 fre[PGP_MAX_BLOCK];
|
|
uint8 encbuf[PGP_MAX_BLOCK];
|
|
};
|
|
|
|
int
|
|
pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len,
|
|
int resync, uint8 *iv)
|
|
{
|
|
int res;
|
|
PX_Cipher *ciph;
|
|
PGP_CFB *ctx;
|
|
|
|
res = pgp_load_cipher(algo, &ciph);
|
|
if (res < 0)
|
|
return res;
|
|
|
|
res = px_cipher_init(ciph, key, key_len, NULL);
|
|
if (res < 0)
|
|
{
|
|
px_cipher_free(ciph);
|
|
return res;
|
|
}
|
|
|
|
ctx = px_alloc(sizeof(*ctx));
|
|
memset(ctx, 0, sizeof(*ctx));
|
|
ctx->ciph = ciph;
|
|
ctx->block_size = px_cipher_block_size(ciph);
|
|
ctx->resync = resync;
|
|
|
|
if (iv)
|
|
memcpy(ctx->fr, iv, ctx->block_size);
|
|
|
|
*ctx_p = ctx;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
pgp_cfb_free(PGP_CFB *ctx)
|
|
{
|
|
px_cipher_free(ctx->ciph);
|
|
memset(ctx, 0, sizeof(*ctx));
|
|
px_free(ctx);
|
|
}
|
|
|
|
/*
|
|
* Data processing for normal CFB. (PGP_PKT_SYMENCRYPTED_DATA_MDC)
|
|
*/
|
|
static int
|
|
mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
|
|
{
|
|
int i;
|
|
|
|
for (i = ctx->pos; i < ctx->pos + len; i++)
|
|
*dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
|
|
ctx->pos += len;
|
|
return len;
|
|
}
|
|
|
|
static int
|
|
mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
|
|
{
|
|
int i;
|
|
|
|
for (i = ctx->pos; i < ctx->pos + len; i++)
|
|
{
|
|
ctx->encbuf[i] = *data++;
|
|
*dst++ = ctx->fre[i] ^ ctx->encbuf[i];
|
|
}
|
|
ctx->pos += len;
|
|
return len;
|
|
}
|
|
|
|
/*
|
|
* Data processing for old PGP CFB mode. (PGP_PKT_SYMENCRYPTED_DATA)
|
|
*
|
|
* The goal is to hide the horror from the rest of the code,
|
|
* thus its all concentrated here.
|
|
*/
|
|
static int
|
|
mix_encrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
|
|
{
|
|
int i,
|
|
n;
|
|
|
|
/* block #2 is 2 bytes long */
|
|
if (ctx->block_no == 2)
|
|
{
|
|
n = 2 - ctx->pos;
|
|
if (len < n)
|
|
n = len;
|
|
for (i = ctx->pos; i < ctx->pos + n; i++)
|
|
*dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
|
|
|
|
ctx->pos += n;
|
|
len -= n;
|
|
|
|
if (ctx->pos == 2)
|
|
{
|
|
memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
|
|
memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
|
|
ctx->pos = 0;
|
|
return n;
|
|
}
|
|
}
|
|
for (i = ctx->pos; i < ctx->pos + len; i++)
|
|
*dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
|
|
ctx->pos += len;
|
|
return len;
|
|
}
|
|
|
|
static int
|
|
mix_decrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
|
|
{
|
|
int i,
|
|
n;
|
|
|
|
/* block #2 is 2 bytes long */
|
|
if (ctx->block_no == 2)
|
|
{
|
|
n = 2 - ctx->pos;
|
|
if (len < n)
|
|
n = len;
|
|
for (i = ctx->pos; i < ctx->pos + n; i++)
|
|
{
|
|
ctx->encbuf[i] = *data++;
|
|
*dst++ = ctx->fre[i] ^ ctx->encbuf[i];
|
|
}
|
|
ctx->pos += n;
|
|
len -= n;
|
|
|
|
if (ctx->pos == 2)
|
|
{
|
|
memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
|
|
memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
|
|
ctx->pos = 0;
|
|
return n;
|
|
}
|
|
}
|
|
for (i = ctx->pos; i < ctx->pos + len; i++)
|
|
{
|
|
ctx->encbuf[i] = *data++;
|
|
*dst++ = ctx->fre[i] ^ ctx->encbuf[i];
|
|
}
|
|
ctx->pos += len;
|
|
return len;
|
|
}
|
|
|
|
/*
|
|
* common code for both encrypt and decrypt.
|
|
*/
|
|
static int
|
|
cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst,
|
|
mix_data_t mix_data)
|
|
{
|
|
int n;
|
|
int res;
|
|
|
|
while (len > 0 && ctx->pos > 0)
|
|
{
|
|
n = ctx->block_size - ctx->pos;
|
|
if (len < n)
|
|
n = len;
|
|
|
|
n = mix_data(ctx, data, n, dst);
|
|
data += n;
|
|
dst += n;
|
|
len -= n;
|
|
|
|
if (ctx->pos == ctx->block_size)
|
|
{
|
|
memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
|
|
ctx->pos = 0;
|
|
}
|
|
}
|
|
|
|
while (len > 0)
|
|
{
|
|
px_cipher_encrypt(ctx->ciph, ctx->fr, ctx->block_size, ctx->fre);
|
|
if (ctx->block_no < 5)
|
|
ctx->block_no++;
|
|
|
|
n = ctx->block_size;
|
|
if (len < n)
|
|
n = len;
|
|
|
|
res = mix_data(ctx, data, n, dst);
|
|
data += res;
|
|
dst += res;
|
|
len -= res;
|
|
|
|
if (ctx->pos == ctx->block_size)
|
|
{
|
|
memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
|
|
ctx->pos = 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* public interface
|
|
*/
|
|
|
|
int
|
|
pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
|
|
{
|
|
mix_data_t mix = ctx->resync ? mix_encrypt_resync : mix_encrypt_normal;
|
|
|
|
return cfb_process(ctx, data, len, dst, mix);
|
|
}
|
|
|
|
int
|
|
pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
|
|
{
|
|
mix_data_t mix = ctx->resync ? mix_decrypt_resync : mix_decrypt_normal;
|
|
|
|
return cfb_process(ctx, data, len, dst, mix);
|
|
}
|