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