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"},
73 {PXE_PGP_MULTIPLE_KEYS,
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
px_THROW_ERROR(int err)96 px_THROW_ERROR(int err)
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 *
px_strerror(int err)122 px_strerror(int err)
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
px_memset(void * ptr,int c,size_t len)134 px_memset(void *ptr, int c, size_t len)
135 {
136 memset(ptr, c, len);
137 }
138
139 const char *
px_resolve_alias(const PX_Alias * list,const char * name)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
px_set_debug_handler(void (* handler)(const char *))154 px_set_debug_handler(void (*handler) (const char *))
155 {
156 debug_handler = handler;
157 }
158
159 void
px_debug(const char * fmt,...)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
combo_encrypt_len(PX_Combo * cx,unsigned dlen)180 combo_encrypt_len(PX_Combo *cx, unsigned dlen)
181 {
182 return dlen + 512;
183 }
184
185 static unsigned
combo_decrypt_len(PX_Combo * cx,unsigned dlen)186 combo_decrypt_len(PX_Combo *cx, unsigned dlen)
187 {
188 return dlen;
189 }
190
191 static int
combo_init(PX_Combo * cx,const uint8 * key,unsigned klen,const uint8 * iv,unsigned ivlen)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
combo_encrypt(PX_Combo * cx,const uint8 * data,unsigned dlen,uint8 * res,unsigned * rlen)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
combo_decrypt(PX_Combo * cx,const uint8 * data,unsigned dlen,uint8 * res,unsigned * rlen)300 combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
301 uint8 *res, unsigned *rlen)
302 {
303 int err = 0;
304 unsigned bs,
305 i,
306 pad;
307 unsigned pad_ok;
308
309 PX_Cipher *c = cx->cipher;
310
311 /* decide whether zero-length input is allowed */
312 if (dlen == 0)
313 {
314 /* with padding, empty ciphertext is not allowed */
315 if (cx->padding)
316 return PXE_DECRYPT_FAILED;
317
318 /* without padding, report empty result */
319 *rlen = 0;
320 return 0;
321 }
322
323 bs = px_cipher_block_size(c);
324 if (bs > 1 && (dlen % bs) != 0)
325 goto block_error;
326
327 /* decrypt */
328 *rlen = dlen;
329 err = px_cipher_decrypt(c, data, dlen, res);
330 if (err)
331 return err;
332
333 /* unpad */
334 if (bs > 1 && cx->padding)
335 {
336 pad = res[*rlen - 1];
337 pad_ok = 0;
338 if (pad > 0 && pad <= bs && pad <= *rlen)
339 {
340 pad_ok = 1;
341 for (i = *rlen - pad; i < *rlen; i++)
342 if (res[i] != pad)
343 {
344 pad_ok = 0;
345 break;
346 }
347 }
348
349 if (pad_ok)
350 *rlen -= pad;
351 }
352
353 return 0;
354
355 block_error:
356 return PXE_NOTBLOCKSIZE;
357 }
358
359 static void
combo_free(PX_Combo * cx)360 combo_free(PX_Combo *cx)
361 {
362 if (cx->cipher)
363 px_cipher_free(cx->cipher);
364 px_memset(cx, 0, sizeof(*cx));
365 px_free(cx);
366 }
367
368 /* PARSER */
369
370 static int
parse_cipher_name(char * full,char ** cipher,char ** pad)371 parse_cipher_name(char *full, char **cipher, char **pad)
372 {
373 char *p,
374 *p2,
375 *q;
376
377 *cipher = full;
378 *pad = NULL;
379
380 p = strchr(full, '/');
381 if (p != NULL)
382 *p++ = 0;
383 while (p != NULL)
384 {
385 if ((q = strchr(p, '/')) != NULL)
386 *q++ = 0;
387
388 if (!*p)
389 {
390 p = q;
391 continue;
392 }
393 p2 = strchr(p, ':');
394 if (p2 != NULL)
395 {
396 *p2++ = 0;
397 if (strcmp(p, "pad") == 0)
398 *pad = p2;
399 else
400 return PXE_BAD_OPTION;
401 }
402 else
403 return PXE_BAD_FORMAT;
404
405 p = q;
406 }
407 return 0;
408 }
409
410 /* provider */
411
412 int
px_find_combo(const char * name,PX_Combo ** res)413 px_find_combo(const char *name, PX_Combo **res)
414 {
415 int err;
416 char *buf,
417 *s_cipher,
418 *s_pad;
419
420 PX_Combo *cx;
421
422 cx = px_alloc(sizeof(*cx));
423 memset(cx, 0, sizeof(*cx));
424
425 buf = px_alloc(strlen(name) + 1);
426 strcpy(buf, name);
427
428 err = parse_cipher_name(buf, &s_cipher, &s_pad);
429 if (err)
430 {
431 px_free(buf);
432 px_free(cx);
433 return err;
434 }
435
436 err = px_find_cipher(s_cipher, &cx->cipher);
437 if (err)
438 goto err1;
439
440 if (s_pad != NULL)
441 {
442 if (strcmp(s_pad, "pkcs") == 0)
443 cx->padding = 1;
444 else if (strcmp(s_pad, "none") == 0)
445 cx->padding = 0;
446 else
447 goto err1;
448 }
449 else
450 cx->padding = 1;
451
452 cx->init = combo_init;
453 cx->encrypt = combo_encrypt;
454 cx->decrypt = combo_decrypt;
455 cx->encrypt_len = combo_encrypt_len;
456 cx->decrypt_len = combo_decrypt_len;
457 cx->free = combo_free;
458
459 px_free(buf);
460
461 *res = cx;
462
463 return 0;
464
465 err1:
466 if (cx->cipher)
467 px_cipher_free(cx->cipher);
468 px_free(cx);
469 px_free(buf);
470 return PXE_NO_CIPHER;
471 }
472