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