3 * OpenPGP string2key functions.
5 * Copyright (c) 2005 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
39 calc_s2k_simple(PGP_S2K
*s2k
, PX_MD
*md
, const uint8
*key
,
44 uint8 buf
[PGP_MAX_DIGEST
];
47 uint8
*dst
= s2k
->key
;
49 md_bs
= px_md_block_size(md
);
50 md_rlen
= px_md_result_size(md
);
52 remain
= s2k
->key_len
;
60 memset(buf
, 0, preload
);
61 px_md_update(md
, buf
, preload
);
65 px_md_update(md
, key
, key_len
);
66 px_md_finish(md
, buf
);
70 memcpy(dst
, buf
, md_rlen
);
76 memcpy(dst
, buf
, remain
);
84 calc_s2k_salted(PGP_S2K
*s2k
, PX_MD
*md
, const uint8
*key
, unsigned key_len
)
88 uint8 buf
[PGP_MAX_DIGEST
];
93 md_bs
= px_md_block_size(md
);
94 md_rlen
= px_md_result_size(md
);
97 remain
= s2k
->key_len
;
104 memset(buf
, 0, preload
);
105 px_md_update(md
, buf
, preload
);
109 px_md_update(md
, s2k
->salt
, PGP_S2K_SALT
);
110 px_md_update(md
, key
, key_len
);
111 px_md_finish(md
, buf
);
113 if (remain
> md_rlen
)
115 memcpy(dst
, buf
, md_rlen
);
121 memcpy(dst
, buf
, remain
);
129 calc_s2k_iter_salted(PGP_S2K
*s2k
, PX_MD
*md
, const uint8
*key
,
134 uint8 buf
[PGP_MAX_DIGEST
];
136 unsigned preload
= 0;
144 count
= ((unsigned) 16 + (cval
& 15)) << ((cval
>> 4) + 6);
146 md_bs
= px_md_block_size(md
);
147 md_rlen
= px_md_result_size(md
);
149 remain
= s2k
->key_len
;
157 memset(buf
, 0, preload
);
158 px_md_update(md
, buf
, preload
);
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
;
166 while (curcnt
< count
)
168 if (curcnt
+ PGP_S2K_SALT
< count
)
172 px_md_update(md
, s2k
->salt
, c
);
175 if (curcnt
+ key_len
< count
)
177 else if (curcnt
< count
)
181 px_md_update(md
, key
, c
);
184 px_md_finish(md
, buf
);
186 if (remain
> md_rlen
)
188 memcpy(dst
, buf
, md_rlen
);
194 memcpy(dst
, buf
, remain
);
202 * Decide S2K_ISALTED iteration count
206 * gpg defaults to 96 => 65536 iters
207 * let it float a bit: 96 + 32 => 262144 iters
210 decide_count(unsigned rand_byte
)
212 return 96 + (rand_byte
& 0x1F);
216 pgp_s2k_fill(PGP_S2K
*s2k
, int mode
, int digest_algo
)
222 s2k
->digest_algo
= digest_algo
;
229 res
= px_get_pseudo_random_bytes(s2k
->salt
, PGP_S2K_SALT
);
232 res
= px_get_pseudo_random_bytes(s2k
->salt
, PGP_S2K_SALT
);
235 res
= px_get_pseudo_random_bytes(&tmp
, 1);
238 s2k
->iter
= decide_count(tmp
);
241 res
= PXE_PGP_BAD_S2K_MODE
;
247 pgp_s2k_read(PullFilter
*src
, PGP_S2K
*s2k
)
251 GETBYTE(src
, s2k
->mode
);
252 GETBYTE(src
, s2k
->digest_algo
);
258 res
= pullf_read_fixed(src
, 8, s2k
->salt
);
261 res
= pullf_read_fixed(src
, 8, s2k
->salt
);
264 GETBYTE(src
, s2k
->iter
);
267 res
= PXE_PGP_BAD_S2K_MODE
;
273 pgp_s2k_process(PGP_S2K
*s2k
, int cipher
, const uint8
*key
, int key_len
)
278 s2k
->key_len
= pgp_get_cipher_key_size(cipher
);
279 if (s2k
->key_len
<= 0)
280 return PXE_PGP_UNSUPPORTED_CIPHER
;
282 res
= pgp_load_digest(s2k
->digest_algo
, &md
);
289 res
= calc_s2k_simple(s2k
, md
, key
, key_len
);
292 res
= calc_s2k_salted(s2k
, md
, key
, key_len
);
295 res
= calc_s2k_iter_salted(s2k
, md
, key
, key_len
);
298 res
= PXE_PGP_BAD_S2K_MODE
;