4242#include " types.h"
4343#include " utils.h"
4444#ifdef CRYPTO_BACKEND_BOTAN
45+ #if defined(ENABLE_CRYPTO_REFRESH)
46+ #include " botan/bigint.h"
47+ #include < botan/pwdhash.h>
48+ #include < cmath>
49+ #endif
4550#include < botan/ffi.h>
4651#include " hash_botan.hpp"
4752#endif
@@ -66,11 +71,30 @@ pgp_s2k_derive_key(pgp_s2k_t *s2k, const char *password, uint8_t *key, int keysi
6671 iterations = s2k->iterations ;
6772 }
6873 break ;
74+ #if defined(ENABLE_CRYPTO_REFRESH)
75+ case PGP_S2KS_ARGON2:
76+ saltptr = s2k->salt ;
77+ break ;
78+ #endif
6979 default :
7080 return false ;
7181 }
7282
73- if (pgp_s2k_iterated (s2k->hash_alg , key, keysize, password, saltptr, iterations)) {
83+ #if defined(ENABLE_CRYPTO_REFRESH)
84+ if (s2k->specifier == PGP_S2KS_ARGON2) {
85+ if (pgp_s2k_argon2 (key,
86+ keysize,
87+ password,
88+ saltptr,
89+ s2k->argon2_t ,
90+ s2k->argon2_p ,
91+ s2k->argon2_encoded_m )) {
92+ RNP_LOG (" s2k argon2 failed" );
93+ return false ;
94+ }
95+ } else
96+ #endif
97+ if (pgp_s2k_iterated (s2k->hash_alg , key, keysize, password, saltptr, iterations)) {
7498 RNP_LOG (" s2k failed" );
7599 return false ;
76100 }
@@ -79,6 +103,45 @@ pgp_s2k_derive_key(pgp_s2k_t *s2k, const char *password, uint8_t *key, int keysi
79103}
80104
81105#ifdef CRYPTO_BACKEND_BOTAN
106+ #if defined(ENABLE_CRYPTO_REFRESH)
107+ int
108+ pgp_s2k_argon2 (uint8_t * out,
109+ size_t output_len,
110+ const char * password,
111+ const uint8_t *salt,
112+ uint8_t t,
113+ uint8_t p,
114+ uint8_t encoded_m)
115+ {
116+ const size_t argon2_salt_size = 16 ;
117+
118+ /* check constraints on p and t */
119+ if (!p || !t) {
120+ RNP_LOG (" Argon2 t and p must be non-zero" );
121+ return -1 ;
122+ }
123+ /* check constraints on m. Floating point calculation is fine due to restricted data range
124+ * (uint8_t) */
125+ if (encoded_m < (3 + (uint8_t ) std::ceil (std::log2 (p))) || encoded_m > 31 ) {
126+ RNP_LOG (" Argon2 encoded_m must be between 3+ceil(log2(p)) and 31" );
127+ return -1 ;
128+ }
129+
130+ try {
131+ auto pwdhash_fam = Botan::PasswordHashFamily::create_or_throw (" Argon2id" );
132+
133+ std::unique_ptr<Botan::PasswordHash> pwhash =
134+ pwdhash_fam->from_params (1 << encoded_m, t, p);
135+ pwhash->derive_key (
136+ out, output_len, password, std::strlen (password), salt, argon2_salt_size);
137+ } catch (const std::exception &e) {
138+ RNP_LOG (" %s" , e.what ());
139+ return -1 ;
140+ }
141+ return 0 ;
142+ }
143+ #endif
144+
82145int
83146pgp_s2k_iterated (pgp_hash_alg_t alg,
84147 uint8_t * out,
@@ -201,3 +264,34 @@ pgp_s2k_compute_iters(pgp_hash_alg_t alg, size_t desired_msec, size_t trial_msec
201264
202265 return pgp_s2k_decode_iterations ((iters > MIN_ITERS) ? iters : MIN_ITERS);
203266}
267+
268+ size_t
269+ pgp_s2k_t ::salt_size(pgp_s2k_specifier_t specifier)
270+ {
271+ #if defined(ENABLE_CRYPTO_REFRESH)
272+ return (specifier == PGP_S2KS_ARGON2 ? 16 : 8 );
273+ #endif
274+ return 8 ;
275+ }
276+
277+ uint8_t
278+ pgp_s2k_t ::specifier_len(pgp_s2k_specifier_t specifier)
279+ {
280+ switch (specifier) {
281+ case PGP_S2KS_SIMPLE:
282+ return 2 ;
283+ case PGP_S2KS_SALTED:
284+ return 10 ;
285+ case PGP_S2KS_ITERATED_AND_SALTED:
286+ return 11 ;
287+ case PGP_S2KS_EXPERIMENTAL:
288+ return 0 ; /* not used */
289+ #if defined(ENABLE_CRYPTO_REFRESH)
290+ case PGP_S2KS_ARGON2:
291+ return 20 ;
292+ #endif
293+ default :
294+ RNP_LOG (" invalid specifier" );
295+ throw rnp::rnp_exception (RNP_ERROR_BAD_PARAMETERS);
296+ }
297+ }
0 commit comments