PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "px.h"
35 #include "pgp.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 = px_alloc(sizeof(*ctx));
71  memset(ctx, 0, sizeof(*ctx));
72  ctx->ciph = ciph;
73  ctx->block_size = px_cipher_block_size(ciph);
74  ctx->resync = resync;
75 
76  if (iv)
77  memcpy(ctx->fr, iv, ctx->block_size);
78 
79  *ctx_p = ctx;
80  return 0;
81 }
82 
83 void
85 {
86  px_cipher_free(ctx->ciph);
87  px_memset(ctx, 0, sizeof(*ctx));
88  px_free(ctx);
89 }
90 
91 /*
92  * Data processing for normal CFB. (PGP_PKT_SYMENCRYPTED_DATA_MDC)
93  */
94 static int
95 mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
96 {
97  int i;
98 
99  for (i = ctx->pos; i < ctx->pos + len; i++)
100  *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
101  ctx->pos += len;
102  return len;
103 }
104 
105 static int
106 mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
107 {
108  int i;
109 
110  for (i = ctx->pos; i < ctx->pos + len; i++)
111  {
112  ctx->encbuf[i] = *data++;
113  *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
114  }
115  ctx->pos += len;
116  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 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  if (ctx->block_no == 2)
133  {
134  n = 2 - ctx->pos;
135  if (len < n)
136  n = len;
137  for (i = ctx->pos; i < ctx->pos + n; i++)
138  *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
139 
140  ctx->pos += n;
141  len -= n;
142 
143  if (ctx->pos == 2)
144  {
145  memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
146  memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
147  ctx->pos = 0;
148  return n;
149  }
150  }
151  for (i = ctx->pos; i < ctx->pos + len; i++)
152  *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
153  ctx->pos += len;
154  return len;
155 }
156 
157 static int
158 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  if (ctx->block_no == 2)
165  {
166  n = 2 - ctx->pos;
167  if (len < n)
168  n = len;
169  for (i = ctx->pos; i < ctx->pos + n; i++)
170  {
171  ctx->encbuf[i] = *data++;
172  *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
173  }
174  ctx->pos += n;
175  len -= n;
176 
177  if (ctx->pos == 2)
178  {
179  memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
180  memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
181  ctx->pos = 0;
182  return n;
183  }
184  }
185  for (i = ctx->pos; i < ctx->pos + len; i++)
186  {
187  ctx->encbuf[i] = *data++;
188  *dst++ = ctx->fre[i] ^ ctx->encbuf[i];
189  }
190  ctx->pos += len;
191  return len;
192 }
193 
194 /*
195  * common code for both encrypt and decrypt.
196  */
197 static int
198 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  while (len > 0 && ctx->pos > 0)
205  {
206  n = ctx->block_size - ctx->pos;
207  if (len < n)
208  n = len;
209 
210  n = mix_data(ctx, data, n, dst);
211  data += n;
212  dst += n;
213  len -= n;
214 
215  if (ctx->pos == ctx->block_size)
216  {
217  memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
218  ctx->pos = 0;
219  }
220  }
221 
222  while (len > 0)
223  {
224  px_cipher_encrypt(ctx->ciph, ctx->fr, ctx->block_size, ctx->fre);
225  if (ctx->block_no < 5)
226  ctx->block_no++;
227 
228  n = ctx->block_size;
229  if (len < n)
230  n = len;
231 
232  res = mix_data(ctx, data, n, dst);
233  data += res;
234  dst += res;
235  len -= res;
236 
237  if (ctx->pos == ctx->block_size)
238  {
239  memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
240  ctx->pos = 0;
241  }
242  }
243  return 0;
244 }
245 
246 /*
247  * public interface
248  */
249 
250 int
251 pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
252 {
254 
255  return cfb_process(ctx, data, len, dst, mix);
256 }
257 
258 int
259 pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
260 {
262 
263  return cfb_process(ctx, data, len, dst, mix);
264 }
uint8 encbuf[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:48
#define px_cipher_init(c, k, klen, iv)
Definition: px.h:225
int block_no
Definition: pgp-cfb.c:44
#define px_free(p)
Definition: px.h:47
unsigned char uint8
Definition: c.h:263
#define px_cipher_free(c)
Definition: px.h:230
int pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:259
#define PGP_MAX_BLOCK
Definition: pgp.h:113
PX_Cipher * ciph
Definition: pgp-cfb.c:41
int(* mix_data_t)(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:37
static int cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst, mix_data_t mix_data)
Definition: pgp-cfb.c:198
uint8 fr[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:46
int pgp_load_cipher(int code, PX_Cipher **res)
Definition: pgp.c:168
static int mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:106
int resync
Definition: pgp-cfb.c:45
int block_size
Definition: pgp-cfb.c:42
#define px_cipher_block_size(c)
Definition: px.h:223
void pgp_cfb_free(PGP_CFB *ctx)
Definition: pgp-cfb.c:84
static int mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:95
uint8 fre[PGP_MAX_BLOCK]
Definition: pgp-cfb.c:47
#define mix(a, b, c)
Definition: hashfunc.c:243
#define NULL
Definition: c.h:226
int pos
Definition: pgp-cfb.c:43
Definition: px.h:155
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
#define px_alloc(s)
Definition: px.h:45
static int mix_encrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:126
int i
static int mix_decrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:158
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:134
#define px_cipher_encrypt(c, data, dlen, res)
Definition: px.h:226
int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
Definition: pgp-cfb.c:251