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  unsigned rlen;
224 
225  px_cipher_encrypt(ctx->ciph, 0, ctx->fr, ctx->block_size, ctx->fre, &rlen);
226  if (ctx->block_no < 5)
227  ctx->block_no++;
228 
229  n = ctx->block_size;
230  if (len < n)
231  n = len;
232 
233  res = mix_data(ctx, data, n, dst);
234  data += res;
235  dst += res;
236  len -= res;
237 
238  if (ctx->pos == ctx->block_size)
239  {
240  memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
241  ctx->pos = 0;
242  }
243  }
244  return 0;
245 }
246 
247 /*
248  * public interface
249  */
250 
251 int
252 pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
253 {
255 
256  return cfb_process(ctx, data, len, dst, mix);
257 }
258 
259 int
260 pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
261 {
263 
264  return cfb_process(ctx, data, len, dst, mix);
265 }
unsigned char uint8
Definition: c.h:504
#define mix(a, b, c)
Definition: hashfn.c:82
int i
Definition: isn.c:73
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc0(Size size)
Definition: mcxt.c:1346
const void size_t len
const void * data
static int mix_decrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:157
int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:252
void pgp_cfb_free(PGP_CFB *ctx)
Definition: pgp-cfb.c:83
static int mix_encrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:125
static int cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst, mix_data_t mix_data)
Definition: pgp-cfb.c:197
int(* mix_data_t)(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:37
int pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:260
static int mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:105
static int mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:94
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
int pgp_load_cipher(int code, PX_Cipher **res)
Definition: pgp.c:157
#define PGP_MAX_BLOCK
Definition: pgp.h:113
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:123
#define px_cipher_free(c)
Definition: px.h:215
#define px_cipher_block_size(c)
Definition: px.h:208
#define px_cipher_encrypt(c, padding, data, dlen, res, rlen)
Definition: px.h:211
#define px_cipher_init(c, k, klen, iv)
Definition: px.h:210
int block_size
Definition: pgp-cfb.c:42
PX_Cipher * ciph
Definition: pgp-cfb.c:41
int pos
Definition: pgp-cfb.c:43
uint8 fre[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:47
uint8 encbuf[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:48
uint8 fr[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:46
int resync
Definition: pgp-cfb.c:45
int block_no
Definition: pgp-cfb.c:44
Definition: px.h:141