1 /*
2  * pgp-s2k.c
3  *	  OpenPGP string2key functions.
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-s2k.c
30  */
31 
32 #include "postgres.h"
33 
34 #include "px.h"
35 #include "pgp.h"
36 
37 #include "utils/backend_random.h"
38 
39 static int
calc_s2k_simple(PGP_S2K * s2k,PX_MD * md,const uint8 * key,unsigned key_len)40 calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
41 				unsigned key_len)
42 {
43 	unsigned	md_rlen;
44 	uint8		buf[PGP_MAX_DIGEST];
45 	unsigned	preload;
46 	unsigned	remain;
47 	uint8	   *dst = s2k->key;
48 
49 	md_rlen = px_md_result_size(md);
50 
51 	remain = s2k->key_len;
52 	preload = 0;
53 	while (remain > 0)
54 	{
55 		px_md_reset(md);
56 
57 		if (preload)
58 		{
59 			memset(buf, 0, preload);
60 			px_md_update(md, buf, preload);
61 		}
62 		preload++;
63 
64 		px_md_update(md, key, key_len);
65 		px_md_finish(md, buf);
66 
67 		if (remain > md_rlen)
68 		{
69 			memcpy(dst, buf, md_rlen);
70 			dst += md_rlen;
71 			remain -= md_rlen;
72 		}
73 		else
74 		{
75 			memcpy(dst, buf, remain);
76 			remain = 0;
77 		}
78 	}
79 	px_memset(buf, 0, sizeof(buf));
80 	return 0;
81 }
82 
83 static int
calc_s2k_salted(PGP_S2K * s2k,PX_MD * md,const uint8 * key,unsigned key_len)84 calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
85 {
86 	unsigned	md_rlen;
87 	uint8		buf[PGP_MAX_DIGEST];
88 	unsigned	preload = 0;
89 	uint8	   *dst;
90 	unsigned	remain;
91 
92 	md_rlen = px_md_result_size(md);
93 
94 	dst = s2k->key;
95 	remain = s2k->key_len;
96 	while (remain > 0)
97 	{
98 		px_md_reset(md);
99 
100 		if (preload > 0)
101 		{
102 			memset(buf, 0, preload);
103 			px_md_update(md, buf, preload);
104 		}
105 		preload++;
106 
107 		px_md_update(md, s2k->salt, PGP_S2K_SALT);
108 		px_md_update(md, key, key_len);
109 		px_md_finish(md, buf);
110 
111 		if (remain > md_rlen)
112 		{
113 			memcpy(dst, buf, md_rlen);
114 			remain -= md_rlen;
115 			dst += md_rlen;
116 		}
117 		else
118 		{
119 			memcpy(dst, buf, remain);
120 			remain = 0;
121 		}
122 	}
123 	px_memset(buf, 0, sizeof(buf));
124 	return 0;
125 }
126 
127 static int
calc_s2k_iter_salted(PGP_S2K * s2k,PX_MD * md,const uint8 * key,unsigned key_len)128 calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
129 					 unsigned key_len)
130 {
131 	unsigned	md_rlen;
132 	uint8		buf[PGP_MAX_DIGEST];
133 	uint8	   *dst;
134 	unsigned	preload = 0;
135 	unsigned	remain,
136 				c,
137 				curcnt,
138 				count;
139 
140 	count = s2k_decode_count(s2k->iter);
141 
142 	md_rlen = px_md_result_size(md);
143 
144 	remain = s2k->key_len;
145 	dst = s2k->key;
146 	while (remain > 0)
147 	{
148 		px_md_reset(md);
149 
150 		if (preload)
151 		{
152 			memset(buf, 0, preload);
153 			px_md_update(md, buf, preload);
154 		}
155 		preload++;
156 
157 		px_md_update(md, s2k->salt, PGP_S2K_SALT);
158 		px_md_update(md, key, key_len);
159 		curcnt = PGP_S2K_SALT + key_len;
160 
161 		while (curcnt < count)
162 		{
163 			if (curcnt + PGP_S2K_SALT < count)
164 				c = PGP_S2K_SALT;
165 			else
166 				c = count - curcnt;
167 			px_md_update(md, s2k->salt, c);
168 			curcnt += c;
169 
170 			if (curcnt + key_len < count)
171 				c = key_len;
172 			else if (curcnt < count)
173 				c = count - curcnt;
174 			else
175 				break;
176 			px_md_update(md, key, c);
177 			curcnt += c;
178 		}
179 		px_md_finish(md, buf);
180 
181 		if (remain > md_rlen)
182 		{
183 			memcpy(dst, buf, md_rlen);
184 			remain -= md_rlen;
185 			dst += md_rlen;
186 		}
187 		else
188 		{
189 			memcpy(dst, buf, remain);
190 			remain = 0;
191 		}
192 	}
193 	px_memset(buf, 0, sizeof(buf));
194 	return 0;
195 }
196 
197 /*
198  * Decide PGP_S2K_ISALTED iteration count (in OpenPGP one-byte representation)
199  *
200  * Too small: weak
201  * Too big: slow
202  * gpg defaults to 96 => 65536 iters
203  *
204  * For our default (count=-1) we let it float a bit: 96 + 32 => between 65536
205  * and 262144 iterations.
206  *
207  * Otherwise, find the smallest number which provides at least the specified
208  * iteration count.
209  */
210 static uint8
decide_s2k_iter(unsigned rand_byte,int count)211 decide_s2k_iter(unsigned rand_byte, int count)
212 {
213 	int			iter;
214 
215 	if (count == -1)
216 		return 96 + (rand_byte & 0x1F);
217 	/* this is a bit brute-force, but should be quick enough */
218 	for (iter = 0; iter <= 255; iter++)
219 		if (s2k_decode_count(iter) >= count)
220 			return iter;
221 	return 255;
222 }
223 
224 int
pgp_s2k_fill(PGP_S2K * s2k,int mode,int digest_algo,int count)225 pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count)
226 {
227 	int			res = 0;
228 	uint8		tmp;
229 
230 	s2k->mode = mode;
231 	s2k->digest_algo = digest_algo;
232 
233 	switch (s2k->mode)
234 	{
235 		case PGP_S2K_SIMPLE:
236 			break;
237 		case PGP_S2K_SALTED:
238 			if (!pg_backend_random((char *) s2k->salt, PGP_S2K_SALT))
239 				return PXE_NO_RANDOM;
240 			break;
241 		case PGP_S2K_ISALTED:
242 			if (!pg_backend_random((char *) s2k->salt, PGP_S2K_SALT))
243 				return PXE_NO_RANDOM;
244 			if (!pg_backend_random((char *) &tmp, 1))
245 				return PXE_NO_RANDOM;
246 			s2k->iter = decide_s2k_iter(tmp, count);
247 			break;
248 		default:
249 			res = PXE_PGP_BAD_S2K_MODE;
250 	}
251 	return res;
252 }
253 
254 int
pgp_s2k_read(PullFilter * src,PGP_S2K * s2k)255 pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
256 {
257 	int			res = 0;
258 
259 	GETBYTE(src, s2k->mode);
260 	GETBYTE(src, s2k->digest_algo);
261 	switch (s2k->mode)
262 	{
263 		case 0:
264 			break;
265 		case 1:
266 			res = pullf_read_fixed(src, 8, s2k->salt);
267 			break;
268 		case 3:
269 			res = pullf_read_fixed(src, 8, s2k->salt);
270 			if (res < 0)
271 				break;
272 			GETBYTE(src, s2k->iter);
273 			break;
274 		default:
275 			res = PXE_PGP_BAD_S2K_MODE;
276 	}
277 	return res;
278 }
279 
280 int
pgp_s2k_process(PGP_S2K * s2k,int cipher,const uint8 * key,int key_len)281 pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
282 {
283 	int			res;
284 	PX_MD	   *md;
285 
286 	s2k->key_len = pgp_get_cipher_key_size(cipher);
287 	if (s2k->key_len <= 0)
288 		return PXE_PGP_UNSUPPORTED_CIPHER;
289 
290 	res = pgp_load_digest(s2k->digest_algo, &md);
291 	if (res < 0)
292 		return res;
293 
294 	switch (s2k->mode)
295 	{
296 		case 0:
297 			res = calc_s2k_simple(s2k, md, key, key_len);
298 			break;
299 		case 1:
300 			res = calc_s2k_salted(s2k, md, key, key_len);
301 			break;
302 		case 3:
303 			res = calc_s2k_iter_salted(s2k, md, key, key_len);
304 			break;
305 		default:
306 			res = PXE_PGP_BAD_S2K_MODE;
307 	}
308 	px_md_free(md);
309 	return res;
310 }
311