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_ENCRYPT_FAILED, "Encryption failed"},
62  {PXE_PGP_CORRUPT_DATA, "Wrong key or corrupt data"},
63  {PXE_PGP_CORRUPT_ARMOR, "Corrupt ascii-armor"},
64  {PXE_PGP_UNSUPPORTED_COMPR, "Unsupported compression algorithm"},
65  {PXE_PGP_UNSUPPORTED_CIPHER, "Unsupported cipher algorithm"},
66  {PXE_PGP_UNSUPPORTED_HASH, "Unsupported digest algorithm"},
67  {PXE_PGP_COMPRESSION_ERROR, "Compression error"},
68  {PXE_PGP_NOT_TEXT, "Not text data"},
69  {PXE_PGP_UNEXPECTED_PKT, "Unexpected packet in key data"},
70  {PXE_PGP_MATH_FAILED, "Math operation failed"},
71  {PXE_PGP_SHORT_ELGAMAL_KEY, "Elgamal keys must be at least 1024 bits long"},
72  {PXE_PGP_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
73  {PXE_PGP_WRONG_KEY, "Wrong key"},
75  "Several keys given - pgcrypto does not handle keyring"},
76  {PXE_PGP_EXPECT_PUBLIC_KEY, "Refusing to encrypt with secret key"},
77  {PXE_PGP_EXPECT_SECRET_KEY, "Cannot decrypt with public key"},
78  {PXE_PGP_NOT_V4_KEYPKT, "Only V4 key packets are supported"},
79  {PXE_PGP_KEYPKT_CORRUPT, "Corrupt key packet"},
80  {PXE_PGP_NO_USABLE_KEY, "No encryption key found"},
81  {PXE_PGP_NEED_SECRET_PSW, "Need password for secret key"},
82  {PXE_PGP_BAD_S2K_MODE, "Bad S2K mode"},
83  {PXE_PGP_UNSUPPORTED_PUBALGO, "Unsupported public key algorithm"},
84  {PXE_PGP_MULTIPLE_SUBKEYS, "Several subkeys not supported"},
85 
86  {0, NULL},
87 };
88 
89 /*
90  * Call ereport(ERROR, ...), with an error code and message corresponding to
91  * the PXE_* error code given as argument.
92  *
93  * This is similar to px_strerror(err), but for some errors, we fill in the
94  * error code and detail fields more appropriately.
95  */
96 void
98 {
99  if (err == PXE_NO_RANDOM)
100  {
101  ereport(ERROR,
102  (errcode(ERRCODE_INTERNAL_ERROR),
103  errmsg("could not generate a random number")));
104  }
105  else
106  {
107  /* For other errors, use the message from the above list. */
108  ereport(ERROR,
109  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
110  errmsg("%s", px_strerror(err))));
111  }
112 }
113 
114 const char *
116 {
117  const struct error_desc *e;
118 
119  for (e = px_err_list; e->desc; e++)
120  if (e->err == err)
121  return e->desc;
122  return "Bad error code";
123 }
124 
125 /* memset that must not be optimized away */
126 void
127 px_memset(void *ptr, int c, size_t len)
128 {
129  memset(ptr, c, len);
130 }
131 
132 const char *
133 px_resolve_alias(const PX_Alias *list, const char *name)
134 {
135  while (list->name)
136  {
137  if (pg_strcasecmp(list->alias, name) == 0)
138  return list->name;
139  list++;
140  }
141  return name;
142 }
143 
144 static void (*debug_handler) (const char *) = NULL;
145 
146 void
147 px_set_debug_handler(void (*handler) (const char *))
148 {
149  debug_handler = handler;
150 }
151 
152 void
153 px_debug(const char *fmt,...)
154 {
155  va_list ap;
156 
157  va_start(ap, fmt);
158  if (debug_handler)
159  {
160  char buf[512];
161 
162  vsnprintf(buf, sizeof(buf), fmt, ap);
163  debug_handler(buf);
164  }
165  va_end(ap);
166 }
167 
168 /*
169  * combo - cipher + padding (+ checksum)
170  */
171 
172 static unsigned
173 combo_encrypt_len(PX_Combo *cx, unsigned dlen)
174 {
175  return dlen + 512;
176 }
177 
178 static unsigned
179 combo_decrypt_len(PX_Combo *cx, unsigned dlen)
180 {
181  return dlen;
182 }
183 
184 static int
185 combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
186  const uint8 *iv, unsigned ivlen)
187 {
188  int err;
189  unsigned ks,
190  ivs;
191  PX_Cipher *c = cx->cipher;
192  uint8 *ivbuf = NULL;
193  uint8 *keybuf;
194 
195  ks = px_cipher_key_size(c);
196 
197  ivs = px_cipher_iv_size(c);
198  if (ivs > 0)
199  {
200  ivbuf = palloc0(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 = palloc0(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  pfree(ivbuf);
217  pfree(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 = palloc(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  pfree(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  pfree(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 = palloc0(sizeof(*cx));
412  buf = pstrdup(name);
413 
414  err = parse_cipher_name(buf, &s_cipher, &s_pad);
415  if (err)
416  {
417  pfree(buf);
418  pfree(cx);
419  return err;
420  }
421 
422  err = px_find_cipher(s_cipher, &cx->cipher);
423  if (err)
424  goto err1;
425 
426  if (s_pad != NULL)
427  {
428  if (strcmp(s_pad, "pkcs") == 0)
429  cx->padding = 1;
430  else if (strcmp(s_pad, "none") == 0)
431  cx->padding = 0;
432  else
433  goto err1;
434  }
435  else
436  cx->padding = 1;
437 
438  cx->init = combo_init;
439  cx->encrypt = combo_encrypt;
440  cx->decrypt = combo_decrypt;
443  cx->free = combo_free;
444 
445  pfree(buf);
446 
447  *res = cx;
448 
449  return 0;
450 
451 err1:
452  if (cx->cipher)
453  px_cipher_free(cx->cipher);
454  pfree(cx);
455  pfree(buf);
456  return PXE_NO_CIPHER;
457 }
#define PXE_OK
Definition: px.h:46
#define PXE_PGP_UNSUPPORTED_HASH
Definition: px.h:70
#define PXE_PGP_KEYPKT_CORRUPT
Definition: px.h:84
void px_THROW_ERROR(int err)
Definition: px.c:97
#define PXE_ARGUMENT_ERROR
Definition: px.h:58
#define PXE_PGP_CORRUPT_DATA
Definition: px.h:66
#define PXE_HASH_UNUSABLE_FOR_HMAC
Definition: px.h:55
static unsigned combo_encrypt_len(PX_Combo *cx, unsigned dlen)
Definition: px.c:173
#define px_cipher_init(c, k, klen, iv)
Definition: px.h:209
unsigned padding
Definition: px.h:167
#define PXE_DECRYPT_FAILED
Definition: px.h:63
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:69
char * pstrdup(const char *in)
Definition: mcxt.c:1187
void(* free)(PX_Combo *cx)
Definition: px.h:164
#define PXE_PGP_EXPECT_SECRET_KEY
Definition: px.h:82
#define PXE_PGP_COMPRESSION_ERROR
Definition: px.h:71
unsigned char uint8
Definition: c.h:427
#define px_cipher_free(c)
Definition: px.h:214
#define PXE_PGP_WRONG_KEY
Definition: px.h:79
Definition: px.h:154
int errcode(int sqlerrcode)
Definition: elog.c:691
#define px_cipher_decrypt(c, data, dlen, res)
Definition: px.h:212
const char * px_resolve_alias(const PX_Alias *list, const char *name)
Definition: px.c:133
#define PXE_PGP_MULTIPLE_SUBKEYS
Definition: px.h:89
static unsigned combo_decrypt_len(PX_Combo *cx, unsigned dlen)
Definition: px.c:179
static void(* debug_handler)(const char *)
Definition: px.c:144
#define PXE_NO_RANDOM
Definition: px.h:62
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:166
Definition: px.h:114
#define PXE_PGP_BAD_S2K_MODE
Definition: px.h:87
#define PXE_PGP_UNSUPPORTED_COMPR
Definition: px.h:68
#define PXE_UNKNOWN_SALT_ALGO
Definition: px.h:59
#define PXE_PGP_NO_USABLE_KEY
Definition: px.h:85
void pfree(void *pointer)
Definition: mcxt.c:1057
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:214
#define PXE_BAD_OPTION
Definition: px.h:51
#define PXE_NO_HASH
Definition: px.h:48
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:68
#define PXE_PGP_NOT_TEXT
Definition: px.h:72
unsigned(* decrypt_len)(PX_Combo *cx, unsigned dlen)
Definition: px.h:163
#define PXE_PGP_UNSUPPORTED_PUBALGO
Definition: px.h:88
static const struct error_desc px_err_list[]
Definition: px.c:42
#define PXE_PGP_UNEXPECTED_PKT
Definition: px.h:73
#define PXE_PGP_CORRUPT_ARMOR
Definition: px.h:67
int px_find_combo(const char *name, PX_Combo **res)
Definition: px.c:402
#define PXE_BUG
Definition: px.h:57
void px_set_debug_handler(void(*handler)(const char *))
Definition: px.c:147
#define px_cipher_iv_size(c)
Definition: px.h:208
#define PXE_PGP_MULTIPLE_KEYS
Definition: px.h:80
const char * px_strerror(int err)
Definition: px.c:115
#define px_cipher_block_size(c)
Definition: px.h:207
int(* init)(PX_Combo *cx, const uint8 *key, unsigned klen, const uint8 *iv, unsigned ivlen)
Definition: px.h:156
int(* encrypt)(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.h:158
void * palloc0(Size size)
Definition: mcxt.c:981
unsigned(* encrypt_len)(PX_Combo *cx, unsigned dlen)
Definition: px.h:162
char * alias
Definition: px.h:116
static int combo_init(PX_Combo *cx, const uint8 *key, unsigned klen, const uint8 *iv, unsigned ivlen)
Definition: px.c:185
#define PXE_PGP_EXPECT_PUBLIC_KEY
Definition: px.h:81
#define ereport(elevel,...)
Definition: elog.h:155
#define PXE_BAD_FORMAT
Definition: px.h:52
static void combo_free(PX_Combo *cx)
Definition: px.c:349
#define PXE_PGP_NEED_SECRET_PSW
Definition: px.h:86
#define PXE_KEY_TOO_BIG
Definition: px.h:53
#define PXE_ENCRYPT_FAILED
Definition: px.h:64
#define PXE_CIPHER_INIT
Definition: px.h:54
static bool s_pad(mp_int z, mp_size min)
Definition: imath.c:2253
#define PXE_BAD_SALT_ROUNDS
Definition: px.h:60
void px_debug(const char *fmt,...)
Definition: px.c:153
#define px_cipher_key_size(c)
Definition: px.h:206
#define PXE_PGP_UNKNOWN_PUBALGO
Definition: px.h:78
#define PXE_DEV_READ_ERROR
Definition: px.h:56
#define PXE_NOTBLOCKSIZE
Definition: px.h:50
Definition: px.h:139
const char * name
Definition: encode.c:561
#define PXE_PGP_MATH_FAILED
Definition: px.h:75
e
Definition: preproc-init.c:82
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define PXE_PGP_SHORT_ELGAMAL_KEY
Definition: px.h:76
int i
#define PXE_NO_CIPHER
Definition: px.h:49
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:160
#define PXE_PGP_NOT_V4_KEYPKT
Definition: px.h:83
char * name
Definition: px.h:117
Definition: px.c:36
#define PXE_MCRYPT_INTERNAL
Definition: px.h:61
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
#define PXE_ERR_GENERIC
Definition: px.h:47
int px_find_cipher(const char *name, PX_Cipher **res)
Definition: internal.c:572