Start background writer during archive recovery. Background writer now performs
[PostgreSQL.git] / contrib / pgcrypto / px.c
blobc56a50d197e6e1c22a06f16080126bc293a8a610
1 /*
2 * px.c
3 * Various cryptographic stuff for PostgreSQL.
5 * Copyright (c) 2001 Marko Kreen
6 * All rights reserved.
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.
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.
29 * $PostgreSQL$
32 #include "postgres.h"
34 #include "px.h"
36 struct error_desc
38 int err;
39 const char *desc;
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 initalized ?"},
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_OSSL_RAND_ERROR, "OpenSSL PRNG error"},
55 {PXE_BUG, "pgcrypto bug"},
56 {PXE_ARGUMENT_ERROR, "Illegal argument to function"},
57 {PXE_UNKNOWN_SALT_ALGO, "Unknown salt algorithm"},
58 {PXE_BAD_SALT_ROUNDS, "Incorrect number of rounds"},
59 {PXE_MCRYPT_INTERNAL, "mcrypt internal error"},
60 {PXE_NO_RANDOM, "No strong random source"},
61 {PXE_DECRYPT_FAILED, "Decryption 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_NO_BIGNUM,
71 "public-key functions disabled - "
72 "pgcrypto needs OpenSSL for bignums"},
73 {PXE_PGP_MATH_FAILED, "Math operation failed"},
74 {PXE_PGP_SHORT_ELGAMAL_KEY, "Elgamal keys must be at least 1024 bits long"},
75 {PXE_PGP_RSA_UNSUPPORTED, "pgcrypto does not support RSA keys"},
76 {PXE_PGP_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
77 {PXE_PGP_WRONG_KEY, "Wrong key"},
78 {PXE_PGP_MULTIPLE_KEYS,
79 "Several keys given - pgcrypto does not handle keyring"},
80 {PXE_PGP_EXPECT_PUBLIC_KEY, "Refusing to encrypt with secret key"},
81 {PXE_PGP_EXPECT_SECRET_KEY, "Cannot decrypt with public key"},
82 {PXE_PGP_NOT_V4_KEYPKT, "Only V4 key packets are supported"},
83 {PXE_PGP_KEYPKT_CORRUPT, "Corrupt key packet"},
84 {PXE_PGP_NO_USABLE_KEY, "No encryption key found"},
85 {PXE_PGP_NEED_SECRET_PSW, "Need password for secret key"},
86 {PXE_PGP_BAD_S2K_MODE, "Bad S2K mode"},
87 {PXE_PGP_UNSUPPORTED_PUBALGO, "Unsupported public key algorithm"},
88 {PXE_PGP_MULTIPLE_SUBKEYS, "Several subkeys not supported"},
90 /* fake this as PXE_PGP_CORRUPT_DATA */
91 {PXE_MBUF_SHORT_READ, "Corrupt data"},
93 {0, NULL},
96 const char *
97 px_strerror(int err)
99 const struct error_desc *e;
101 for (e = px_err_list; e->desc; e++)
102 if (e->err == err)
103 return e->desc;
104 return "Bad error code";
108 const char *
109 px_resolve_alias(const PX_Alias * list, const char *name)
111 while (list->name)
113 if (pg_strcasecmp(list->alias, name) == 0)
114 return list->name;
115 list++;
117 return name;
120 static void (*debug_handler) (const char *) = NULL;
122 void
123 px_set_debug_handler(void (*handler) (const char *))
125 debug_handler = handler;
128 void
129 px_debug(const char *fmt,...)
131 va_list ap;
133 va_start(ap, fmt);
134 if (debug_handler)
136 char buf[512];
138 vsnprintf(buf, sizeof(buf), fmt, ap);
139 debug_handler(buf);
141 va_end(ap);
145 * combo - cipher + padding (+ checksum)
148 static unsigned
149 combo_encrypt_len(PX_Combo * cx, unsigned dlen)
151 return dlen + 512;
154 static unsigned
155 combo_decrypt_len(PX_Combo * cx, unsigned dlen)
157 return dlen;
160 static int
161 combo_init(PX_Combo * cx, const uint8 *key, unsigned klen,
162 const uint8 *iv, unsigned ivlen)
164 int err;
165 unsigned bs,
167 ivs;
168 PX_Cipher *c = cx->cipher;
169 uint8 *ivbuf = NULL;
170 uint8 *keybuf;
172 bs = px_cipher_block_size(c);
173 ks = px_cipher_key_size(c);
175 ivs = px_cipher_iv_size(c);
176 if (ivs > 0)
178 ivbuf = px_alloc(ivs);
179 memset(ivbuf, 0, ivs);
180 if (ivlen > ivs)
181 memcpy(ivbuf, iv, ivs);
182 else
183 memcpy(ivbuf, iv, ivlen);
186 if (klen > ks)
187 klen = ks;
188 keybuf = px_alloc(ks);
189 memset(keybuf, 0, ks);
190 memcpy(keybuf, key, klen);
192 err = px_cipher_init(c, keybuf, klen, ivbuf);
194 if (ivbuf)
195 px_free(ivbuf);
196 px_free(keybuf);
198 return err;
201 static int
202 combo_encrypt(PX_Combo * cx, const uint8 *data, unsigned dlen,
203 uint8 *res, unsigned *rlen)
205 int err = 0;
206 uint8 *bbuf;
207 unsigned bs,
208 maxlen,
209 bpos,
211 pad;
213 PX_Cipher *c = cx->cipher;
215 bbuf = NULL;
216 maxlen = *rlen;
217 bs = px_cipher_block_size(c);
219 /* encrypt */
220 if (bs > 1)
222 bbuf = px_alloc(bs * 4);
223 bpos = dlen % bs;
224 *rlen = dlen - bpos;
225 memcpy(bbuf, data + *rlen, bpos);
227 /* encrypt full-block data */
228 if (*rlen)
230 err = px_cipher_encrypt(c, data, *rlen, res);
231 if (err)
232 goto out;
235 /* bbuf has now bpos bytes of stuff */
236 if (cx->padding)
238 pad = bs - (bpos % bs);
239 for (i = 0; i < pad; i++)
240 bbuf[bpos++] = pad;
242 else if (bpos % bs)
244 /* ERROR? */
245 pad = bs - (bpos % bs);
246 for (i = 0; i < pad; i++)
247 bbuf[bpos++] = 0;
250 /* encrypt the rest - pad */
251 if (bpos)
253 err = px_cipher_encrypt(c, bbuf, bpos, res + *rlen);
254 *rlen += bpos;
257 else
259 /* stream cipher/mode - no pad needed */
260 err = px_cipher_encrypt(c, data, dlen, res);
261 if (err)
262 goto out;
263 *rlen = dlen;
265 out:
266 if (bbuf)
267 px_free(bbuf);
269 return err;
272 static int
273 combo_decrypt(PX_Combo * cx, const uint8 *data, unsigned dlen,
274 uint8 *res, unsigned *rlen)
276 unsigned bs,
278 pad;
279 unsigned pad_ok;
281 PX_Cipher *c = cx->cipher;
283 /* decide whether zero-length input is allowed */
284 if (dlen == 0)
286 /* with padding, empty ciphertext is not allowed */
287 if (cx->padding)
288 return PXE_DECRYPT_FAILED;
290 /* without padding, report empty result */
291 *rlen = 0;
292 return 0;
295 bs = px_cipher_block_size(c);
296 if (bs > 1 && (dlen % bs) != 0)
297 goto block_error;
299 /* decrypt */
300 *rlen = dlen;
301 px_cipher_decrypt(c, data, dlen, res);
303 /* unpad */
304 if (bs > 1 && cx->padding)
306 pad = res[*rlen - 1];
307 pad_ok = 0;
308 if (pad > 0 && pad <= bs && pad <= *rlen)
310 pad_ok = 1;
311 for (i = *rlen - pad; i < *rlen; i++)
312 if (res[i] != pad)
314 pad_ok = 0;
315 break;
319 if (pad_ok)
320 *rlen -= pad;
323 return 0;
325 block_error:
326 return PXE_NOTBLOCKSIZE;
329 static void
330 combo_free(PX_Combo * cx)
332 if (cx->cipher)
333 px_cipher_free(cx->cipher);
334 memset(cx, 0, sizeof(*cx));
335 px_free(cx);
338 /* PARSER */
340 static int
341 parse_cipher_name(char *full, char **cipher, char **pad)
343 char *p,
344 *p2,
347 *cipher = full;
348 *pad = NULL;
350 p = strchr(full, '/');
351 if (p != NULL)
352 *p++ = 0;
353 while (p != NULL)
355 if ((q = strchr(p, '/')) != NULL)
356 *q++ = 0;
358 if (!*p)
360 p = q;
361 continue;
363 p2 = strchr(p, ':');
364 if (p2 != NULL)
366 *p2++ = 0;
367 if (!strcmp(p, "pad"))
368 *pad = p2;
369 else
370 return PXE_BAD_OPTION;
372 else
373 return PXE_BAD_FORMAT;
375 p = q;
377 return 0;
380 /* provider */
383 px_find_combo(const char *name, PX_Combo ** res)
385 int err;
386 char *buf,
387 *s_cipher,
388 *s_pad;
390 PX_Combo *cx;
392 cx = px_alloc(sizeof(*cx));
393 memset(cx, 0, sizeof(*cx));
395 buf = px_alloc(strlen(name) + 1);
396 strcpy(buf, name);
398 err = parse_cipher_name(buf, &s_cipher, &s_pad);
399 if (err)
401 px_free(buf);
402 px_free(cx);
403 return err;
406 err = px_find_cipher(s_cipher, &cx->cipher);
407 if (err)
408 goto err1;
410 if (s_pad != NULL)
412 if (!strcmp(s_pad, "pkcs"))
413 cx->padding = 1;
414 else if (!strcmp(s_pad, "none"))
415 cx->padding = 0;
416 else
417 goto err1;
419 else
420 cx->padding = 1;
422 cx->init = combo_init;
423 cx->encrypt = combo_encrypt;
424 cx->decrypt = combo_decrypt;
425 cx->encrypt_len = combo_encrypt_len;
426 cx->decrypt_len = combo_decrypt_len;
427 cx->free = combo_free;
429 px_free(buf);
431 *res = cx;
433 return 0;
435 err1:
436 if (cx->cipher)
437 px_cipher_free(cx->cipher);
438 px_free(cx);
439 px_free(buf);
440 return PXE_NO_CIPHER;