Skip to content

Commit 294eee2

Browse files
committed
Introduce new RSA API.
This also: a) deprecates the old RSA and PKCS#1 API. b) reverts the changes done to them in order to make the now deprecated API compatible again with the last release. The fixes commit mentioned below is the testcase for the Bleichenbacher attack, which works now again as expected. Fixes: 9d03c38 ("add flags to `der_decode_sequence()`") Signed-off-by: Steffen Jaeckel <[email protected]>
1 parent 15815a8 commit 294eee2

25 files changed

+1483
-685
lines changed

demos/timing.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -702,11 +702,21 @@ static void time_rsa(void)
702702
unsigned char buf[2][2048] = { 0 };
703703
unsigned long x, y, z, zzz;
704704
int err, zz, stat;
705+
ltc_rsa_op_parameters rsa_params = {
706+
.u.crypt.lparam = (const unsigned char *)"testprog",
707+
.u.crypt.lparamlen = 8,
708+
.prng = &yarrow_prng,
709+
.wprng = find_prng("yarrow"),
710+
.params.hash_alg = "sha1",
711+
.params.mgf1_hash_alg = "sha1",
712+
.params.saltlen = 8,
713+
};
705714

706715
if (ltc_mp.name == NULL) return;
707716

708717
for (x = 2048; x <= 8192; x <<= 1) {
709718
t2 = 0;
719+
rsa_params.padding = LTC_PKCS_1_OAEP;
710720
for (y = 0; y < 4; y++) {
711721
t_start();
712722
t1 = t_read();
@@ -734,9 +744,7 @@ static void time_rsa(void)
734744
t_start();
735745
t1 = t_read();
736746
z = sizeof(buf[1]);
737-
if ((err = rsa_encrypt_key(buf[0], 32, buf[1], &z, (const unsigned char *)"testprog", 8, &yarrow_prng,
738-
find_prng("yarrow"), find_hash("sha1"),
739-
&key)) != CRYPT_OK) {
747+
if ((err = rsa_encrypt_key_v2(buf[0], 32, buf[1], &z, &rsa_params, &key)) != CRYPT_OK) {
740748
fprintf(stderr, "\n\nrsa_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
741749
exit(EXIT_FAILURE);
742750
}
@@ -755,8 +763,7 @@ static void time_rsa(void)
755763
t_start();
756764
t1 = t_read();
757765
zzz = sizeof(buf[0]);
758-
if ((err = rsa_decrypt_key(buf[1], z, buf[0], &zzz, (const unsigned char *)"testprog", 8, find_hash("sha1"),
759-
&zz, &key)) != CRYPT_OK) {
766+
if ((err = rsa_decrypt_key_v2(buf[1], z, buf[0], &zzz, &rsa_params, &zz, &key)) != CRYPT_OK) {
760767
fprintf(stderr, "\n\nrsa_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
761768
exit(EXIT_FAILURE);
762769
}
@@ -771,12 +778,12 @@ static void time_rsa(void)
771778
fprintf(stderr, "RSA-%lu decrypt_key took %15"PRI64"u cycles\n", x, t2);
772779

773780
t2 = 0;
781+
rsa_params.padding = LTC_PKCS_1_PSS;
774782
for (y = 0; y < 256; y++) {
775783
t_start();
776784
t1 = t_read();
777785
z = sizeof(buf[1]);
778-
if ((err = rsa_sign_hash(buf[0], 20, buf[1], &z, &yarrow_prng,
779-
find_prng("yarrow"), find_hash("sha1"), 8, &key)) != CRYPT_OK) {
786+
if ((err = rsa_sign_hash_v2(buf[0], 20, buf[1], &z, &rsa_params, &key)) != CRYPT_OK) {
780787
fprintf(stderr, "\n\nrsa_sign_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
781788
exit(EXIT_FAILURE);
782789
}
@@ -794,7 +801,7 @@ static void time_rsa(void)
794801
for (y = 0; y < 2048; y++) {
795802
t_start();
796803
t1 = t_read();
797-
if ((err = rsa_verify_hash(buf[1], z, buf[0], 20, find_hash("sha1"), 8, &stat, &key)) != CRYPT_OK) {
804+
if ((err = rsa_verify_hash_v2(buf[1], z, buf[0], 20, &rsa_params, &stat, &key)) != CRYPT_OK) {
798805
fprintf(stderr, "\n\nrsa_verify_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
799806
exit(EXIT_FAILURE);
800807
}

doc/crypt.tex

Lines changed: 396 additions & 168 deletions
Large diffs are not rendered by default.

src/headers/tomcrypt_pk.h

Lines changed: 108 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ typedef struct ltc_rsa_parameters {
7070
/** saltLength is only defined for PSS
7171
* If saltLength == 0 -> OAEP, else -> PSS */
7272
unsigned long saltlen;
73-
/** hash and MGF hash algorithms */
73+
/** lparam hash for OAEP
74+
* resp.
75+
* signature hash for PSS
76+
* and MGF hash algorithms */
7477
const char *hash_alg, *mgf1_hash_alg;
7578
} ltc_rsa_parameters;
7679

@@ -109,52 +112,133 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen,
109112

110113
void rsa_free(rsa_key *key);
111114

112-
/* These use PKCS #1 v2.0 padding */
113-
#define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \
114-
rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, -1, LTC_PKCS_1_OAEP, key)
115-
116-
#define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \
117-
rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key)
118-
119-
#define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \
120-
rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, hash_idx, saltlen, key)
121-
122-
#define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \
123-
rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, hash_idx, saltlen, stat, key)
124-
125-
#define rsa_sign_saltlen_get_max(hash_idx, key) \
126-
rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key)
115+
typedef struct ltc_rsa_op_parameters {
116+
/* The RSA API will set the `pss_oaep` field for you,
117+
* depending on the value of `padding`. */
118+
ltc_rsa_parameters params;
119+
/* The padding type */
120+
int padding;
121+
/* The PRNG to use.
122+
* Only required for signing and encryption. */
123+
int wprng;
124+
prng_state *prng;
125+
/* Operation-specific parameters */
126+
union {
127+
struct {
128+
const unsigned char *lparam;
129+
unsigned long lparamlen;
130+
} crypt;
131+
/* let's make space for potential future extensions */
132+
ulong64 dummy[8];
133+
} u;
134+
} ltc_rsa_op_parameters;
135+
136+
int rsa_encrypt_key_v2(const unsigned char *in, unsigned long inlen,
137+
unsigned char *out, unsigned long *outlen,
138+
ltc_rsa_op_parameters *opts,
139+
const rsa_key *key);
140+
141+
int rsa_decrypt_key_v2(const unsigned char *in, unsigned long inlen,
142+
unsigned char *out, unsigned long *outlen,
143+
ltc_rsa_op_parameters *opts,
144+
int *stat,
145+
const rsa_key *key);
146+
147+
int rsa_sign_hash_v2(const unsigned char *hash, unsigned long hashlen,
148+
unsigned char *sig, unsigned long *siglen,
149+
ltc_rsa_op_parameters *opts,
150+
const rsa_key *key);
151+
152+
int rsa_verify_hash_v2(const unsigned char *sig, unsigned long siglen,
153+
const unsigned char *hash, unsigned long hashlen,
154+
ltc_rsa_op_parameters *opts,
155+
int *stat,
156+
const rsa_key *key);
127157

158+
/* These use PKCS #1 v2.0 padding */
159+
#define ltc_rsa_encrypt_key(in, inlen, out, outlen, lp, lplen, prng_, prng_idx, hash_idx, key) \
160+
rsa_encrypt_key_v2(in, inlen, out, outlen, \
161+
&(ltc_rsa_op_parameters){ \
162+
.u.crypt.lparam = lp, \
163+
.u.crypt.lparamlen = lplen,\
164+
.prng = prng_, \
165+
.wprng = prng_idx, \
166+
.params.mgf1_hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \
167+
.params.hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \
168+
.padding = LTC_PKCS_1_OAEP, \
169+
}, key)
170+
171+
#define ltc_rsa_decrypt_key(in, inlen, out, outlen, lp, lplen, hash_idx, stat, key) \
172+
rsa_decrypt_key_v2(in, inlen, out, outlen, \
173+
&(ltc_rsa_op_parameters){ \
174+
.u.crypt.lparam = lp, \
175+
.u.crypt.lparamlen = lplen,\
176+
.params.mgf1_hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \
177+
.params.hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \
178+
.padding = LTC_PKCS_1_OAEP, \
179+
}, stat, key)
180+
181+
#define ltc_rsa_sign_hash(hash, hashlen, sig, siglen, prng_, prng_idx, hash_idx, saltlen_, key) \
182+
rsa_sign_hash_v2(hash, hashlen, sig, siglen, \
183+
&(ltc_rsa_op_parameters){ \
184+
.prng = prng_, \
185+
.wprng = prng_idx, \
186+
.params.mgf1_hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \
187+
.params.hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \
188+
.params.saltlen = saltlen_, \
189+
.padding = LTC_PKCS_1_PSS, \
190+
}, key)
191+
192+
#define ltc_rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen_, stat, key) \
193+
rsa_verify_hash_v2(sig, siglen, hash, hashlen, \
194+
&(ltc_rsa_op_parameters){ \
195+
.params.mgf1_hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \
196+
.params.hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \
197+
.params.saltlen = saltlen_, \
198+
.padding = LTC_PKCS_1_PSS, \
199+
}, stat, key)
200+
201+
/* If you used those in v1, they're still working */
202+
#define rsa_encrypt_key ltc_rsa_encrypt_key
203+
#define rsa_decrypt_key ltc_rsa_decrypt_key
204+
#define rsa_sign_hash ltc_rsa_sign_hash
205+
#define rsa_verify_hash ltc_rsa_verify_hash
206+
207+
#ifndef LTC_NO_DEPRECATED_APIS
128208
/* These can be switched between PKCS #1 v2.x and PKCS #1 v1.5 paddings */
209+
LTC_DEPRECATED(rsa_encrypt_key_v2)
129210
int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
130211
unsigned char *out, unsigned long *outlen,
131212
const unsigned char *lparam, unsigned long lparamlen,
132213
prng_state *prng, int prng_idx,
133-
int mgf_hash, int lparam_hash,
134-
int padding,
214+
int hash_idx, int padding,
135215
const rsa_key *key);
136216

217+
LTC_DEPRECATED(rsa_decrypt_key_v2)
137218
int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
138219
unsigned char *out, unsigned long *outlen,
139220
const unsigned char *lparam, unsigned long lparamlen,
140-
int mgf_hash, int lparam_hash,
141-
int padding,
221+
int hash_idx, int padding,
142222
int *stat, const rsa_key *key);
143223

224+
LTC_DEPRECATED(rsa_sign_hash_v2)
144225
int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
145226
unsigned char *out, unsigned long *outlen,
146227
int padding,
147228
prng_state *prng, int prng_idx,
148-
int hash_idx, int mgf_hash_idx,
149-
unsigned long saltlen,
229+
int hash_idx, unsigned long saltlen,
150230
const rsa_key *key);
151231

232+
LTC_DEPRECATED(rsa_verify_hash_v2)
152233
int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
153234
const unsigned char *hash, unsigned long hashlen,
154235
int padding,
155-
int hash_idx, int mgf_hash_idx,
156-
unsigned long saltlen,
236+
int hash_idx, unsigned long saltlen,
157237
int *stat, const rsa_key *key);
238+
#endif /* LTC_NO_DEPRECATED_APIS */
239+
240+
#define rsa_sign_saltlen_get_max(hash_idx, key) \
241+
rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key)
158242

159243
int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key);
160244

src/headers/tomcrypt_pkcs.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,19 @@ enum ltc_pkcs_1_paddings
2020
LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */
2121
};
2222

