PostgreSQL Source Code  git master
px.c
Go to the documentation of this file.
1 /*
2  * px.c
3  * Various cryptographic stuff for PostgreSQL.
4  *
5  * Copyright (c) 2001 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/px.c
30  */
31 
32 #include "postgres.h"
33 
34 #include "px.h"
35 
36 struct error_desc
37 {
38  int err;
39  const char *desc;
40 };
41 
42 static const struct error_desc px_err_list[] = {
43  {PXE_OK, "Everything ok"},
44  {PXE_ERR_GENERIC, "Some PX error (not specified)"},
45  {PXE_NO_HASH, "No such hash algorithm"},
46  {PXE_NO_CIPHER, "No such cipher algorithm"},
47  {PXE_NOTBLOCKSIZE, "Data not a multiple of block size"},
48  {PXE_BAD_OPTION, "Unknown option"},
49  {PXE_BAD_FORMAT, "Badly formatted type"},
50  {PXE_KEY_TOO_BIG, "Key was too big"},
51  {PXE_CIPHER_INIT, "Cipher cannot be initialized ?"},
52  {PXE_HASH_UNUSABLE_FOR_HMAC, "This hash algorithm is unusable for HMAC"},
53  {PXE_DEV_READ_ERROR, "Error reading from random device"},
54  {PXE_BUG, "pgcrypto bug"},
55  {PXE_ARGUMENT_ERROR, "Illegal argument to function"},
56  {PXE_UNKNOWN_SALT_ALGO, "Unknown salt algorithm"},
57  {PXE_BAD_SALT_ROUNDS, "Incorrect number of rounds"},
58  {PXE_MCRYPT_INTERNAL, "mcrypt internal error"},
59  {PXE_NO_RANDOM, "Failed to generate strong random bits"},
60  {PXE_DECRYPT_FAILED, "Decryption failed"},
61  {PXE_PGP_CORRUPT_DATA, "Wrong key or corrupt data"},
62  {PXE_PGP_CORRUPT_ARMOR, "Corrupt ascii-armor"},
63  {PXE_PGP_UNSUPPORTED_COMPR, "Unsupported compression algorithm"},
64  {PXE_PGP_UNSUPPORTED_CIPHER, "Unsupported cipher algorithm"},
65  {PXE_PGP_UNSUPPORTED_HASH, "Unsupported digest algorithm"},
66  {PXE_PGP_COMPRESSION_ERROR, "Compression error"},
67  {PXE_PGP_NOT_TEXT, "Not text data"},
68  {PXE_PGP_UNEXPECTED_PKT, "Unexpected packet in key data"},
69  {PXE_PGP_MATH_FAILED, "Math operation failed"},
70  {PXE_PGP_SHORT_ELGAMAL_KEY, "Elgamal keys must be at least 1024 bits long"},
71  {PXE_PGP_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
72  {PXE_PGP_WRONG_KEY, "Wrong key"},
74  "Several keys given - pgcrypto does not handle keyring"},
75  {PXE_PGP_EXPECT_PUBLIC_KEY, "Refusing to encrypt with secret key"},
76  {PXE_PGP_EXPECT_SECRET_KEY, "Cannot decrypt with public key"},
77  {PXE_PGP_NOT_V4_KEYPKT, "Only V4 key packets are supported"},
78  {PXE_PGP_KEYPKT_CORRUPT, "Corrupt key packet"},
79  {PXE_PGP_NO_USABLE_KEY, "No encryption key found"},
80  {PXE_PGP_NEED_SECRET_PSW, "Need password for secret key"},
81  {PXE_PGP_BAD_S2K_MODE, "Bad S2K mode"},
82  {PXE_PGP_UNSUPPORTED_PUBALGO, "Unsupported public key algorithm"},
83  {PXE_PGP_MULTIPLE_SUBKEYS, "Several subkeys not supported"},
84 
85  {0, NULL},
86 };
87 
88 /*
89  * Call ereport(ERROR, ...), with an error code and message corresponding to
90  * the PXE_* error code given as argument.
91  *
92  * This is similar to px_strerror(err), but for some errors, we fill in the
93  * error code and detail fields more appropriately.
94  */
95 void
97 {
98  if (err == PXE_NO_RANDOM)
99  {
100  ereport(ERROR,
101  (errcode(ERRCODE_INTERNAL_ERROR),
102  errmsg("could not generate a random number")));
103  }
104  else
105  {
106  /* For other errors, use the message from the above list. */
107  ereport(ERROR,
108  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
109  errmsg("%s", px_strerror(err))));
110  }
111 }
112 
113 const char *
115 {
116  const struct error_desc *e;
117 
118  for (e = px_err_list; e->desc; e++)
119  if (e->err == err)
120  return e->desc;
121  return "Bad error code";
122 }
123 
124 /* memset that must not be optimized away */
125 void
126 px_memset(void *ptr, int c, size_t len)
127 {
128  memset(ptr, c, len);
129 }
130 
131 const char *
132 px_resolve_alias(const PX_Alias *list, const char *name)
133 {
134  while (list->name)
135  {
136  if (pg_strcasecmp(list->alias, name) == 0)
137  return list->name;
138  list++;
139  }
140  return name;
141 }
142 
143 static void (*debug_handler) (const char *) = NULL;
144 
145 void
146 px_set_debug_handler(void (*handler) (const char *))
147 {
148  debug_handler = handler;
149 }
150 
151 void
152 px_debug(const char *fmt,...)
153 {
154  va_list ap;
155 
156  va_start(ap, fmt);
157  if (debug_handler)
158  {
159  char buf[512];
160 
161  vsnprintf(buf, sizeof(buf), fmt, ap);
162  debug_handler(buf);
163  }
164  va_end(ap);
165 }
166 
167 /*
168  * combo - cipher + padding (+ checksum)
169  */
170 
171 static unsigned
172 combo_encrypt_len(PX_Combo *cx, unsigned dlen)
173 {
174  return dlen + 512;
175 }
176 
177 static unsigned
178 combo_decrypt_len(PX_Combo *cx, unsigned dlen)
179 {
180  return dlen;
181 }
182 
183 static int
184 combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
185  const uint8 *iv, unsigned ivlen)
186 {
187  int err;
188  unsigned ks,
189  ivs;
190  PX_Cipher *c = cx->cipher;
191  uint8 *ivbuf = NULL;
192  uint8 *keybuf;
193 
194  ks = px_cipher_key_size(c);
195 
196  ivs = px_cipher_iv_size(c);
197  if (ivs > 0)
198  {
199  ivbuf = px_alloc(ivs);
200  memset(ivbuf, 0, ivs);
201  if (ivlen > ivs)
202  memcpy(ivbuf, iv, ivs);
203  else
204  memcpy(ivbuf, iv, ivlen);
205  }
206 
207  if (klen > ks)
208  klen = ks;
209  keybuf = px_alloc(ks);
210  memset(keybuf, 0, ks);
211  memcpy(keybuf, key, klen);
212 
213  err = px_cipher_init(c, keybuf, klen, ivbuf);
214 
215  if (ivbuf)
216  px_free(ivbuf);
217  px_free(keybuf);
218 
219  return err;
220 }
221 
222 static int
223 combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
224  uint8 *res, unsigned *rlen)
225 {
226  int err = 0;
227  uint8 *bbuf;
228  unsigned bs,
229  bpos,
230  i,
231  pad;
232 
233  PX_Cipher *c = cx->cipher;
234 
235  bbuf = NULL;
236  bs = px_cipher_block_size(c);
237 
238  /* encrypt */
239  if (bs > 1)
240  {
241  bbuf = px_alloc(bs * 4);
242  bpos = dlen % bs;
243  *rlen = dlen - bpos;
244  memcpy(bbuf, data + *rlen, bpos);
245 
246  /* encrypt full-block data */
247  if (*rlen)
248  {
249  err = px_cipher_encrypt(c, data, *rlen, res);
250  if (err)
251  goto out;
252  }
253 
254  /* bbuf has now bpos bytes of stuff */
255  if (cx->padding)
256  {
257  pad = bs - (bpos % bs);
258  for (i = 0; i < pad; i++)
259  bbuf[bpos++] = pad;
260  }
261  else if (bpos % bs)
262  {
263  /* ERROR? */
264  pad = bs - (bpos % bs);
265  for (i = 0; i < pad; i++)
266  bbuf[bpos++] = 0;
267  }
268 
269  /* encrypt the rest - pad */
270  if (bpos)
271  {
272  err = px_cipher_encrypt(c, bbuf, bpos, res + *rlen);
273  *rlen += bpos;
274  }
275  }
276  else
277  {
278  /* stream cipher/mode - no pad needed */
279  err = px_cipher_encrypt(c, data, dlen, res);
280  if (err)
281  goto out;
282  *rlen = dlen;
283  }
284 out:
285  if (bbuf)
286  px_free(bbuf);
287 
288  return err;
289 }
290 
291 static int
292 combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
293  uint8 *res, unsigned *rlen)
294 {
295  unsigned bs,
296  i,
297  pad;
298  unsigned pad_ok;
299 
300  PX_Cipher *c = cx->cipher;
301 
302  /* decide whether zero-length input is allowed */
303  if (dlen == 0)
304  {
305  /* with padding, empty ciphertext is not allowed */
306  if (cx->padding)
307  return PXE_DECRYPT_FAILED;
308 
309  /* without padding, report empty result */
310  *rlen = 0;
311  return 0;
312  }
313 
314  bs = px_cipher_block_size(c);
315  if (bs > 1 && (dlen % bs) != 0)
316  goto block_error;
317 
318  /* decrypt */
319  *rlen = dlen;
320  px_cipher_decrypt(c, data, dlen, res);
321 
322  /* unpad */
323  if (bs > 1 && cx->padding)
324  {
325  pad = res[*rlen - 1];
326  pad_ok = 0;
327  if (pad > 0 && pad <= bs && pad <= *rlen)
328  {
329  pad_ok = 1;
330  for (i = *rlen - pad; i < *rlen; i++)
331  if (res[i] != pad)
332  {
333  pad_ok = 0;
334  break;
335  }
336  }
337 
338  if (pad_ok)
339  *rlen -= pad;
340  }
341 
342  return 0;
343 
344 block_error:
345  return PXE_NOTBLOCKSIZE;
346 }
347 
348 static void
350 {
351  if (cx->cipher)
352  px_cipher_free(cx->cipher);
353  px_memset(cx, 0, sizeof(*cx));
354  px_free(cx);
355 }
356 
357 /* PARSER */
358 
359 static int
360 parse_cipher_name(char *full, char **cipher, char **pad)
361 {
362  char *p,
363  *p2,
364  *q;
365 
366  *cipher = full;
367  *pad = NULL;
368 
369  p = strchr(full, '/');
370  if (p != NULL)
371  *p++ = 0;
372  while (p != NULL)
373  {
374  if ((q = strchr(p, '/')) != NULL)
375  *q++ = 0;
376 
377  if (!*p)
378  {
379  p = q;
380  continue;
381  }
382  p2 = strchr(p, ':');
383  if (p2 != NULL)
384  {
385  *p2++ = 0;
386  if (strcmp(p, "pad") == 0)
387  *pad = p2;
388  else
389  return PXE_BAD_OPTION;
390  }
391  else
392  return PXE_BAD_FORMAT;
393 
394  p = q;
395  }
396  return 0;
397 }
398 
399 /* provider */
400 
401 int
402 px_find_combo(const char *name, PX_Combo **res)
403 {
404  int err;
405  char *buf,
406  *s_cipher,
407  *s_pad;
408 
409  PX_Combo *cx;
410 
411  cx = px_alloc(sizeof(*cx));
412  memset(cx, 0, sizeof(*cx));
413 
414  buf = px_alloc(strlen(name) + 1);
415  strcpy(buf, name);
416 
417  err = parse_cipher_name(buf, &s_cipher, &s_pad);
418  if (err)
419  {
420  px_free(buf);
421  px_free(cx);
422  return err;
423  }
424 
425  err = px_find_cipher(s_cipher, &cx->cipher);
426  if (err)
427  goto err1;
428 
429  if (s_pad != NULL)
430  {
431  if (strcmp(s_pad, "pkcs") == 0)
432  cx->padding = 1;
433  else if (strcmp(s_pad, "none") == 0)
434  cx->padding = 0;
435  else
436  goto err1;
437  }
438  else
439  cx->padding = 1;
440 
441  cx->init = combo_init;
442  cx->encrypt = combo_encrypt;
443  cx->decrypt = combo_decrypt;
446  cx->free = combo_free;
447 
448  px_free(buf);
449 
450  *res = cx;
451 
452  return 0;
453 
454 err1:
455  if (cx->cipher)
456  px_cipher_free(cx->cipher);
457  px_free(cx);
458  px_free(buf);
459  return PXE_NO_CIPHER;
460 }
#define PXE_OK
Definition: px.h:59
#define PXE_PGP_UNSUPPORTED_HASH
Definition: px.h:82
#define PXE_PGP_KEYPKT_CORRUPT
Definition: px.h:96
void px_THROW_ERROR(int err)
Definition: px.c:96
#define PXE_ARGUMENT_ERROR
Definition: px.h:71
#define PXE_PGP_CORRUPT_DATA
Definition: px.h:78
#define PXE_HASH_UNUSABLE_FOR_HMAC
Definition: px.h:68
static unsigned combo_encrypt_len(PX_Combo *cx, unsigned dlen)
Definition: px.c:172
#define px_cipher_init(c, k, klen, iv)
Definition: px.h:221
unsigned padding
Definition: px.h:179
#define PXE_DECRYPT_FAILED
Definition: px.h:76
static int combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.c:223
int err
Definition: px.c:38
#define PXE_PGP_UNSUPPORTED_CIPHER
Definition: px.h:81
#define px_free(p)
Definition: px.h:46
void(* free)(PX_Combo *cx)
Definition: px.h:176
#define PXE_PGP_EXPECT_SECRET_KEY
Definition: px.h:94
#define PXE_PGP_COMPRESSION_ERROR
Definition: px.h:83
unsigned char uint8
Definition: c.h:357
#define px_cipher_free(c)
Definition: px.h:226
#define PXE_PGP_WRONG_KEY
Definition: px.h:91
Definition: px.h:166
int errcode(int sqlerrcode)
Definition: elog.c:608
#define px_cipher_decrypt(c, data, dlen, res)
Definition: px.h:224
const char * px_resolve_alias(const PX_Alias *list, const char *name)
Definition: px.c:132
#define PXE_PGP_MULTIPLE_SUBKEYS
Definition: px.h:101
static unsigned combo_decrypt_len(PX_Combo *cx, unsigned dlen)
Definition: px.c:178
static void(* debug_handler)(const char *)
Definition: px.c:143
#define PXE_NO_RANDOM
Definition: px.h:75
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
const char * desc
Definition: px.c:39
PX_Cipher * cipher
Definition: px.h:178
Definition: px.h:126
#define PXE_PGP_BAD_S2K_MODE
Definition: px.h:99
#define PXE_PGP_UNSUPPORTED_COMPR
Definition: px.h:80
#define PXE_UNKNOWN_SALT_ALGO
Definition: px.h:72
#define PXE_PGP_NO_USABLE_KEY
Definition: px.h:97
int cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
#define ERROR
Definition: elog.h:43
#define vsnprintf
Definition: port.h:191
#define PXE_BAD_OPTION
Definition: px.h:64
#define PXE_NO_HASH
Definition: px.h:61
static int parse_cipher_name(char *full, char **cipher, char **pad)
Definition: px.c:360
char * c
static char * buf
Definition: pg_test_fsync.c:67
#define PXE_PGP_NOT_TEXT
Definition: px.h:84
unsigned(* decrypt_len)(PX_Combo *cx, unsigned dlen)
Definition: px.h:175
#define PXE_PGP_UNSUPPORTED_PUBALGO
Definition: px.h:100
static const struct error_desc px_err_list[]
Definition: px.c:42
#define PXE_PGP_UNEXPECTED_PKT
Definition: px.h:85
#define PXE_PGP_CORRUPT_ARMOR
Definition: px.h:79
int px_find_combo(const char *name, PX_Combo **res)
Definition: px.c:402
#define PXE_BUG
Definition: px.h:70
void px_set_debug_handler(void(*handler)(const char *))
Definition: px.c:146
#define ereport(elevel, rest)
Definition: elog.h:141
#define px_cipher_iv_size(c)
Definition: px.h:220
#define PXE_PGP_MULTIPLE_KEYS
Definition: px.h:92
const char * px_strerror(int err)
Definition: px.c:114
#define px_cipher_block_size(c)
Definition: px.h:219
int(* init)(PX_Combo *cx, const uint8 *key, unsigned klen, const uint8 *iv, unsigned ivlen)
Definition: px.h:168
int(* encrypt)(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.h:170
unsigned(* encrypt_len)(PX_Combo *cx, unsigned dlen)
Definition: px.h:174
char * alias
Definition: px.h:128
static int combo_init(PX_Combo *cx, const uint8 *key, unsigned klen, const uint8 *iv, unsigned ivlen)
Definition: px.c:184
#define PXE_PGP_EXPECT_PUBLIC_KEY
Definition: px.h:93
#define PXE_BAD_FORMAT
Definition: px.h:65
static void combo_free(PX_Combo *cx)
Definition: px.c:349
#define PXE_PGP_NEED_SECRET_PSW
Definition: px.h:98
#define PXE_KEY_TOO_BIG
Definition: px.h:66
#define PXE_CIPHER_INIT
Definition: px.h:67
static bool s_pad(mp_int z, mp_size min)
Definition: imath.c:2253
#define PXE_BAD_SALT_ROUNDS
Definition: px.h:73
void px_debug(const char *fmt,...)
Definition: px.c:152
#define px_cipher_key_size(c)
Definition: px.h:218
#define PXE_PGP_UNKNOWN_PUBALGO
Definition: px.h:90
#define PXE_DEV_READ_ERROR
Definition: px.h:69
#define PXE_NOTBLOCKSIZE
Definition: px.h:63
Definition: px.h:151
const char * name
Definition: encode.c:521
#define PXE_PGP_MATH_FAILED
Definition: px.h:87
#define px_alloc(s)
Definition: px.h:44
e
Definition: preproc-init.c:82
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define PXE_PGP_SHORT_ELGAMAL_KEY
Definition: px.h:88
int i
#define PXE_NO_CIPHER
Definition: px.h:62
static int combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.c:292
int(* decrypt)(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.h:172
#define PXE_PGP_NOT_V4_KEYPKT
Definition: px.h:95
char * name
Definition: px.h:129
Definition: px.c:36
#define PXE_MCRYPT_INTERNAL
Definition: px.h:74
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:126
#define px_cipher_encrypt(c, data, dlen, res)
Definition: px.h:222
#define PXE_ERR_GENERIC
Definition: px.h:60
int px_find_cipher(const char *name, PX_Cipher **res)
Definition: internal.c:578