Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * pgp.c
3 : : * Various utility stuff.
4 : : *
5 : : * Copyright (c) 2005 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/pgp.c
30 : : */
31 : :
32 : : #include "postgres.h"
33 : :
34 : : #include "pgp.h"
35 : : #include "px.h"
36 : :
37 : : /*
38 : : * Defaults.
39 : : */
40 : : static int def_cipher_algo = PGP_SYM_AES_128;
41 : : static int def_s2k_cipher_algo = -1;
42 : : static int def_s2k_mode = PGP_S2K_ISALTED;
43 : : static int def_s2k_count = -1;
44 : : static int def_s2k_digest_algo = PGP_DIGEST_SHA1;
45 : : static int def_compress_algo = PGP_COMPR_NONE;
46 : : static int def_compress_level = 6;
47 : : static int def_disable_mdc = 0;
48 : : static int def_use_sess_key = 0;
49 : : static int def_text_mode = 0;
50 : : static int def_unicode_mode = 0;
51 : : static int def_convert_crlf = 0;
52 : :
53 : : struct digest_info
54 : : {
55 : : const char *name;
56 : : int code;
57 : : };
58 : :
59 : : struct cipher_info
60 : : {
61 : : const char *name;
62 : : int code;
63 : : const char *int_name;
64 : : int key_len;
65 : : int block_len;
66 : : };
67 : :
68 : : static const struct digest_info digest_list[] = {
69 : : {"md5", PGP_DIGEST_MD5},
70 : : {"sha1", PGP_DIGEST_SHA1},
71 : : {"sha-1", PGP_DIGEST_SHA1},
72 : : {"ripemd160", PGP_DIGEST_RIPEMD160},
73 : : {"sha256", PGP_DIGEST_SHA256},
74 : : {"sha384", PGP_DIGEST_SHA384},
75 : : {"sha512", PGP_DIGEST_SHA512},
76 : : {NULL, 0}
77 : : };
78 : :
79 : : static const struct cipher_info cipher_list[] = {
80 : : {"3des", PGP_SYM_DES3, "3des-ecb", 192 / 8, 64 / 8},
81 : : {"cast5", PGP_SYM_CAST5, "cast5-ecb", 128 / 8, 64 / 8},
82 : : {"bf", PGP_SYM_BLOWFISH, "bf-ecb", 128 / 8, 64 / 8},
83 : : {"blowfish", PGP_SYM_BLOWFISH, "bf-ecb", 128 / 8, 64 / 8},
84 : : {"aes", PGP_SYM_AES_128, "aes-ecb", 128 / 8, 128 / 8},
85 : : {"aes128", PGP_SYM_AES_128, "aes-ecb", 128 / 8, 128 / 8},
86 : : {"aes192", PGP_SYM_AES_192, "aes-ecb", 192 / 8, 128 / 8},
87 : : {"aes256", PGP_SYM_AES_256, "aes-ecb", 256 / 8, 128 / 8},
88 : : {"twofish", PGP_SYM_TWOFISH, "twofish-ecb", 256 / 8, 128 / 8},
89 : : {NULL, 0, NULL}
90 : : };
91 : :
92 : : static const struct cipher_info *
6853 bruce@momjian.us 93 :CBC 339 : get_cipher_info(int code)
94 : : {
95 : : const struct cipher_info *i;
96 : :
97 [ + - ]: 1808 : for (i = cipher_list; i->name; i++)
98 [ + + ]: 1808 : if (i->code == code)
99 : 339 : return i;
6853 bruce@momjian.us 100 :UBC 0 : return NULL;
101 : : }
102 : :
103 : : int
6853 bruce@momjian.us 104 :CBC 6 : pgp_get_digest_code(const char *name)
105 : : {
106 : : const struct digest_info *i;
107 : :
108 [ + - ]: 9 : for (i = digest_list; i->name; i++)
109 [ + + ]: 9 : if (pg_strcasecmp(i->name, name) == 0)
110 : 6 : return i->code;
6853 bruce@momjian.us 111 :UBC 0 : return PXE_PGP_UNSUPPORTED_HASH;
112 : : }
113 : :
114 : : int
6853 bruce@momjian.us 115 :CBC 14 : pgp_get_cipher_code(const char *name)
116 : : {
117 : : const struct cipher_info *i;
118 : :
119 [ + - ]: 76 : for (i = cipher_list; i->name; i++)
120 [ + + ]: 76 : if (pg_strcasecmp(i->name, name) == 0)
121 : 14 : return i->code;
6853 bruce@momjian.us 122 :UBC 0 : return PXE_PGP_UNSUPPORTED_CIPHER;
123 : : }
124 : :
125 : : const char *
6853 bruce@momjian.us 126 :CBC 233 : pgp_get_digest_name(int code)
127 : : {
128 : : const struct digest_info *i;
129 : :
130 [ + - ]: 470 : for (i = digest_list; i->name; i++)
131 [ + + ]: 470 : if (i->code == code)
132 : 233 : return i->name;
6853 bruce@momjian.us 133 :UBC 0 : return NULL;
134 : : }
135 : :
136 : : int
6853 bruce@momjian.us 137 :CBC 107 : pgp_get_cipher_key_size(int code)
138 : : {
139 : 107 : const struct cipher_info *i = get_cipher_info(code);
140 : :
141 [ + - ]: 107 : if (i != NULL)
142 : 107 : return i->key_len;
6853 bruce@momjian.us 143 :UBC 0 : return 0;
144 : : }
145 : :
146 : : int
6853 bruce@momjian.us 147 :CBC 112 : pgp_get_cipher_block_size(int code)
148 : : {
149 : 112 : const struct cipher_info *i = get_cipher_info(code);
150 : :
151 [ + - ]: 112 : if (i != NULL)
152 : 112 : return i->block_len;
6853 bruce@momjian.us 153 :UBC 0 : return 0;
154 : : }
155 : :
156 : : int
5421 bruce@momjian.us 157 :CBC 120 : pgp_load_cipher(int code, PX_Cipher **res)
158 : : {
159 : : int err;
6853 160 : 120 : const struct cipher_info *i = get_cipher_info(code);
161 : :
162 [ - + ]: 120 : if (i == NULL)
6853 bruce@momjian.us 163 :UBC 0 : return PXE_PGP_CORRUPT_DATA;
164 : :
6853 bruce@momjian.us 165 :CBC 120 : err = px_find_cipher(i->int_name, res);
166 [ + - ]: 120 : if (err == 0)
167 : 120 : return 0;
168 : :
6853 bruce@momjian.us 169 :UBC 0 : return PXE_PGP_UNSUPPORTED_CIPHER;
170 : : }
171 : :
172 : : int
5421 bruce@momjian.us 173 :CBC 233 : pgp_load_digest(int code, PX_MD **res)
174 : : {
175 : : int err;
6853 176 : 233 : const char *name = pgp_get_digest_name(code);
177 : :
178 [ - + ]: 233 : if (name == NULL)
6853 bruce@momjian.us 179 :UBC 0 : return PXE_PGP_CORRUPT_DATA;
180 : :
6853 bruce@momjian.us 181 :CBC 233 : err = px_find_digest(name, res);
182 [ + - ]: 233 : if (err == 0)
183 : 233 : return 0;
184 : :
6853 bruce@momjian.us 185 :UBC 0 : return PXE_PGP_UNSUPPORTED_HASH;
186 : : }
187 : :
188 : : int
5421 bruce@momjian.us 189 :CBC 115 : pgp_init(PGP_Context **ctx_p)
190 : : {
191 : : PGP_Context *ctx;
192 : :
1297 michael@paquier.xyz 193 : 115 : ctx = palloc0(sizeof *ctx);
194 : :
6853 bruce@momjian.us 195 : 115 : ctx->cipher_algo = def_cipher_algo;
196 : 115 : ctx->s2k_cipher_algo = def_s2k_cipher_algo;
197 : 115 : ctx->s2k_mode = def_s2k_mode;
2958 alvherre@alvh.no-ip. 198 : 115 : ctx->s2k_count = def_s2k_count;
6853 bruce@momjian.us 199 : 115 : ctx->s2k_digest_algo = def_s2k_digest_algo;
200 : 115 : ctx->compress_algo = def_compress_algo;
201 : 115 : ctx->compress_level = def_compress_level;
202 : 115 : ctx->disable_mdc = def_disable_mdc;
203 : 115 : ctx->use_sess_key = def_use_sess_key;
204 : 115 : ctx->unicode_mode = def_unicode_mode;
205 : 115 : ctx->convert_crlf = def_convert_crlf;
206 : 115 : ctx->text_mode = def_text_mode;
207 : :
208 : 115 : *ctx_p = ctx;
209 : 115 : return 0;
210 : : }
211 : :
212 : : int
5421 213 : 115 : pgp_free(PGP_Context *ctx)
214 : : {
6853 215 [ + + ]: 115 : if (ctx->pub_key)
216 : 20 : pgp_key_free(ctx->pub_key);
3650 217 : 115 : px_memset(ctx, 0, sizeof *ctx);
1297 michael@paquier.xyz 218 : 115 : pfree(ctx);
6853 bruce@momjian.us 219 : 115 : return 0;
220 : : }
221 : :
222 : : int
5421 223 : 1 : pgp_disable_mdc(PGP_Context *ctx, int disable)
224 : : {
6853 225 : 1 : ctx->disable_mdc = disable ? 1 : 0;
226 : 1 : return 0;
227 : : }
228 : :
229 : : int
5421 230 : 5 : pgp_set_sess_key(PGP_Context *ctx, int use)
231 : : {
6853 232 : 5 : ctx->use_sess_key = use ? 1 : 0;
233 : 5 : return 0;
234 : : }
235 : :
236 : : int
5421 237 : 5 : pgp_set_convert_crlf(PGP_Context *ctx, int doit)
238 : : {
6853 239 : 5 : ctx->convert_crlf = doit ? 1 : 0;
240 : 5 : return 0;
241 : : }
242 : :
243 : : int
5421 244 : 3 : pgp_set_s2k_mode(PGP_Context *ctx, int mode)
245 : : {
6853 246 : 3 : int err = PXE_OK;
247 : :
248 [ + - ]: 3 : switch (mode)
249 : : {
250 : 3 : case PGP_S2K_SIMPLE:
251 : : case PGP_S2K_SALTED:
252 : : case PGP_S2K_ISALTED:
253 : 3 : ctx->s2k_mode = mode;
254 : 3 : break;
6853 bruce@momjian.us 255 :UBC 0 : default:
256 : 0 : err = PXE_ARGUMENT_ERROR;
257 : 0 : break;
258 : : }
6853 bruce@momjian.us 259 :CBC 3 : return err;
260 : : }
261 : :
262 : : int
2958 alvherre@alvh.no-ip. 263 : 2 : pgp_set_s2k_count(PGP_Context *ctx, int count)
264 : : {
265 [ + - + - : 2 : if (ctx->s2k_mode == PGP_S2K_ISALTED && count >= 1024 && count <= 65011712)
+ - ]
266 : : {
267 : 2 : ctx->s2k_count = count;
268 : 2 : return PXE_OK;
269 : : }
2958 alvherre@alvh.no-ip. 270 :UBC 0 : return PXE_ARGUMENT_ERROR;
271 : : }
272 : :
273 : : int
5421 bruce@momjian.us 274 :CBC 5 : pgp_set_compress_algo(PGP_Context *ctx, int algo)
275 : : {
6853 276 [ + - ]: 5 : switch (algo)
277 : : {
278 : 5 : case PGP_COMPR_NONE:
279 : : case PGP_COMPR_ZIP:
280 : : case PGP_COMPR_ZLIB:
281 : : case PGP_COMPR_BZIP2:
282 : 5 : ctx->compress_algo = algo;
283 : 5 : return 0;
284 : : }
6853 bruce@momjian.us 285 :UBC 0 : return PXE_ARGUMENT_ERROR;
286 : : }
287 : :
288 : : int
5421 bruce@momjian.us 289 :CBC 2 : pgp_set_compress_level(PGP_Context *ctx, int level)
290 : : {
6853 291 [ + - + - ]: 2 : if (level >= 0 && level <= 9)
292 : : {
293 : 2 : ctx->compress_level = level;
294 : 2 : return 0;
295 : : }
6853 bruce@momjian.us 296 :UBC 0 : return PXE_ARGUMENT_ERROR;
297 : : }
298 : :
299 : : int
5421 bruce@momjian.us 300 :CBC 115 : pgp_set_text_mode(PGP_Context *ctx, int mode)
301 : : {
6853 302 : 115 : ctx->text_mode = mode;
303 : 115 : return 0;
304 : : }
305 : :
306 : : int
5421 307 : 6 : pgp_set_cipher_algo(PGP_Context *ctx, const char *name)
308 : : {
6853 309 : 6 : int code = pgp_get_cipher_code(name);
310 : :
311 [ - + ]: 6 : if (code < 0)
6853 bruce@momjian.us 312 :UBC 0 : return code;
6853 bruce@momjian.us 313 :CBC 6 : ctx->cipher_algo = code;
314 : 6 : return 0;
315 : : }
316 : :
317 : : int
5421 bruce@momjian.us 318 :UBC 0 : pgp_set_s2k_cipher_algo(PGP_Context *ctx, const char *name)
319 : : {
6853 320 : 0 : int code = pgp_get_cipher_code(name);
321 : :
322 [ # # ]: 0 : if (code < 0)
323 : 0 : return code;
324 : 0 : ctx->s2k_cipher_algo = code;
325 : 0 : return 0;
326 : : }
327 : :
328 : : int
5421 bruce@momjian.us 329 :CBC 2 : pgp_set_s2k_digest_algo(PGP_Context *ctx, const char *name)
330 : : {
6853 331 : 2 : int code = pgp_get_digest_code(name);
332 : :
333 [ - + ]: 2 : if (code < 0)
6853 bruce@momjian.us 334 :UBC 0 : return code;
6853 bruce@momjian.us 335 :CBC 2 : ctx->s2k_digest_algo = code;
336 : 2 : return 0;
337 : : }
338 : :
339 : : int
5421 340 : 107 : pgp_get_unicode_mode(PGP_Context *ctx)
341 : : {
6853 342 : 107 : return ctx->unicode_mode;
343 : : }
344 : :
345 : : int
5421 bruce@momjian.us 346 :UBC 0 : pgp_set_unicode_mode(PGP_Context *ctx, int mode)
347 : : {
6853 348 : 0 : ctx->unicode_mode = mode ? 1 : 0;
349 : 0 : return 0;
350 : : }
351 : :
352 : : int
5421 bruce@momjian.us 353 :CBC 89 : pgp_set_symkey(PGP_Context *ctx, const uint8 *key, int len)
354 : : {
6853 355 [ + - - + ]: 89 : if (key == NULL || len < 1)
6853 bruce@momjian.us 356 :UBC 0 : return PXE_ARGUMENT_ERROR;
6853 bruce@momjian.us 357 :CBC 89 : ctx->sym_key = key;
358 : 89 : ctx->sym_key_len = len;
359 : 89 : return 0;
360 : : }
|