23+
#ifndef LTC_NO_DEPRECATED_APIS
24+
LTC_DEPRECATED(nothing. API will be internal)
2325
int pkcs_1_mgf1( int hash_idx,
2426
const unsigned char *seed, unsigned long seedlen,
2527
unsigned char *mask, unsigned long masklen);
2628

29+
LTC_DEPRECATED(nothing. API will be removed)
2730
int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out);
31+
LTC_DEPRECATED(nothing. API will be removed)
2832
int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen);
2933

3034
/* *** v1.5 padding */
35+
LTC_DEPRECATED(nothing. API will be internal)
3136
int pkcs_1_v1_5_encode(const unsigned char *msg,
3237
unsigned long msglen,
3338
int block_type,
@@ -37,6 +42,7 @@ int pkcs_1_v1_5_encode(const unsigned char *msg,
3742
unsigned char *out,
3843
unsigned long *outlen);
3944

45+
LTC_DEPRECATED(nothing. API will be internal)
4046
int pkcs_1_v1_5_decode(const unsigned char *msg,
4147
unsigned long msglen,
4248
int block_type,
@@ -46,30 +52,33 @@ int pkcs_1_v1_5_decode(const unsigned char *msg,
4652
int *is_valid);
4753

4854
/* *** v2.1 padding */
55+
LTC_DEPRECATED(nothing. API will be internal)
4956
int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
5057
const unsigned char *lparam, unsigned long lparamlen,
5158
unsigned long modulus_bitlen, prng_state *prng,
52-
int prng_idx,
53-
int mgf_hash, int lparam_hash,
59+
int prng_idx, int hash_idx,
5460
unsigned char *out, unsigned long *outlen);
5561

62+
LTC_DEPRECATED(nothing. API will be internal)
5663
int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
5764
const unsigned char *lparam, unsigned long lparamlen,
58-
unsigned long modulus_bitlen,
59-
int mgf_hash, int lparam_hash,
65+
unsigned long modulus_bitlen, int hash_idx,
6066
unsigned char *out, unsigned long *outlen,
6167
int *res);
6268

69+
LTC_DEPRECATED(nothing. API will be internal)
6370
int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
6471
unsigned long saltlen, prng_state *prng,
6572
int prng_idx, int hash_idx,
6673
unsigned long modulus_bitlen,
6774
unsigned char *out, unsigned long *outlen);
6875

76+
LTC_DEPRECATED(nothing. API will be internal)
6977
int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
7078
const unsigned char *sig, unsigned long siglen,
7179
unsigned long saltlen, int hash_idx,
7280
unsigned long modulus_bitlen, int *res);
81+
#endif /* LTC_NO_DEPRECATED_APIS */
7382

7483
#endif /* LTC_PKCS_1 */
7584

0 commit comments

Comments
 (0)