Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 188f359

Browse files
committed
pgcrypto: support changing S2K iteration count
pgcrypto already supports key-stretching during symmetric encryption, including the salted-and-iterated method; but the number of iterations was not configurable. This commit implements a new s2k-count parameter to pgp_sym_encrypt() which permits selecting a larger number of iterations. Author: Jeff Janes
1 parent b6fb647 commit 188f359

File tree

9 files changed

+98
-16
lines changed

9 files changed

+98
-16
lines changed

contrib/pgcrypto/expected/pgp-encrypt.out

+19
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,25 @@ select pgp_sym_decrypt(
103103
Secret.
104104
(1 row)
105105

106+
-- s2k count change
107+
select pgp_sym_decrypt(
108+
pgp_sym_encrypt('Secret.', 'key', 's2k-count=1024'),
109+
'key', 'expect-s2k-count=1024');
110+
pgp_sym_decrypt
111+
-----------------
112+
Secret.
113+
(1 row)
114+
115+
-- s2k_count rounds up
116+
select pgp_sym_decrypt(
117+
pgp_sym_encrypt('Secret.', 'key', 's2k-count=65000000'),
118+
'key', 'expect-s2k-count=65000000');
119+
NOTICE: pgp_decrypt: unexpected s2k_count: expected 65000000 got 65011712
120+
pgp_sym_decrypt
121+
-----------------
122+
Secret.
123+
(1 row)
124+
106125
-- s2k digest change
107126
select pgp_sym_decrypt(
108127
pgp_sym_encrypt('Secret.', 'key', 's2k-digest-algo=md5'),

contrib/pgcrypto/pgp-decrypt.c

+1
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,7 @@ parse_symenc_sesskey(PGP_Context *ctx, PullFilter *src)
643643
if (res < 0)
644644
return res;
645645
ctx->s2k_mode = ctx->s2k.mode;
646+
ctx->s2k_count = s2k_decode_count(ctx->s2k.iter);
646647
ctx->s2k_digest_algo = ctx->s2k.digest_algo;
647648

648649
/*

contrib/pgcrypto/pgp-encrypt.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ init_s2k_key(PGP_Context *ctx)
567567
if (ctx->s2k_cipher_algo < 0)
568568
ctx->s2k_cipher_algo = ctx->cipher_algo;
569569

570-
res = pgp_s2k_fill(&ctx->s2k, ctx->s2k_mode, ctx->s2k_digest_algo);
570+
res = pgp_s2k_fill(&ctx->s2k, ctx->s2k_mode, ctx->s2k_digest_algo, ctx->s2k_count);
571571
if (res < 0)
572572
return res;
573573

contrib/pgcrypto/pgp-pgsql.c

+10
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ struct debug_expect
181181
int expect;
182182
int cipher_algo;
183183
int s2k_mode;
184+
int s2k_count;
184185
int s2k_cipher_algo;
185186
int s2k_digest_algo;
186187
int compress_algo;
@@ -196,6 +197,7 @@ fill_expect(struct debug_expect * ex, int text_mode)
196197
ex->expect = 0;
197198
ex->cipher_algo = -1;
198199
ex->s2k_mode = -1;
200+
ex->s2k_count = -1;
199201
ex->s2k_cipher_algo = -1;
200202
ex->s2k_digest_algo = -1;
201203
ex->compress_algo = -1;
@@ -218,6 +220,7 @@ check_expect(PGP_Context *ctx, struct debug_expect * ex)
218220
{
219221
EX_CHECK(cipher_algo);
220222
EX_CHECK(s2k_mode);
223+
EX_CHECK(s2k_count);
221224
EX_CHECK(s2k_digest_algo);
222225
EX_CHECK(use_sess_key);
223226
if (ctx->use_sess_key)
@@ -247,6 +250,8 @@ set_arg(PGP_Context *ctx, char *key, char *val,
247250
res = pgp_set_sess_key(ctx, atoi(val));
248251
else if (strcmp(key, "s2k-mode") == 0)
249252
res = pgp_set_s2k_mode(ctx, atoi(val));
253+
else if (strcmp(key, "s2k-count") == 0)
254+
res = pgp_set_s2k_count(ctx, atoi(val));
250255
else if (strcmp(key, "s2k-digest-algo") == 0)
251256
res = pgp_set_s2k_digest_algo(ctx, val);
252257
else if (strcmp(key, "s2k-cipher-algo") == 0)
@@ -286,6 +291,11 @@ set_arg(PGP_Context *ctx, char *key, char *val,
286291
ex->expect = 1;
287292
ex->s2k_mode = atoi(val);
288293
}
294+
else if (ex != NULL && strcmp(key, "expect-s2k-count") == 0)
295+
{
296+
ex->expect = 1;
297+
ex->s2k_count = atoi(val);
298+
}
289299
else if (ex != NULL && strcmp(key, "expect-s2k-digest-algo") == 0)
290300
{
291301
ex->expect = 1;

contrib/pgcrypto/pgp-s2k.c

+24-13
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,10 @@ calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
132132
unsigned preload = 0;
133133
unsigned remain,
134134
c,
135-
cval,
136135
curcnt,
137136
count;
138137

139-
cval = s2k->iter;
140-
count = ((unsigned) 16 + (cval & 15)) << ((cval >> 4) + 6);
138+
count = s2k_decode_count(s2k->iter);
141139

142140
md_rlen = px_md_result_size(md);
143141

@@ -195,21 +193,34 @@ calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
195193
}
196194

197195
/*
198-
* Decide S2K_ISALTED iteration count
196+
* Decide PGP_S2K_ISALTED iteration count (in OpenPGP one-byte representation)
199197
*
200198
* Too small: weak
201199
* Too big: slow
202200
* gpg defaults to 96 => 65536 iters
203-
* let it float a bit: 96 + 32 => 262144 iters
201+
*
202+
* For our default (count=-1) we let it float a bit: 96 + 32 => between 65536
203+
* and 262144 iterations.
204+
*
205+
* Otherwise, find the smallest number which provides at least the specified
206+
* iteration count.
204207
*/
205-
static int
206-
decide_count(unsigned rand_byte)
208+
static uint8
209+
decide_s2k_iter(unsigned rand_byte, int count)
207210
{
208-
return 96 + (rand_byte & 0x1F);
211+
int iter;
212+
213+
if (count == -1)
214+
return 96 + (rand_byte & 0x1F);
215+
/* this is a bit brute-force, but should be quick enough */
216+
for (iter = 0; iter <= 255; iter++)
217+
if (s2k_decode_count(iter) >= count)
218+
return iter;
219+
return 255;
209220
}
210221

211222
int
212-
pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
223+
pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count)
213224
{
214225
int res = 0;
215226
uint8 tmp;
@@ -219,19 +230,19 @@ pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
219230

220231
switch (s2k->mode)
221232
{
222-
case 0:
233+
case PGP_S2K_SIMPLE:
223234
break;
224-
case 1:
235+
case PGP_S2K_SALTED:
225236
res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
226237
break;
227-
case 3:
238+
case PGP_S2K_ISALTED:
228239
res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
229240
if (res < 0)
230241
break;
231242
res = px_get_pseudo_random_bytes(&tmp, 1);
232243
if (res < 0)
233244
break;
234-
s2k->iter = decide_count(tmp);
245+
s2k->iter = decide_s2k_iter(tmp, count);
235246
break;
236247
default:
237248
res = PXE_PGP_BAD_S2K_MODE;

contrib/pgcrypto/pgp.c

+13
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
static int def_cipher_algo = PGP_SYM_AES_128;
4141
static int def_s2k_cipher_algo = -1;
4242
static int def_s2k_mode = PGP_S2K_ISALTED;
43+
static int def_s2k_count = -1;
4344
static int def_s2k_digest_algo = PGP_DIGEST_SHA1;
4445
static int def_compress_algo = PGP_COMPR_NONE;
4546
static int def_compress_level = 6;
@@ -206,6 +207,7 @@ pgp_init(PGP_Context **ctx_p)
206207
ctx->cipher_algo = def_cipher_algo;
207208
ctx->s2k_cipher_algo = def_s2k_cipher_algo;
208209
ctx->s2k_mode = def_s2k_mode;
210+
ctx->s2k_count = def_s2k_count;
209211
ctx->s2k_digest_algo = def_s2k_digest_algo;
210212
ctx->compress_algo = def_compress_algo;
211213
ctx->compress_level = def_compress_level;
@@ -269,6 +271,17 @@ pgp_set_s2k_mode(PGP_Context *ctx, int mode)
269271
return err;
270272
}
271273

274+
int
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+
272285
int
273286
pgp_set_compress_algo(PGP_Context *ctx, int algo)
274287
{

contrib/pgcrypto/pgp.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ struct PGP_S2K
124124
uint8 mode;
125125
uint8 digest_algo;
126126
uint8 salt[8];
127-
uint8 iter;
127+
uint8 iter; /* encoded (one-octet) count */
128128
/* calculated: */
129129
uint8 key[PGP_MAX_KEY];
130130
uint8 key_len;
@@ -138,6 +138,7 @@ struct PGP_Context
138138
*/
139139
PGP_S2K s2k;
140140
int s2k_mode;
141+
int s2k_count; /* 4-byte decoded count */
141142
int s2k_digest_algo;
142143
int s2k_cipher_algo;
143144
int cipher_algo;
@@ -171,6 +172,10 @@ struct PGP_Context
171172
unsigned sess_key_len;
172173
};
173174

175+
/* from RFC 4880 3.7.1.3 */
176+
#define s2k_decode_count(cval) \
177+
(((unsigned) 16 + (cval & 15)) << ((cval >> 4) + 6))
178+
174179
struct PGP_MPI
175180
{
176181
uint8 *data;
@@ -243,6 +248,7 @@ const char *pgp_get_cipher_name(int code);
243248

244249
int pgp_set_cipher_algo(PGP_Context *ctx, const char *name);
245250
int pgp_set_s2k_mode(PGP_Context *ctx, int type);
251+
int pgp_set_s2k_count(PGP_Context *ctx, int count);
246252
int pgp_set_s2k_cipher_algo(PGP_Context *ctx, const char *name);
247253
int pgp_set_s2k_digest_algo(PGP_Context *ctx, const char *name);
248254
int pgp_set_convert_crlf(PGP_Context *ctx, int doit);
@@ -267,7 +273,7 @@ int pgp_load_cipher(int c, PX_Cipher **res);
267273
int pgp_get_cipher_key_size(int c);
268274
int pgp_get_cipher_block_size(int c);
269275

270-
int pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo);
276+
int pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count);
271277
int pgp_s2k_read(PullFilter *src, PGP_S2K *s2k);
272278
int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int klen);
273279

