Skip to content
This repository was archived by the owner on Jan 26, 2026. It is now read-only.

Commit 26bfa41

Browse files
author
NIIBE Yutaka
committed
kdf: Extend original Balloon to other digest algos.
* cipher/kdf.c (struct balloon_thread_data): Use pointer to md_spec. (prng_aes_ctr_init): Select relevant cipher to match BLKLEN. Use other half of digest for IV if not original Balloon. (balloon_open): Support other digest algos. (balloon_final): Check the error code in compute. -- GnuPG-bug-id: 5817 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
1 parent 08ab322 commit 26bfa41

1 file changed

Lines changed: 76 additions & 18 deletions

File tree

cipher/kdf.c

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -891,11 +891,10 @@ struct balloon_thread_data {
891891
/* Balloon context */
892892
struct balloon_context {
893893
int algo;
894-
int hash_type;
895894
int prng_type;
896895

897896
unsigned int blklen;
898-
gcry_md_spec_t md_spec;
897+
const gcry_md_spec_t *md_spec;
899898

900899
const unsigned char *password;
901900
size_t passwordlen;
@@ -925,20 +924,55 @@ prng_aes_ctr_init (gcry_cipher_hd_t *hd_p, balloon_ctx_t b,
925924
gpg_err_code_t ec;
926925
gcry_cipher_hd_t hd;
927926
unsigned char key[BALLOON_SALT_LEN_MAX];
927+
int cipher_algo;
928+
unsigned int keylen, blklen;
928929

929-
b->md_spec.hash_buffers (key, b->blklen, iov, iov_count);
930-
ec = _gcry_cipher_open (&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0);
930+
switch (b->blklen)
931+
{
932+
case 64:
933+
cipher_algo = GCRY_CIPHER_AES256;
934+
break;
935+
936+
case 48:
937+
cipher_algo = GCRY_CIPHER_AES192;
938+
break;
939+
940+
default:
941+
case 32:
942+
cipher_algo = GCRY_CIPHER_AES;
943+
break;
944+
}
945+
946+
keylen = _gcry_cipher_get_algo_keylen (cipher_algo);
947+
blklen = _gcry_cipher_get_algo_blklen (cipher_algo);
948+
949+
b->md_spec->hash_buffers (key, b->blklen, iov, iov_count);
950+
ec = _gcry_cipher_open (&hd, cipher_algo, GCRY_CIPHER_MODE_CTR, 0);
931951
if (ec)
932952
return ec;
933953

934-
ec = _gcry_cipher_setkey (hd, key, 16);
954+
ec = _gcry_cipher_setkey (hd, key, keylen);
935955
if (ec)
936956
{
937957
_gcry_cipher_close (hd);
938958
return ec;
939959
}
940960

941-
wipememory (key, 32);
961+
if (cipher_algo == GCRY_CIPHER_AES
962+
&& b->md_spec == &_gcry_digest_spec_sha256)
963+
/* Original Balloon uses zero IV. */
964+
;
965+
else
966+
{
967+
ec = _gcry_cipher_setiv (hd, key+keylen, blklen);
968+
if (ec)
969+
{
970+
_gcry_cipher_close (hd);
971+
return ec;
972+
}
973+
}
974+
975+
wipememory (key, BALLOON_SALT_LEN_MAX);
942976
*hd_p = hd;
943977
return ec;
944978
}
@@ -985,15 +1019,37 @@ balloon_open (gcry_kdf_hd_t *hd, int subalgo,
9851019
size_t n;
9861020
unsigned char *block;
9871021
unsigned int i;
988-
gcry_md_spec_t md_spec;
1022+
const gcry_md_spec_t *md_spec;
9891023

990-
/* For now, only SHA256 is supported. */
991-
if (subalgo != GCRY_MD_SHA256)
992-
return GPG_ERR_NOT_SUPPORTED;
993-
else
1024+
hash_type = subalgo;
1025+
switch (hash_type)
9941026
{
995-
hash_type = subalgo;
996-
md_spec = _gcry_digest_spec_sha256;
1027+
case GCRY_MD_SHA256:
1028+
md_spec = &_gcry_digest_spec_sha256;
1029+
break;
1030+
1031+
case GCRY_MD_SHA384:
1032+
md_spec = &_gcry_digest_spec_sha384;
1033+
break;
1034+
1035+
case GCRY_MD_SHA512:
1036+
md_spec = &_gcry_digest_spec_sha512;
1037+
break;
1038+
1039+
case GCRY_MD_SHA3_256:
1040+
md_spec = &_gcry_digest_spec_sha3_256;
1041+
break;
1042+
1043+
case GCRY_MD_SHA3_384:
1044+
md_spec = &_gcry_digest_spec_sha3_384;
1045+
break;
1046+
1047+
case GCRY_MD_SHA3_512:
1048+
md_spec = &_gcry_digest_spec_sha3_512;
1049+
break;
1050+
1051+
default:
1052+
return GPG_ERR_NOT_SUPPORTED;
9971053
}
9981054

9991055
blklen = _gcry_md_get_algo_dlen (hash_type);
@@ -1006,7 +1062,7 @@ balloon_open (gcry_kdf_hd_t *hd, int subalgo,
10061062
/*
10071063
* It should have space_cost and time_cost.
10081064
* Optionally, for parallelised version, it has parallelism.
1009-
* Possibly (in future), it may have options for PRNG.
1065+
* Possibly (in future), it may have option to specify PRNG type.
10101066
*/
10111067
if (paramlen != 2 && paramlen != 3)
10121068
return GPG_ERR_INV_VALUE;
@@ -1027,7 +1083,6 @@ balloon_open (gcry_kdf_hd_t *hd, int subalgo,
10271083
return gpg_err_code_from_errno (errno);
10281084

10291085
b->algo = GCRY_KDF_BALLOON;
1030-
b->hash_type = hash_type;
10311086
b->md_spec = md_spec;
10321087
b->blklen = blklen;
10331088

@@ -1097,7 +1152,7 @@ balloon_compress (balloon_ctx_t b, u64 *counter_p, unsigned char *out,
10971152
iov[i].off = 0;
10981153
}
10991154

1100-
b->md_spec.hash_buffers (out, b->blklen, iov, 1+BALLOON_COMPRESS_BLOCKS);
1155+
b->md_spec->hash_buffers (out, b->blklen, iov, 1+BALLOON_COMPRESS_BLOCKS);
11011156
*counter_p += 1;
11021157
}
11031158

@@ -1120,7 +1175,7 @@ balloon_expand (balloon_ctx_t b, u64 *counter_p, unsigned char *block,
11201175
buf_put_le64 (octet_counter, *counter_p);
11211176
iov[1].data = block;
11221177
block += b->blklen;
1123-
b->md_spec.hash_buffers (block, b->blklen, iov, 2);
1178+
b->md_spec->hash_buffers (block, b->blklen, iov, 2);
11241179
*counter_p += 1;
11251180
}
11261181
}
@@ -1160,7 +1215,7 @@ balloon_compute_fill (balloon_ctx_t b,
11601215
iov[5].data = octet_parallelism;
11611216
iov[5].len = 4;
11621217
iov[5].off = 0;
1163-
b->md_spec.hash_buffers (t->block, b->blklen, iov, 6);
1218+
b->md_spec->hash_buffers (t->block, b->blklen, iov, 6);
11641219
*counter_p += 1;
11651220
balloon_expand (b, counter_p, t->block, b->n_blocks);
11661221
}
@@ -1296,6 +1351,9 @@ balloon_final (balloon_ctx_t b, size_t resultlen, void *result)
12961351
struct balloon_thread_data *t = &b->thread_data[i];
12971352
const unsigned char *last_block;
12981353

1354+
if (t->ec)
1355+
return t->ec;
1356+
12991357
last_block = t->block + (b->blklen * (t->b->n_blocks - 1));
13001358
balloon_xor_block (b, result, (u64 *)last_block);
13011359
}

0 commit comments

Comments
 (0)