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