Age Owner TLA 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_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
69 : {PXE_PGP_WRONG_KEY, "Wrong key"},
70 : {PXE_PGP_MULTIPLE_KEYS,
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
2316 heikki.linnakangas 93 CBC 21 : px_THROW_ERROR(int err)
94 : {
95 21 : if (err == PXE_NO_RANDOM)
96 : {
2316 heikki.linnakangas 97 UBC 0 : 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. */
2316 heikki.linnakangas 104 CBC 21 : ereport(ERROR,
105 : (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
106 : errmsg("%s", px_strerror(err))));
107 : }
108 : }
109 :
110 : const char *
6385 bruce 111 66 : px_strerror(int err)
112 : {
113 : const struct error_desc *e;
114 :
6593 neilc 115 792 : for (e = px_err_list; e->desc; e++)
116 792 : if (e->err == err)
117 66 : return e->desc;
6593 neilc 118 UBC 0 : return "Bad error code";
119 : }
120 :
121 : /* memset that must not be optimized away */
122 : void
3279 bruce 123 CBC 2960 : px_memset(void *ptr, int c, size_t len)
124 : {
125 2960 : memset(ptr, c, len);
126 2960 : }
127 :
128 : const char *
5050 129 191 : px_resolve_alias(const PX_Alias *list, const char *name)
130 : {
7836 131 2516 : while (list->name)
132 : {
6911 tgl 133 2371 : if (pg_strcasecmp(list->alias, name) == 0)
7901 bruce 134 46 : return list->name;
135 2325 : list++;
136 : }
137 145 : return name;
138 : }
139 :
140 : static void (*debug_handler) (const char *) = NULL;
141 :
142 : void
6385 143 117 : px_set_debug_handler(void (*handler) (const char *))
144 : {
6482 145 117 : debug_handler = handler;
146 117 : }
147 :
148 : void
6385 149 18 : px_debug(const char *fmt,...)
150 : {
151 : va_list ap;
152 :
6482 153 18 : va_start(ap, fmt);
6385 154 18 : if (debug_handler)
155 : {
156 : char buf[512];
157 :
6482 158 8 : vsnprintf(buf, sizeof(buf), fmt, ap);
159 8 : debug_handler(buf);
160 : }
161 18 : va_end(ap);
162 18 : }
163 :
164 : /*
165 : * combo - cipher + padding (+ checksum)
166 : */
167 :
168 : static unsigned
5050 169 59 : combo_encrypt_len(PX_Combo *cx, unsigned dlen)
170 : {
7901 171 59 : return dlen + 512;
172 : }
173 :
174 : static unsigned
5050 175 11 : combo_decrypt_len(PX_Combo *cx, unsigned dlen)
176 : {
7901 177 11 : return dlen;
178 : }
179 :
180 : static int
5050 181 70 : 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;
7836 187 70 : PX_Cipher *c = cx->cipher;
188 70 : uint8 *ivbuf = NULL;
189 : uint8 *keybuf;
190 :
7901 191 70 : ks = px_cipher_key_size(c);
192 :
193 70 : ivs = px_cipher_iv_size(c);
7836 194 70 : if (ivs > 0)
195 : {
926 michael 196 70 : ivbuf = palloc0(ivs);
7901 bruce 197 70 : if (ivlen > ivs)
7901 bruce 198 UBC 0 : memcpy(ivbuf, iv, ivs);
402 tgl 199 CBC 70 : else if (ivlen > 0)
7901 bruce 200 11 : memcpy(ivbuf, iv, ivlen);
201 : }
202 :
7822 203 70 : if (klen > ks)
7822 bruce 204 UBC 0 : klen = ks;
926 michael 205 CBC 70 : keybuf = palloc0(ks);
7901 bruce 206 GIC 70 : memcpy(keybuf, key, klen);
7901 bruce 207 ECB :
7901 bruce 208 GIC 70 : err = px_cipher_init(c, keybuf, klen, ivbuf);
7901 bruce 209 ECB :
7901 bruce 210 CBC 70 : if (ivbuf)
926 michael 211 70 : pfree(ivbuf);
926 michael 212 GIC 70 : pfree(keybuf);
7901 bruce 213 ECB :
7901 bruce 214 GIC 70 : return err;
215 : }
216 :
7901 bruce 217 ECB : static int
5050 bruce 218 GIC 55 : combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
219 : uint8 *res, unsigned *rlen)
7901 bruce 220 ECB : {
383 peter 221 GIC 55 : return px_cipher_encrypt(cx->cipher, cx->padding, data, dlen, res, rlen);
222 : }
223 :
7901 bruce 224 ECB : static int
5050 bruce 225 GIC 11 : combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
226 : uint8 *res, unsigned *rlen)
7901 bruce 227 ECB : {
383 peter 228 GIC 11 : return px_cipher_decrypt(cx->cipher, cx->padding, data, dlen, res, rlen);
229 : }
230 :
7901 bruce 231 ECB : static void
5050 bruce 232 GIC 70 : combo_free(PX_Combo *cx)
7901 bruce 233 ECB : {
7901 bruce 234 CBC 70 : if (cx->cipher)
235 70 : px_cipher_free(cx->cipher);
3279 236 70 : px_memset(cx, 0, sizeof(*cx));
926 michael 237 70 : pfree(cx);
7901 bruce 238 GIC 70 : }
239 :
240 : /* PARSER */
241 :
7885 bruce 242 ECB : static int
7901 bruce 243 GIC 71 : parse_cipher_name(char *full, char **cipher, char **pad)
244 : {
245 : char *p,
246 : *p2,
247 : *q;
7836 bruce 248 ECB :
7901 bruce 249 CBC 71 : *cipher = full;
7901 bruce 250 GIC 71 : *pad = NULL;
7836 bruce 251 ECB :
7901 bruce 252 CBC 71 : p = strchr(full, '/');
253 71 : if (p != NULL)
254 19 : *p++ = 0;
7836 bruce 255 GIC 90 : while (p != NULL)
7836 bruce 256 ECB : {
7901 bruce 257 GBC 19 : if ((q = strchr(p, '/')) != NULL)
7901 bruce 258 UIC 0 : *q++ = 0;
7836 bruce 259 ECB :
7836 bruce 260 GIC 19 : if (!*p)
7836 bruce 261 EUB : {
7901 bruce 262 UBC 0 : p = q;
7901 bruce 263 UIC 0 : continue;
7901 bruce 264 ECB : }
7901 bruce 265 CBC 19 : p2 = strchr(p, ':');
7836 bruce 266 GIC 19 : if (p2 != NULL)
7836 bruce 267 ECB : {
7901 bruce 268 CBC 19 : *p2++ = 0;
4121 peter_e 269 19 : if (strcmp(p, "pad") == 0)
7901 bruce 270 GIC 19 : *pad = p2;
7885 bruce 271 EUB : else
6593 neilc 272 UIC 0 : return PXE_BAD_OPTION;
273 : }
7836 bruce 274 EUB : else
6593 neilc 275 UIC 0 : return PXE_BAD_FORMAT;
7836 bruce 276 ECB :
7901 bruce 277 GIC 19 : p = q;
7901 bruce 278 ECB : }
7885 bruce 279 GIC 71 : return 0;
280 : }
281 :
282 : /* provider */
283 :
7901 bruce 284 ECB : int
5050 bruce 285 GIC 71 : px_find_combo(const char *name, PX_Combo **res)
286 : {
287 : int err;
288 : char *buf,
289 : *s_cipher,
290 : *s_pad;
291 :
292 : PX_Combo *cx;
7901 bruce 293 ECB :
926 michael 294 CBC 71 : cx = palloc0(sizeof(*cx));
926 michael 295 GIC 71 : buf = pstrdup(name);
7901 bruce 296 ECB :
7885 bruce 297 CBC 71 : err = parse_cipher_name(buf, &s_cipher, &s_pad);
7836 bruce 298 GIC 71 : if (err)
7836 bruce 299 EUB : {
926 michael 300 UBC 0 : pfree(buf);
301 0 : pfree(cx);
7885 bruce 302 UIC 0 : return err;
303 : }
7901 bruce 304 ECB :
7901 bruce 305 CBC 71 : err = px_find_cipher(s_cipher, &cx->cipher);
306 71 : if (err)
7901 bruce 307 GIC 1 : goto err1;
7836 bruce 308 ECB :
7836 bruce 309 GIC 70 : if (s_pad != NULL)
7836 bruce 310 ECB : {
4121 peter_e 311 GBC 19 : if (strcmp(s_pad, "pkcs") == 0)
7901 bruce 312 LBC 0 : cx->padding = 1;
4121 peter_e 313 CBC 19 : else if (strcmp(s_pad, "none") == 0)
7901 bruce 314 GIC 19 : cx->padding = 0;
7901 bruce 315 EUB : else
7901 bruce 316 UIC 0 : goto err1;
317 : }
7836 bruce 318 ECB : else
7901 bruce 319 GIC 51 : cx->padding = 1;
7901 bruce 320 ECB :
7901 bruce 321 CBC 70 : cx->init = combo_init;
322 70 : cx->encrypt = combo_encrypt;
323 70 : cx->decrypt = combo_decrypt;
324 70 : cx->encrypt_len = combo_encrypt_len;
325 70 : cx->decrypt_len = combo_decrypt_len;
7901 bruce 326 GIC 70 : cx->free = combo_free;
7901 bruce 327 ECB :
926 michael 328 GIC 70 : pfree(buf);
7901 bruce 329 ECB :
7901 bruce 330 GIC 70 : *res = cx;
7901 bruce 331 ECB :
7901 bruce 332 GIC 70 : return 0;
7836 bruce 333 ECB :
7901 bruce 334 CBC 1 : err1:
7901 bruce 335 GBC 1 : if (cx->cipher)
7901 bruce 336 LBC 0 : px_cipher_free(cx->cipher);
926 michael 337 CBC 1 : pfree(cx);
338 1 : pfree(buf);
6593 neilc 339 GIC 1 : return PXE_NO_CIPHER;
340 : }
|