PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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, "No strong random source"},
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 #ifdef HAVE_STRONG_RANDOM
101  ereport(ERROR,
102  (errcode(ERRCODE_INTERNAL_ERROR),
103  errmsg("could not generate a random number")));
104 #else
105  ereport(ERROR,
106  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
107  errmsg("generating random data is not supported by this build"),
108  errdetail("This functionality requires a source of strong random numbers"),
109  errhint("You need to rebuild PostgreSQL using --enable-strong-random")));
110 #endif
111  }
112  else
113  {
114  /* For other errors, use the message from the above list. */
115  ereport(ERROR,
116  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
117  errmsg("%s", px_strerror(err))));
118  }
119 }
120 
121 const char *
123 {
124  const struct error_desc *e;
125 
126  for (e = px_err_list; e->desc; e++)
127  if (e->err == err)
128  return e->desc;
129  return "Bad error code";
130 }
131 
132 /* memset that must not be optimized away */
133 void
134 px_memset(void *ptr, int c, size_t len)
135 {
136  memset(ptr, c, len);
137 }
138 
139 const char *
140 px_resolve_alias(const PX_Alias *list, const char *name)
141 {
142  while (list->name)
143  {
144  if (pg_strcasecmp(list->alias, name) == 0)
145  return list->name;
146  list++;
147  }
148  return name;
149 }
150 
151 static void (*debug_handler) (const char *) = NULL;
152 
153 void
154 px_set_debug_handler(void (*handler) (const char *))
155 {
156  debug_handler = handler;
157 }
158 
159 void
160 px_debug(const char *fmt,...)
161 {
162  va_list ap;
163 
164  va_start(ap, fmt);
165  if (debug_handler)
166  {
167  char buf[512];
168 
169  vsnprintf(buf, sizeof(buf), fmt, ap);
170  debug_handler(buf);
171  }
172  va_end(ap);
173 }
174 
175 /*
176  * combo - cipher + padding (+ checksum)
177  */
178 
179 static unsigned
180 combo_encrypt_len(PX_Combo *cx, unsigned dlen)
181 {
182  return dlen + 512;
183 }
184 
185 static unsigned
186 combo_decrypt_len(PX_Combo *cx, unsigned dlen)
187 {
188  return dlen;
189 }
190 
191 static int
192 combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
193  const uint8 *iv, unsigned ivlen)
194 {
195  int err;
196  unsigned ks,
197  ivs;
198  PX_Cipher *c = cx->cipher;
199  uint8 *ivbuf = NULL;
200  uint8 *keybuf;
201 
202  ks = px_cipher_key_size(c);
203 
204  ivs = px_cipher_iv_size(c);
205  if (ivs > 0)
206  {
207  ivbuf = px_alloc(ivs);
208  memset(ivbuf, 0, ivs);
209  if (ivlen > ivs)
210  memcpy(ivbuf, iv, ivs);
211  else
212  memcpy(ivbuf, iv, ivlen);
213  }
214 
215  if (klen > ks)
216  klen = ks;
217  keybuf = px_alloc(ks);
218  memset(keybuf, 0, ks);
219  memcpy(keybuf, key, klen);
220 
221  err = px_cipher_init(c, keybuf, klen, ivbuf);
222 
223  if (ivbuf)
224  px_free(ivbuf);
225  px_free(keybuf);
226 
227  return err;
228 }
229 
230 static int
231 combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
232  uint8 *res, unsigned *rlen)
233 {
234  int err = 0;
235  uint8 *bbuf;
236  unsigned bs,
237  bpos,
238  i,
239  pad;
240 
241  PX_Cipher *c = cx->cipher;
242 
243  bbuf = NULL;
244  bs = px_cipher_block_size(c);
245 
246  /* encrypt */
247  if (bs > 1)
248  {
249  bbuf = px_alloc(bs * 4);
250  bpos = dlen % bs;
251  *rlen = dlen - bpos;
252  memcpy(bbuf, data + *rlen, bpos);
253 
254  /* encrypt full-block data */
255  if (*rlen)
256  {
257  err = px_cipher_encrypt(c, data, *rlen, res);
258  if (err)
259  goto out;
260  }
261 
262  /* bbuf has now bpos bytes of stuff */
263  if (cx->padding)
264  {
265  pad = bs - (bpos % bs);
266  for (i = 0; i < pad; i++)
267  bbuf[bpos++] = pad;
268  }
269  else if (bpos % bs)
270  {
271  /* ERROR? */
272  pad = bs - (bpos % bs);
273  for (i = 0; i < pad; i++)
274  bbuf[bpos++] = 0;
275  }
276 
277  /* encrypt the rest - pad */
278  if (bpos)
279  {
280  err = px_cipher_encrypt(c, bbuf, bpos, res + *rlen);
281  *rlen += bpos;
282  }
283  }
284  else
285  {
286  /* stream cipher/mode - no pad needed */
287  err = px_cipher_encrypt(c, data, dlen, res);
288  if (err)
289  goto out;
290  *rlen = dlen;
291  }
292 out:
293  if (bbuf)
294  px_free(bbuf);
295 
296  return err;
297 }
298 
299 static int
300 combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
301  uint8 *res, unsigned *rlen)
302 {
303  unsigned bs,
304  i,
305  pad;
306  unsigned pad_ok;
307 
308  PX_Cipher *c = cx->cipher;
309 
310  /* decide whether zero-length input is allowed */
311  if (dlen == 0)
312  {
313  /* with padding, empty ciphertext is not allowed */
314  if (cx->padding)
315  return PXE_DECRYPT_FAILED;
316 
317  /* without padding, report empty result */
318  *rlen = 0;
319  return 0;
320  }
321 
322  bs = px_cipher_block_size(c);
323  if (bs > 1 && (dlen % bs) != 0)
324  goto block_error;
325 
326  /* decrypt */
327  *rlen = dlen;
328  px_cipher_decrypt(c, data, dlen, res);
329 
330  /* unpad */
331  if (bs > 1 && cx->padding)
332  {
333  pad = res[*rlen - 1];
334  pad_ok = 0;
335  if (pad > 0 && pad <= bs && pad <= *rlen)
336  {
337  pad_ok = 1;
338  for (i = *rlen - pad; i < *rlen; i++)
339  if (res[i] != pad)
340  {
341  pad_ok = 0;
342  break;
343  }
344  }
345 
346  if (pad_ok)
347  *rlen -= pad;
348  }
349 
350  return 0;
351 
352 block_error:
353  return PXE_NOTBLOCKSIZE;
354 }
355 
356 static void
358 {
359  if (cx->cipher)
360  px_cipher_free(cx->cipher);
361  px_memset(cx, 0, sizeof(*cx));
362  px_free(cx);
363 }
364 
365 /* PARSER */
366 
367 static int
368 parse_cipher_name(char *full, char **cipher, char **pad)
369 {
370  char *p,
371  *p2,
372  *q;
373 
374  *cipher = full;
375  *pad = NULL;
376 
377  p = strchr(full, '/');
378  if (p != NULL)
379  *p++ = 0;
380  while (p != NULL)
381  {
382  if ((q = strchr(p, '/')) != NULL)
383  *q++ = 0;
384 
385  if (!*p)
386  {
387  p = q;
388  continue;
389  }
390  p2 = strchr(p, ':');
391  if (p2 != NULL)
392  {
393  *p2++ = 0;
394  if (strcmp(p, "pad") == 0)
395  *pad = p2;
396  else
397  return PXE_BAD_OPTION;
398  }
399  else
400  return PXE_BAD_FORMAT;
401 
402  p = q;
403  }
404  return 0;
405 }
406 
407 /* provider */
408 
409 int
410 px_find_combo(const char *name, PX_Combo **res)
411 {
412  int err;
413  char *buf,
414  *s_cipher,
415  *s_pad;
416 
417  PX_Combo *cx;
418 
419  cx = px_alloc(sizeof(*cx));
420  memset(cx, 0, sizeof(*cx));
421 
422  buf = px_alloc(strlen(name) + 1);
423  strcpy(buf, name);
424 
425  err = parse_cipher_name(buf, &s_cipher, &s_pad);
426  if (err)
427  {
428  px_free(buf);
429  px_free(cx);
430  return err;
431  }
432 
433  err = px_find_cipher(s_cipher, &cx->cipher);
434  if (err)
435  goto err1;
436 
437  if (s_pad != NULL)
438  {
439  if (strcmp(s_pad, "pkcs") == 0)
440  cx->padding = 1;
441  else if (strcmp(s_pad, "none") == 0)
442  cx->padding = 0;
443  else
444  goto err1;
445  }
446  else
447  cx->padding = 1;
448 
449  cx->init = combo_init;
450  cx->encrypt = combo_encrypt;
451  cx->decrypt = combo_decrypt;
454  cx->free = combo_free;
455 
456  px_free(buf);
457 
458  *res = cx;
459 
460  return 0;
461 
462 err1:
463  if (cx->cipher)
464  px_cipher_free(cx->cipher);
465  px_free(cx);
466  px_free(buf);
467  return PXE_NO_CIPHER;
468 }
static void(* debug_handler)(const char *)
Definition: px.c:151
#define PXE_OK
Definition: px.h:62
static int s_pad(mp_int z, mp_size min)
Definition: imath.c:2324
#define PXE_PGP_UNSUPPORTED_HASH
Definition: px.h:85
#define PXE_PGP_KEYPKT_CORRUPT
Definition: px.h:99
void px_THROW_ERROR(int err)
Definition: px.c:96
#define PXE_ARGUMENT_ERROR
Definition: px.h:74
int errhint(const char *fmt,...)
Definition: elog.c:987
#define PXE_PGP_CORRUPT_DATA
Definition: px.h:81
#define PXE_HASH_UNUSABLE_FOR_HMAC
Definition: px.h:71
static unsigned combo_encrypt_len(PX_Combo *cx, unsigned dlen)
Definition: px.c:180
#define px_cipher_init(c, k, klen, iv)
Definition: px.h:224
unsigned padding
Definition: px.h:182
#define PXE_DECRYPT_FAILED
Definition: px.h:79
int(* decrypt)(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.h:175
static int combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.c:231
int err
Definition: px.c:38
#define PXE_PGP_UNSUPPORTED_CIPHER
Definition: px.h:84
#define px_free(p)
Definition: px.h:46
#define PXE_PGP_EXPECT_SECRET_KEY
Definition: px.h:97
#define PXE_PGP_COMPRESSION_ERROR
Definition: px.h:86
unsigned char uint8
Definition: c.h:266
#define px_cipher_free(c)
Definition: px.h:229
#define PXE_PGP_WRONG_KEY
Definition: px.h:94
Definition: px.h:169
int errcode(int sqlerrcode)
Definition: elog.c:575
#define px_cipher_decrypt(c, data, dlen, res)
Definition: px.h:227
const char * px_resolve_alias(const PX_Alias *list, const char *name)
Definition: px.c:140
#define PXE_PGP_MULTIPLE_SUBKEYS
Definition: px.h:104
static unsigned combo_decrypt_len(PX_Combo *cx, unsigned dlen)
Definition: px.c:186
#define PXE_NO_RANDOM
Definition: px.h:78
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
const char * desc
Definition: px.c:39
unsigned(* decrypt_len)(PX_Combo *cx, unsigned dlen)
Definition: px.h:178
PX_Cipher * cipher
Definition: px.h:181
Definition: px.h:129
#define PXE_PGP_BAD_S2K_MODE
Definition: px.h:102
int int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
#define PXE_PGP_UNSUPPORTED_COMPR
Definition: px.h:83
#define PXE_UNKNOWN_SALT_ALGO
Definition: px.h:75
#define PXE_PGP_NO_USABLE_KEY
Definition: px.h:100
void(* free)(PX_Combo *cx)
Definition: px.h:179
int cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
#define ERROR
Definition: elog.h:43
#define PXE_BAD_OPTION
Definition: px.h:67
#define PXE_NO_HASH
Definition: px.h:64
static int parse_cipher_name(char *full, char **cipher, char **pad)
Definition: px.c:368
char * c
static char * buf
Definition: pg_test_fsync.c:66
#define PXE_PGP_NOT_TEXT
Definition: px.h:87
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define PXE_PGP_UNSUPPORTED_PUBALGO
Definition: px.h:103
static const struct error_desc px_err_list[]
Definition: px.c:42
#define PXE_PGP_UNEXPECTED_PKT
Definition: px.h:88
#define PXE_PGP_CORRUPT_ARMOR
Definition: px.h:82
int px_find_combo(const char *name, PX_Combo **res)
Definition: px.c:410
#define PXE_BUG
Definition: px.h:73
void px_set_debug_handler(void(*handler)(const char *))
Definition: px.c:154
#define ereport(elevel, rest)
Definition: elog.h:122
#define px_cipher_iv_size(c)
Definition: px.h:223
int(* encrypt)(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.h:173
#define PXE_PGP_MULTIPLE_KEYS
Definition: px.h:95
const char * px_strerror(int err)
Definition: px.c:122
#define px_cipher_block_size(c)
Definition: px.h:222
char * alias
Definition: px.h:131
static int combo_init(PX_Combo *cx, const uint8 *key, unsigned klen, const uint8 *iv, unsigned ivlen)
Definition: px.c:192
#define PXE_PGP_EXPECT_PUBLIC_KEY
Definition: px.h:96
#define PXE_BAD_FORMAT
Definition: px.h:68
static void combo_free(PX_Combo *cx)
Definition: px.c:357
#define PXE_PGP_NEED_SECRET_PSW
Definition: px.h:101
#define PXE_KEY_TOO_BIG
Definition: px.h:69
#define PXE_CIPHER_INIT
Definition: px.h:70
#define NULL
Definition: c.h:229
#define PXE_BAD_SALT_ROUNDS
Definition: px.h:76
void px_debug(const char *fmt,...)
Definition: px.c:160
#define px_cipher_key_size(c)
Definition: px.h:221
#define PXE_PGP_UNKNOWN_PUBALGO
Definition: px.h:93
#define PXE_DEV_READ_ERROR
Definition: px.h:72
#define PXE_NOTBLOCKSIZE
Definition: px.h:66
Definition: px.h:154
const char * name
Definition: encode.c:521
#define PXE_PGP_MATH_FAILED
Definition: px.h:90
#define px_alloc(s)
Definition: px.h:44
e
Definition: preproc-init.c:82
tuple list
Definition: sort-test.py:11
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PXE_PGP_SHORT_ELGAMAL_KEY
Definition: px.h:91
int i
#define PXE_NO_CIPHER
Definition: px.h:65
static int combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.c:300
#define PXE_PGP_NOT_V4_KEYPKT
Definition: px.h:98
char * name
Definition: px.h:132
int(* init)(PX_Combo *cx, const uint8 *key, unsigned klen, const uint8 *iv, unsigned ivlen)
Definition: px.h:171
Definition: px.c:36
#define PXE_MCRYPT_INTERNAL
Definition: px.h:77
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:225
#define PXE_ERR_GENERIC
Definition: px.h:63
int px_find_cipher(const char *name, PX_Cipher **res)
Definition: internal.c:597
unsigned(* encrypt_len)(PX_Combo *cx, unsigned dlen)
Definition: px.h:177