PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pgp-s2k.c
Go to the documentation of this file.
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
40 calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
41  unsigned key_len)
42 {
43  unsigned md_rlen;
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
84 calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
85 {
86  unsigned md_rlen;
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
128 calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
129  unsigned key_len)
130 {
131  unsigned md_rlen;
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
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
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
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
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)
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 }
uint8 mode
Definition: pgp.h:124
static int calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
Definition: pgp-s2k.c:40
int pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
Definition: mbuf.c:317
#define PXE_PGP_UNSUPPORTED_CIPHER
Definition: px.h:84
#define px_md_update(md, data, dlen)
Definition: px.h:208
unsigned char uint8
Definition: c.h:266
static int calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
Definition: pgp-s2k.c:84
#define PXE_NO_RANDOM
Definition: px.h:78
#define px_md_finish(md, buf)
Definition: px.h:209
#define PXE_PGP_BAD_S2K_MODE
Definition: px.h:102
#define px_md_reset(md)
Definition: px.h:207
int pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count)
Definition: pgp-s2k.c:225
uint8 digest_algo
Definition: pgp.h:125
#define px_md_result_size(md)
Definition: px.h:205
Definition: px.h:113
#define GETBYTE(x, i)
Definition: hstore_gist.c:32
char * c
bool pg_backend_random(char *dst, int len)
static char * buf
Definition: pg_test_fsync.c:66
uint8 salt[8]
Definition: pgp.h:126
uint8 key[PGP_MAX_KEY]
Definition: pgp.h:129
Definition: pgp.h:122
int pgp_get_cipher_key_size(int code)
Definition: pgp.c:148
static int calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
Definition: pgp-s2k.c:128
int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
Definition: pgp-s2k.c:281
#define px_md_free(md)
Definition: px.h:210
#define PGP_S2K_SALT
Definition: pgp.h:115
int pgp_load_digest(int code, PX_MD **res)
Definition: pgp.c:184
static uint8 decide_s2k_iter(unsigned rand_byte, int count)
Definition: pgp-s2k.c:211
uint8 iter
Definition: pgp.h:127
int pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
Definition: pgp-s2k.c:255
uint8 key_len
Definition: pgp.h:130
#define s2k_decode_count(cval)
Definition: pgp.h:176
#define PGP_MAX_DIGEST
Definition: pgp.h:114
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:134