contrib/pgcrypto/sql/pgp-encrypt.sql

+9
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ select pgp_sym_decrypt(
5555
pgp_sym_encrypt('Secret.', 'key', 's2k-mode=3'),
5656
'key', 'expect-s2k-mode=3');
5757

58+
-- s2k count change
59+
select pgp_sym_decrypt(
60+
pgp_sym_encrypt('Secret.', 'key', 's2k-count=1024'),
61+
'key', 'expect-s2k-count=1024');
62+
-- s2k_count rounds up
63+
select pgp_sym_decrypt(
64+
pgp_sym_encrypt('Secret.', 'key', 's2k-count=65000000'),
65+
'key', 'expect-s2k-count=65000000');
66+
5867
-- s2k digest change
5968
select pgp_sym_decrypt(
6069
pgp_sym_encrypt('Secret.', 'key', 's2k-digest-algo=md5'),

doc/src/sgml/pgcrypto.sgml

+13
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,19 @@ Applies to: pgp_sym_encrypt
858858
</literallayout>
859859
</sect4>
860860

861+
<sect4>
862+
<title>s2k-count</title>
863+
864+
<para>
865+
The number of iterations of the S2K algorithm to use. It must
866+
be a value between 1024 and 65011712, inclusive.
867+
</para>
868+
<literallayout>
869+
Default: A random value bewteen 65536 and 253952
870+
Applies to: pgp_sym_encrypt, only with s2k-mode=3
871+
</literallayout>
872+
</sect4>
873+
861874
<sect4>
862875
<title>s2k-digest-algo</title>
863876

0 commit comments

Comments
 (0)