3 * Various cryptographic stuff for PostgreSQL.
5 * Copyright (c) 2001 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
29 * contrib/pgcrypto/px.c
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"},
86 * Call ereport(ERROR, ...), with an error code and message corresponding to
87 * the PXE_* error code given as argument.
89 * This is similar to px_strerror(err), but for some errors, we fill in the
90 * error code and detail fields more appropriately.
93 px_THROW_ERROR(int err
)
95 if (err
== PXE_NO_RANDOM
)
98 (errcode(ERRCODE_INTERNAL_ERROR
),
99 errmsg("could not generate a random number")));
103 /* For other errors, use the message from the above list. */
105 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION
),
106 errmsg("%s", px_strerror(err
))));
113 const struct error_desc
*e
;
115 for (e
= px_err_list
; e
->desc
; e
++)
118 return "Bad error code";
121 /* memset that must not be optimized away */
123 px_memset(void *ptr
, int c
, size_t len
)
129 px_resolve_alias(const PX_Alias
*list
, const char *name
)
133 if (pg_strcasecmp(list
->alias
, name
) == 0)
140 static void (*debug_handler
) (const char *) = NULL
;
143 px_set_debug_handler(void (*handler
) (const char *))
145 debug_handler
= handler
;
149 px_debug(const char *fmt
,...)
158 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
165 * combo - cipher + padding (+ checksum)
169 combo_encrypt_len(PX_Combo
*cx
, unsigned dlen
)
175 combo_decrypt_len(PX_Combo
*cx
, unsigned dlen
)
181 combo_init(PX_Combo
*cx
, const uint8
*key
, unsigned klen
,
182 const uint8
*iv
, unsigned ivlen
)
187 PX_Cipher
*c
= cx
->cipher
;
191 ks
= px_cipher_key_size(c
);
193 ivs
= px_cipher_iv_size(c
);
196 ivbuf
= palloc0(ivs
);
198 memcpy(ivbuf
, iv
, ivs
);
200 memcpy(ivbuf
, iv
, ivlen
);
205 keybuf
= palloc0(ks
);
206 memcpy(keybuf
, key
, klen
);
208 err
= px_cipher_init(c
, keybuf
, klen
, ivbuf
);
218 combo_encrypt(PX_Combo
*cx
, const uint8
*data
, unsigned dlen
,
219 uint8
*res
, unsigned *rlen
)
221 return px_cipher_encrypt(cx
->cipher
, cx
->padding
, data
, dlen
, res
, rlen
);
225 combo_decrypt(PX_Combo
*cx
, const uint8
*data
, unsigned dlen
,
226 uint8
*res
, unsigned *rlen
)
228 return px_cipher_decrypt(cx
->cipher
, cx
->padding
, data
, dlen
, res
, rlen
);
232 combo_free(PX_Combo
*cx
)
235 px_cipher_free(cx
->cipher
);
236 px_memset(cx
, 0, sizeof(*cx
));
243 parse_cipher_name(char *full
, char **cipher
, char **pad
)
252 p
= strchr(full
, '/');
257 if ((q
= strchr(p
, '/')) != NULL
)
269 if (strcmp(p
, "pad") == 0)
272 return PXE_BAD_OPTION
;
275 return PXE_BAD_FORMAT
;
285 px_find_combo(const char *name
, PX_Combo
**res
)
294 cx
= palloc0(sizeof(*cx
));
297 err
= parse_cipher_name(buf
, &s_cipher
, &s_pad
);
305 err
= px_find_cipher(s_cipher
, &cx
->cipher
);
311 if (strcmp(s_pad
, "pkcs") == 0)
313 else if (strcmp(s_pad
, "none") == 0)
321 cx
->init
= combo_init
;
322 cx
->encrypt
= combo_encrypt
;
323 cx
->decrypt
= combo_decrypt
;
324 cx
->encrypt_len
= combo_encrypt_len
;
325 cx
->decrypt_len
= combo_decrypt_len
;
326 cx
->free
= combo_free
;
336 px_cipher_free(cx
->cipher
);
339 return PXE_NO_CIPHER
;