Line data Source code
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_KEY_TOO_BIG, "Session key too big"},
69 : {PXE_PGP_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
70 : {PXE_PGP_WRONG_KEY, "Wrong key"},
71 : {PXE_PGP_MULTIPLE_KEYS,
72 : "Several keys given - pgcrypto does not handle keyring"},
73 : {PXE_PGP_EXPECT_PUBLIC_KEY, "Refusing to encrypt with secret key"},
74 : {PXE_PGP_EXPECT_SECRET_KEY, "Cannot decrypt with public key"},
75 : {PXE_PGP_NOT_V4_KEYPKT, "Only V4 key packets are supported"},
76 : {PXE_PGP_KEYPKT_CORRUPT, "Corrupt key packet"},
77 : {PXE_PGP_NO_USABLE_KEY, "No encryption key found"},
78 : {PXE_PGP_NEED_SECRET_PSW, "Need password for secret key"},
79 : {PXE_PGP_BAD_S2K_MODE, "Bad S2K mode"},
80 : {PXE_PGP_UNSUPPORTED_PUBALGO, "Unsupported public key algorithm"},
81 : {PXE_PGP_MULTIPLE_SUBKEYS, "Several subkeys not supported"},
82 :
83 : {0, NULL},
84 : };
85 :
86 : /*
87 : * Call ereport(ERROR, ...), with an error code and message corresponding to
88 : * the PXE_* error code given as argument.
89 : *
90 : * This is similar to px_strerror(err), but for some errors, we fill in the
91 : * error code and detail fields more appropriately.
92 : */
93 : void
94 22 : px_THROW_ERROR(int err)
95 : {
96 22 : if (err == PXE_NO_RANDOM)
97 : {
98 0 : ereport(ERROR,
99 : (errcode(ERRCODE_INTERNAL_ERROR),
100 : errmsg("could not generate a random number")));
101 : }
102 : else
103 : {
104 : /* For other errors, use the message from the above list. */
105 22 : ereport(ERROR,
106 : (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
107 : errmsg("%s", px_strerror(err))));
108 : }
109 : }
110 :
111 : const char *
112 71 : px_strerror(int err)
113 : {
114 : const struct error_desc *e;
115 :
116 873 : for (e = px_err_list; e->desc; e++)
117 873 : if (e->err == err)
118 71 : return e->desc;
119 0 : return "Bad error code";
120 : }
121 :
122 : /* memset that must not be optimized away */
123 : void
124 3073 : px_memset(void *ptr, int c, size_t len)
125 : {
126 3073 : memset(ptr, c, len);
127 3073 : }
128 :
129 : const char *
130 210 : px_resolve_alias(const PX_Alias *list, const char *name)
131 : {
132 2965 : while (list->name)
133 : {
134 2801 : if (pg_strcasecmp(list->alias, name) == 0)
135 46 : return list->name;
136 2755 : list++;
137 : }
138 164 : return name;
139 : }
140 :
141 : static void (*debug_handler) (const char *) = NULL;
142 :
143 : void
144 120 : px_set_debug_handler(void (*handler) (const char *))
145 : {
146 120 : debug_handler = handler;
147 120 : }
148 :
149 : void
150 19 : px_debug(const char *fmt,...)
151 : {
152 : va_list ap;
153 :
154 19 : va_start(ap, fmt);
155 19 : if (debug_handler)
156 : {
157 : char buf[512];
158 :
159 8 : vsnprintf(buf, sizeof(buf), fmt, ap);
160 8 : debug_handler(buf);
161 : }
162 19 : va_end(ap);
163 19 : }
164 :
165 : /*
166 : * combo - cipher + padding (+ checksum)
167 : */
168 :
169 : static unsigned
170 72 : combo_encrypt_len(PX_Combo *cx, unsigned dlen)
171 : {
172 72 : return dlen + 512;
173 : }
174 :
175 : static unsigned
176 16 : combo_decrypt_len(PX_Combo *cx, unsigned dlen)
177 : {
178 16 : return dlen;
179 : }
180 :
181 : static int
182 88 : combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
183 : const uint8 *iv, unsigned ivlen)
184 : {
185 : int err;
186 : unsigned ks,
187 : ivs;
188 88 : PX_Cipher *c = cx->cipher;
189 88 : uint8 *ivbuf = NULL;
190 : uint8 *keybuf;
191 :
192 88 : ks = px_cipher_key_size(c);
193 :
194 88 : ivs = px_cipher_iv_size(c);
195 88 : if (ivs > 0)
196 : {
197 88 : ivbuf = palloc0(ivs);
198 88 : if (ivlen > ivs)
199 0 : memcpy(ivbuf, iv, ivs);
200 88 : else if (ivlen > 0)
201 14 : memcpy(ivbuf, iv, ivlen);
202 : }
203 :
204 88 : if (klen > ks)
205 0 : klen = ks;
206 88 : keybuf = palloc0(ks);
207 88 : memcpy(keybuf, key, klen);
208 :
209 88 : err = px_cipher_init(c, keybuf, klen, ivbuf);
210 :
211 88 : if (ivbuf)
212 88 : pfree(ivbuf);
213 88 : pfree(keybuf);
214 :
215 88 : return err;
216 : }
217 :
218 : static int
219 68 : combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
220 : uint8 *res, unsigned *rlen)
221 : {
222 68 : return px_cipher_encrypt(cx->cipher, cx->padding, data, dlen, res, rlen);
223 : }
224 :
225 : static int
226 16 : combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
227 : uint8 *res, unsigned *rlen)
228 : {
229 16 : return px_cipher_decrypt(cx->cipher, cx->padding, data, dlen, res, rlen);
230 : }
231 :
232 : static void
233 88 : combo_free(PX_Combo *cx)
234 : {
235 88 : if (cx->cipher)
236 88 : px_cipher_free(cx->cipher);
237 88 : px_memset(cx, 0, sizeof(*cx));
238 88 : pfree(cx);
239 88 : }
240 :
241 : /* PARSER */
242 :
243 : static int
244 89 : parse_cipher_name(char *full, char **cipher, char **pad)
245 : {
246 : char *p,
247 : *p2,
248 : *q;
249 :
250 89 : *cipher = full;
251 89 : *pad = NULL;
252 :
253 89 : p = strchr(full, '/');
254 89 : if (p != NULL)
255 21 : *p++ = 0;
256 110 : while (p != NULL)
257 : {
258 21 : if ((q = strchr(p, '/')) != NULL)
259 0 : *q++ = 0;
260 :
261 21 : if (!*p)
262 : {
263 0 : p = q;
264 0 : continue;
265 : }
266 21 : p2 = strchr(p, ':');
267 21 : if (p2 != NULL)
268 : {
269 21 : *p2++ = 0;
270 21 : if (strcmp(p, "pad") == 0)
271 21 : *pad = p2;
272 : else
273 0 : return PXE_BAD_OPTION;
274 : }
275 : else
276 0 : return PXE_BAD_FORMAT;
277 :
278 21 : p = q;
279 : }
280 89 : return 0;
281 : }
282 :
283 : /* provider */
284 :
285 : int
286 89 : px_find_combo(const char *name, PX_Combo **res)
287 : {
288 : int err;
289 : char *buf,
290 : *s_cipher,
291 : *s_pad;
292 :
293 : PX_Combo *cx;
294 :
295 89 : cx = palloc0_object(PX_Combo);
296 89 : buf = pstrdup(name);
297 :
298 89 : err = parse_cipher_name(buf, &s_cipher, &s_pad);
299 89 : if (err)
300 : {
301 0 : pfree(buf);
302 0 : pfree(cx);
303 0 : return err;
304 : }
305 :
306 89 : err = px_find_cipher(s_cipher, &cx->cipher);
307 89 : if (err)
308 1 : goto err1;
309 :
310 88 : if (s_pad != NULL)
311 : {
312 21 : if (strcmp(s_pad, "pkcs") == 0)
313 0 : cx->padding = 1;
314 21 : else if (strcmp(s_pad, "none") == 0)
315 21 : cx->padding = 0;
316 : else
317 0 : goto err1;
318 : }
319 : else
320 67 : cx->padding = 1;
321 :
322 88 : cx->init = combo_init;
323 88 : cx->encrypt = combo_encrypt;
324 88 : cx->decrypt = combo_decrypt;
325 88 : cx->encrypt_len = combo_encrypt_len;
326 88 : cx->decrypt_len = combo_decrypt_len;
327 88 : cx->free = combo_free;
328 :
329 88 : pfree(buf);
330 :
331 88 : *res = cx;
332 :
333 88 : return 0;
334 :
335 1 : err1:
336 1 : if (cx->cipher)
337 0 : px_cipher_free(cx->cipher);
338 1 : pfree(cx);
339 1 : pfree(buf);
340 1 : return PXE_NO_CIPHER;
341 : }
|