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_NO_HASH, "No such hash algorithm"},
45  {PXE_NO_CIPHER, "No such cipher algorithm"},
46  {PXE_BAD_OPTION, "Unknown option"},
47  {PXE_BAD_FORMAT, "Badly formatted type"},
48  {PXE_KEY_TOO_BIG, "Key was too big"},
49  {PXE_CIPHER_INIT, "Cipher cannot be initialized"},
50  {PXE_HASH_UNUSABLE_FOR_HMAC, "This hash algorithm is unusable for HMAC"},
51  {PXE_BUG, "pgcrypto bug"},
52  {PXE_ARGUMENT_ERROR, "Illegal argument to function"},
53  {PXE_UNKNOWN_SALT_ALGO, "Unknown salt algorithm"},
54  {PXE_BAD_SALT_ROUNDS, "Incorrect number of rounds"},
55  {PXE_NO_RANDOM, "Failed to generate strong random bits"},
56  {PXE_DECRYPT_FAILED, "Decryption failed"},
57  {PXE_ENCRYPT_FAILED, "Encryption failed"},
58  {PXE_PGP_CORRUPT_DATA, "Wrong key or corrupt data"},
59  {PXE_PGP_CORRUPT_ARMOR, "Corrupt ascii-armor"},
60  {PXE_PGP_UNSUPPORTED_COMPR, "Unsupported compression algorithm"},
61  {PXE_PGP_UNSUPPORTED_CIPHER, "Unsupported cipher algorithm"},
62  {PXE_PGP_UNSUPPORTED_HASH, "Unsupported digest algorithm"},
63  {PXE_PGP_COMPRESSION_ERROR, "Compression error"},
64  {PXE_PGP_NOT_TEXT, "Not text data"},
65  {PXE_PGP_UNEXPECTED_PKT, "Unexpected packet in key data"},
66  {PXE_PGP_MATH_FAILED, "Math operation failed"},
67  {PXE_PGP_SHORT_ELGAMAL_KEY, "Elgamal keys must be at least 1024 bits long"},
68  {PXE_PGP_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
69  {PXE_PGP_WRONG_KEY, "Wrong key"},
71  "Several keys given - pgcrypto does not handle keyring"},
72  {PXE_PGP_EXPECT_PUBLIC_KEY, "Refusing to encrypt with secret key"},
73  {PXE_PGP_EXPECT_SECRET_KEY, "Cannot decrypt with public key"},
74  {PXE_PGP_NOT_V4_KEYPKT, "Only V4 key packets are supported"},
75  {PXE_PGP_KEYPKT_CORRUPT, "Corrupt key packet"},
76  {PXE_PGP_NO_USABLE_KEY, "No encryption key found"},
77  {PXE_PGP_NEED_SECRET_PSW, "Need password for secret key"},
78  {PXE_PGP_BAD_S2K_MODE, "Bad S2K mode"},
79  {PXE_PGP_UNSUPPORTED_PUBALGO, "Unsupported public key algorithm"},
80  {PXE_PGP_MULTIPLE_SUBKEYS, "Several subkeys not supported"},
81 
82  {0, NULL},
83 };
84 
85 /*
86  * Call ereport(ERROR, ...), with an error code and message corresponding to
87  * the PXE_* error code given as argument.
88  *
89  * This is similar to px_strerror(err), but for some errors, we fill in the
90  * error code and detail fields more appropriately.
91  */
92 void
94 {
95  if (err == PXE_NO_RANDOM)
96  {
97  ereport(ERROR,
98  (errcode(ERRCODE_INTERNAL_ERROR),
99  errmsg("could not generate a random number")));
100  }
101  else
102  {
103  /* For other errors, use the message from the above list. */
104  ereport(ERROR,
105  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
106  errmsg("%s", px_strerror(err))));
107  }
108 }
109 
110 const char *
112 {
113  const struct error_desc *e;
114 
115  for (e = px_err_list; e->desc; e++)
116  if (e->err == err)
117  return e->desc;
118  return "Bad error code";
119 }
120 
121 /* memset that must not be optimized away */
122 void
123 px_memset(void *ptr, int c, size_t len)
124 {
125  memset(ptr, c, len);
126 }
127 
128 const char *
129 px_resolve_alias(const PX_Alias *list, const char *name)
130 {
131  while (list->name)
132  {
133  if (pg_strcasecmp(list->alias, name) == 0)
134  return list->name;
135  list++;
136  }
137  return name;
138 }
139 
140 static void (*debug_handler) (const char *) = NULL;
141 
142 void
143 px_set_debug_handler(void (*handler) (const char *))
144 {
145  debug_handler = handler;
146 }
147 
148 void
149 px_debug(const char *fmt,...)
150 {
151  va_list ap;
152 
153  va_start(ap, fmt);
154  if (debug_handler)
155  {
156  char buf[512];
157 
158  vsnprintf(buf, sizeof(buf), fmt, ap);
160  }
161  va_end(ap);
162 }
163 
164 /*
165  * combo - cipher + padding (+ checksum)
166  */
167 
168 static unsigned
169 combo_encrypt_len(PX_Combo *cx, unsigned dlen)
170 {
171  return dlen + 512;
172 }
173 
174 static unsigned
175 combo_decrypt_len(PX_Combo *cx, unsigned dlen)
176 {
177  return dlen;
178 }
179 
180 static int
181 combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
182  const uint8 *iv, unsigned ivlen)
183 {
184  int err;
185  unsigned ks,
186  ivs;
187  PX_Cipher *c = cx->cipher;
188  uint8 *ivbuf = NULL;
189  uint8 *keybuf;
190 
191  ks = px_cipher_key_size(c);
192 
193  ivs = px_cipher_iv_size(c);
194  if (ivs > 0)
195  {
196  ivbuf = palloc0(ivs);
197  if (ivlen > ivs)
198  memcpy(ivbuf, iv, ivs);
199  else if (ivlen > 0)
200  memcpy(ivbuf, iv, ivlen);
201  }
202 
203  if (klen > ks)
204  klen = ks;
205  keybuf = palloc0(ks);
206  memset(keybuf, 0, ks);
207  memcpy(keybuf, key, klen);
208 
209  err = px_cipher_init(c, keybuf, klen, ivbuf);
210 
211  if (ivbuf)
212  pfree(ivbuf);
213  pfree(keybuf);
214 
215  return err;
216 }
217 
218 static int
219 combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
220  uint8 *res, unsigned *rlen)
221 {
222  return px_cipher_encrypt(cx->cipher, cx->padding, data, dlen, res, rlen);
223 }
224 
225 static int
226 combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
227  uint8 *res, unsigned *rlen)
228 {
229  return px_cipher_decrypt(cx->cipher, cx->padding, data, dlen, res, rlen);
230 }
231 
232 static void
234 {
235  if (cx->cipher)
236  px_cipher_free(cx->cipher);
237  px_memset(cx, 0, sizeof(*cx));
238  pfree(cx);
239 }
240 
241 /* PARSER */
242 
243 static int
244 parse_cipher_name(char *full, char **cipher, char **pad)
245 {
246  char *p,
247  *p2,
248  *q;
249 
250  *cipher = full;
251  *pad = NULL;
252 
253  p = strchr(full, '/');
254  if (p != NULL)
255  *p++ = 0;
256  while (p != NULL)
257  {
258  if ((q = strchr(p, '/')) != NULL)
259  *q++ = 0;
260 
261  if (!*p)
262  {
263  p = q;
264  continue;
265  }
266  p2 = strchr(p, ':');
267  if (p2 != NULL)
268  {
269  *p2++ = 0;
270  if (strcmp(p, "pad") == 0)
271  *pad = p2;
272  else
273  return PXE_BAD_OPTION;
274  }
275  else
276  return PXE_BAD_FORMAT;
277 
278  p = q;
279  }
280  return 0;
281 }
282 
283 /* provider */
284 
285 int
287 {
288  int err;
289  char *buf,
290  *s_cipher,
291  *s_pad;
292 
293  PX_Combo *cx;
294 
295  cx = palloc0(sizeof(*cx));
296  buf = pstrdup(name);
297 
298  err = parse_cipher_name(buf, &s_cipher, &s_pad);
299  if (err)
300  {
301  pfree(buf);
302  pfree(cx);
303  return err;
304  }
305 
306  err = px_find_cipher(s_cipher, &cx->cipher);
307  if (err)
308  goto err1;
309 
310  if (s_pad != NULL)
311  {
312  if (strcmp(s_pad, "pkcs") == 0)
313  cx->padding = 1;
314  else if (strcmp(s_pad, "none") == 0)
315  cx->padding = 0;
316  else
317  goto err1;
318  }
319  else
320  cx->padding = 1;
321 
322  cx->init = combo_init;
323  cx->encrypt = combo_encrypt;
324  cx->decrypt = combo_decrypt;
325  cx->encrypt_len = combo_encrypt_len;
326  cx->decrypt_len = combo_decrypt_len;
327  cx->free = combo_free;
328 
329  pfree(buf);
330 
331  *res = cx;
332 
333  return 0;
334 
335 err1:
336  if (cx->cipher)
337  px_cipher_free(cx->cipher);
338  pfree(cx);
339  pfree(buf);
340  return PXE_NO_CIPHER;
341 }
unsigned char uint8
Definition: c.h:439
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
const char * name
Definition: encode.c:561
int cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
va_end(args)
static void const char * fmt
va_start(args, fmt)
char * pstrdup(const char *in)
Definition: mcxt.c:1305
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc0(Size size)
Definition: mcxt.c:1099
int px_find_cipher(const char *name, PX_Cipher **res)
Definition: openssl.c:771
const void size_t len
const void * data
static char * buf
Definition: pg_test_fsync.c:67
#define vsnprintf
Definition: port.h:224
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
char * c
e
Definition: preproc-init.c:82
void px_THROW_ERROR(int err)
Definition: px.c:93
static void combo_free(PX_Combo *cx)
Definition: px.c:233
static int combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.c:219
static int parse_cipher_name(char *full, char **cipher, char **pad)
Definition: px.c:244
static const struct error_desc px_err_list[]
Definition: px.c:42
const char * px_resolve_alias(const PX_Alias *list, const char *name)
Definition: px.c:129
static int combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
Definition: px.c:226
static unsigned combo_decrypt_len(PX_Combo *cx, unsigned dlen)
Definition: px.c:175
const char * px_strerror(int err)
Definition: px.c:111
void px_debug(const char *fmt,...)
Definition: px.c:149
static unsigned combo_encrypt_len(PX_Combo *cx, unsigned dlen)
Definition: px.c:169
static void(* debug_handler)(const char *)
Definition: px.c:140
void px_set_debug_handler(void(*handler)(const char *))
Definition: px.c:143
static int combo_init(PX_Combo *cx, const uint8 *key, unsigned klen, const uint8 *iv, unsigned ivlen)
Definition: px.c:181
int px_find_combo(const char *name, PX_Combo **res)
Definition: px.c:286
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:123
#define px_cipher_decrypt(c, padding, data, dlen, res, rlen)
Definition: px.h:213
#define PXE_PGP_EXPECT_PUBLIC_KEY
Definition: px.h:82
#define px_cipher_free(c)
Definition: px.h:215
#define PXE_PGP_UNSUPPORTED_COMPR
Definition: px.h:69
#define PXE_PGP_BAD_S2K_MODE
Definition: px.h:88
#define PXE_OK
Definition: px.h:46
#define PXE_DECRYPT_FAILED
Definition: px.h:64
#define px_cipher_iv_size(c)
Definition: px.h:209
#define PXE_ARGUMENT_ERROR
Definition: px.h:59
#define PXE_BAD_SALT_ROUNDS
Definition: px.h:61
#define PXE_CIPHER_INIT
Definition: px.h:54
#define PXE_PGP_UNEXPECTED_PKT
Definition: px.h:74
#define PXE_PGP_MULTIPLE_KEYS
Definition: px.h:81
#define PXE_ENCRYPT_FAILED
Definition: px.h:65
#define PXE_PGP_UNSUPPORTED_PUBALGO
Definition: px.h:89
#define PXE_PGP_NO_USABLE_KEY
Definition: px.h:86
#define PXE_NO_HASH
Definition: px.h:48
#define PXE_NO_CIPHER
Definition: px.h:49
#define PXE_PGP_EXPECT_SECRET_KEY
Definition: px.h:83
#define PXE_HASH_UNUSABLE_FOR_HMAC
Definition: px.h:55
#define PXE_BAD_FORMAT
Definition: px.h:52
#define PXE_BUG
Definition: px.h:58
#define PXE_PGP_NEED_SECRET_PSW
Definition: px.h:87
#define PXE_PGP_MULTIPLE_SUBKEYS
Definition: px.h:90
#define PXE_PGP_COMPRESSION_ERROR
Definition: px.h:72
#define PXE_PGP_WRONG_KEY
Definition: px.h:80
#define PXE_PGP_CORRUPT_DATA
Definition: px.h:67
#define PXE_NO_RANDOM
Definition: px.h:63
#define PXE_UNKNOWN_SALT_ALGO
Definition: px.h:60
#define PXE_PGP_MATH_FAILED
Definition: px.h:76
#define PXE_PGP_UNSUPPORTED_CIPHER
Definition: px.h:70
#define px_cipher_encrypt(c, padding, data, dlen, res, rlen)
Definition: px.h:211
#define PXE_PGP_NOT_TEXT
Definition: px.h:73
#define PXE_PGP_UNKNOWN_PUBALGO
Definition: px.h:79
#define PXE_PGP_SHORT_ELGAMAL_KEY
Definition: px.h:77
#define PXE_PGP_CORRUPT_ARMOR
Definition: px.h:68
#define PXE_PGP_KEYPKT_CORRUPT
Definition: px.h:85
#define px_cipher_init(c, k, klen, iv)
Definition: px.h:210
#define PXE_BAD_OPTION
Definition: px.h:51
#define PXE_PGP_UNSUPPORTED_HASH
Definition: px.h:71
#define PXE_KEY_TOO_BIG
Definition: px.h:53
#define px_cipher_key_size(c)
Definition: px.h:207
#define PXE_PGP_NOT_V4_KEYPKT
Definition: px.h:84
Definition: px.c:37
const char * desc
Definition: px.c:39
int err
Definition: px.c:38
Definition: px.h:116
Definition: px.h:141
Definition: px.h:156