~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to contrib/pgcrypto/pgp-s2k.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

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