mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
Add missing pgcrypto files from previous commit.
This commit is contained in:
257
contrib/pgcrypto/pgp-cfb.c
Normal file
257
contrib/pgcrypto/pgp-cfb.c
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-cfb.c,v 1.1 2005/07/10 13:46:28 momjian Exp $
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user