Skip to content

Commit e4d5e49

Browse files
committed
Add support for separate MGF1 hashes
Update PKCS#1-PSS and RSA APIs that allow passing a separate hash index for the MGF1 hash. Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent 4db24a7 commit e4d5e49

File tree

8 files changed

+115
-37
lines changed

8 files changed

+115
-37
lines changed

src/headers/tomcrypt_pk.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ void rsa_free(rsa_key *key);
103103
rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key)
104104

105105
#define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \
106-
rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key)
106+
rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, hash_idx, saltlen, key)
107107

108108
#define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \
109-
rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, saltlen, stat, key)
109+
rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, hash_idx, saltlen, stat, key)
110110

111111
#define rsa_sign_saltlen_get_max(hash_idx, key) \
112112
rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key)
@@ -130,14 +130,16 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen
130130
int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
131131
unsigned char *out, unsigned long *outlen,
132132
int padding,
133-
prng_state *prng, int prng_idx,
134-
int hash_idx, unsigned long saltlen,
133+
prng_state *prng, int prng_idx,
134+
int hash_idx, int mgf_hash_idx,
135+
unsigned long saltlen,
135136
const rsa_key *key);
136137

137138
int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
138139
const unsigned char *hash, unsigned long hashlen,
139140
int padding,
140-
int hash_idx, unsigned long saltlen,
141+
int hash_idx, int mgf_hash_idx,
142+
unsigned long saltlen,
141143
int *stat, const rsa_key *key);
142144

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

src/headers/tomcrypt_private.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,22 @@ int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2);
750750

751751
/* tomcrypt_pkcs.h */
752752

753+
#ifdef LTC_PKCS_1
754+
755+
int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long msghashlen,
756+
unsigned long saltlen,
757+
prng_state *prng, int prng_idx,
758+
int hash_idx, int mgf_hash_idx,
759+
unsigned long modulus_bitlen,
760+
unsigned char *out, unsigned long *outlen);
761+
int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashlen,
762+
const unsigned char *sig, unsigned long siglen,
763+
unsigned long saltlen,
764+
int hash_idx, int mgf_hash_idx,
765+
unsigned long modulus_bitlen, int *res);
766+
767+
#endif /* LTC_PKCS_1 */
768+
753769
#ifdef LTC_PKCS_8
754770

755771
/* Public-Key Cryptography Standards (PKCS) #8:

src/pk/pkcs1/pkcs_1_pss_decode.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@
1717
@param siglen The length of the signature data (octets)
1818
@param saltlen The length of the salt used (octets)
1919
@param hash_idx The index of the hash desired
20+
@param mgf_hash_idx The index of the hash desired for MGF1
2021
@param modulus_bitlen The bit length of the RSA modulus
2122
@param res [out] The result of the comparison, 1==valid, 0==invalid
2223
@return CRYPT_OK if successful (even if the comparison failed)
2324
*/
24-
int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
25-
const unsigned char *sig, unsigned long siglen,
26-
unsigned long saltlen, int hash_idx,
27-
unsigned long modulus_bitlen, int *res)
25+
int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashlen,
26+
const unsigned char *sig, unsigned long siglen,
27+
unsigned long saltlen,
28+
int hash_idx, int mgf_hash_idx,
29+
unsigned long modulus_bitlen, int *res)
2830
{
2931
unsigned char *DB, *mask, *salt, *hash;
3032
unsigned long x, y, hLen, modulus_len;
@@ -41,6 +43,11 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
4143
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
4244
return err;
4345
}
46+
if (hash_idx != mgf_hash_idx) {
47+
if ((err = hash_is_valid(mgf_hash_idx)) != CRYPT_OK) {
48+
return err;
49+
}
50+
}
4451

4552
hLen = hash_descriptor[hash_idx].hashsize;
4653
modulus_bitlen--;
@@ -95,7 +102,7 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
95102
}
96103

97104
/* generate mask of length modulus_len - hLen - 1 from hash */
98-
if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
105+
if ((err = pkcs_1_mgf1(mgf_hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
99106
goto LBL_ERR;
100107
}
101108

@@ -163,4 +170,25 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
163170
return err;
164171
}
165172

173+
174+
/**
175+
PKCS #1 v2.00 PSS decode
176+
@param msghash The hash to verify
177+
@param msghashlen The length of the hash (octets)
178+
@param sig The signature data (encoded data)
179+
@param siglen The length of the signature data (octets)
180+
@param saltlen The length of the salt used (octets)
181+
@param hash_idx The index of the hash desired
182+
@param modulus_bitlen The bit length of the RSA modulus
183+
@param res [out] The result of the comparison, 1==valid, 0==invalid
184+
@return CRYPT_OK if successful (even if the comparison failed)
185+
*/
186+
int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
187+
const unsigned char *sig, unsigned long siglen,
188+
unsigned long saltlen, int hash_idx,
189+
unsigned long modulus_bitlen, int *res)
190+
{
191+
return pkcs_1_pss_decode_mgf1(msghash, msghashlen, sig, siglen, saltlen, hash_idx, hash_idx, modulus_bitlen, res);
192+
}
193+
166194
#endif /* LTC_PKCS_1 */

src/pk/pkcs1/pkcs_1_pss_encode.c

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@
1717
@param prng An active PRNG context
1818
@param prng_idx The index of the PRNG desired
1919
@param hash_idx The index of the hash desired
20+
@param mgf_hash_idx The index of the hash desired for MGF1
2021
@param modulus_bitlen The bit length of the RSA modulus
2122
@param out [out] The destination of the encoding
2223
@param outlen [in/out] The max size and resulting size of the encoded data
2324
@return CRYPT_OK if successful
2425
*/
25-
int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
26-
unsigned long saltlen, prng_state *prng,
27-
int prng_idx, int hash_idx,
28-
unsigned long modulus_bitlen,
29-
unsigned char *out, unsigned long *outlen)
26+
int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long msghashlen,
27+
unsigned long saltlen,
28+
prng_state *prng, int prng_idx,
29+
int hash_idx, int mgf_hash_idx,
30+
unsigned long modulus_bitlen,
31+
unsigned char *out, unsigned long *outlen)
3032
{
3133
unsigned char *DB, *mask, *salt, *hash;
3234
unsigned long x, y, hLen, modulus_len;
@@ -37,10 +39,15 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
3739
LTC_ARGCHK(out != NULL);
3840
LTC_ARGCHK(outlen != NULL);
3941

40-
/* ensure hash and PRNG are valid */
42+
/* ensure hashes and PRNG are valid */
4143
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
4244
return err;
4345
}
46+
if (hash_idx != mgf_hash_idx) {
47+
if ((err = hash_is_valid(mgf_hash_idx)) != CRYPT_OK) {
48+
return err;
49+
}
50+
}
4451
if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
4552
return err;
4653
}
@@ -111,7 +118,7 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
111118
/* x += saltlen; */
112119

113120
/* generate mask of length modulus_len - hLen - 1 from hash */
114-
if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
121+
if ((err = pkcs_1_mgf1(mgf_hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
115122
goto LBL_ERR;
116123
}
117124

@@ -161,4 +168,27 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
161168
return err;
162169
}
163170

171+
172+
/**
173+
PKCS #1 v2.00 Signature Encoding using MGF1 and both hashes are the same
174+
@param msghash The hash to encode
175+
@param msghashlen The length of the hash (octets)
176+
@param saltlen The length of the salt desired (octets)
177+
@param prng An active PRNG context
178+
@param prng_idx The index of the PRNG desired
179+
@param hash_idx The index of the hash desired
180+
@param modulus_bitlen The bit length of the RSA modulus
181+
@param out [out] The destination of the encoding
182+
@param outlen [in/out] The max size and resulting size of the encoded data
183+
@return CRYPT_OK if successful
184+
*/
185+
int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
186+
unsigned long saltlen, prng_state *prng,
187+
int prng_idx, int hash_idx,
188+
unsigned long modulus_bitlen,
189+
unsigned char *out, unsigned long *outlen)
190+
{
191+
return pkcs_1_pss_encode_mgf1(msghash, msghashlen, saltlen, prng, prng_idx, hash_idx, hash_idx, modulus_bitlen, out, outlen);
192+
}
193+
164194
#endif /* LTC_PKCS_1 */

src/pk/rsa/rsa_sign_hash.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@
2626
int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
2727
unsigned char *out, unsigned long *outlen,
2828
int padding,
29-
prng_state *prng, int prng_idx,
30-
int hash_idx, unsigned long saltlen,
31-
const rsa_key *key)
29+
prng_state *prng, int prng_idx,
30+
int hash_idx, int mgf_hash_idx,
31+
unsigned long saltlen,
32+
const rsa_key *key)
3233
{
3334
unsigned long modulus_bitlen, modulus_bytelen, x, y;
3435
int err;
@@ -72,8 +73,8 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
7273
if (padding == LTC_PKCS_1_PSS) {
7374
/* PSS pad the key */
7475
x = *outlen;
75-
if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx,
76-
hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) {
76+
if ((err = pkcs_1_pss_encode_mgf1(in, inlen, saltlen, prng, prng_idx,
77+
hash_idx, mgf_hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) {
7778
return err;
7879
}
7980
} else {

src/pk/rsa/rsa_verify_hash.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
2626
const unsigned char *hash, unsigned long hashlen,
2727
int padding,
28-
int hash_idx, unsigned long saltlen,
28+
int hash_idx, int mgf_hash_idx,
29+
unsigned long saltlen,
2930
int *stat, const rsa_key *key)
3031
{
3132
unsigned long modulus_bitlen, modulus_bytelen, x;
@@ -87,10 +88,10 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle
8788
/* PSS decode and verify it */
8889

8990
if(modulus_bitlen%8 == 1){
90-
err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat);
91+
err = pkcs_1_pss_decode_mgf1(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, mgf_hash_idx, modulus_bitlen, stat);
9192
}
9293
else{
93-
err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
94+
err = pkcs_1_pss_decode_mgf1(hash, hashlen, tmpbuf, x, saltlen, hash_idx, mgf_hash_idx, modulus_bitlen, stat);
9495
}
9596

9697
} else {

tests/pkcs_1_emsa_test.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ int pkcs_1_emsa_test(void)
3939
unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf);
4040
int stat;
4141
DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name);
42-
DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, 0, key), s->name);
42+
DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, -1, 0, key), s->name);
4343
COMPARE_TESTVECTOR(obuf, obuflen, s->o2, s->o2_l,s->name, j);
44-
DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, 0, &stat, key), s->name);
44+
DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, -1, 0, &stat, key), s->name);
4545
DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
4646
} /* for */
4747

tests/rsa_test.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,13 @@ static int rsa_compat_test(void)
191191

192192
/* sign-verify a message with PKCS #1 v1.5 no ASN.1 */
193193
len = sizeof(buf);
194-
DO(rsa_sign_hash_ex((unsigned char*)"test", 4, buf, &len, LTC_PKCS_1_V1_5_NA1, NULL, 0, 0, 0, &key));
194+
DO(rsa_sign_hash_ex((unsigned char*)"test", 4, buf, &len, LTC_PKCS_1_V1_5_NA1, NULL, 0, 0, 0, 0, &key));
195195
if (len != sizeof(openssl_rsautl_pkcs) || memcmp(buf, openssl_rsautl_pkcs, len)) {
196196
fprintf(stderr, "RSA rsa_sign_hash_ex + LTC_PKCS_1_V1_5_NA1 failed\n");
197197
return 1;
198198
}
199199
stat = 0;
200-
DO(rsa_verify_hash_ex(openssl_rsautl_pkcs, sizeof(openssl_rsautl_pkcs), (unsigned char*)"test", 4, LTC_PKCS_1_V1_5_NA1, 0, 0, &stat, &pubkey));
200+
DO(rsa_verify_hash_ex(openssl_rsautl_pkcs, sizeof(openssl_rsautl_pkcs), (unsigned char*)"test", 4, LTC_PKCS_1_V1_5_NA1, 0, 0, 0, &stat, &pubkey));
201201
if (stat != 1) {
202202
fprintf(stderr, "RSA rsa_verify_hash_ex + LTC_PKCS_1_V1_5_NA1 failed\n");
203203
return 1;
@@ -331,9 +331,9 @@ static int s_rsa_cryptx_issue_69(void)
331331
l1 = sizeof(buf1);
332332
DO(radix_to_bin(sig1, 16, buf0, &l0));
333333
DO(radix_to_bin(hash, 16, buf1, &l1));
334-
SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, &stat, &key));
334+
SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, 0, &stat, &key));
335335
DO(radix_to_bin(sig2, 16, buf0, &l0));
336-
SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, &stat, &key));
336+
SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, 0, &stat, &key));
337337
rsa_free(&key);
338338
return CRYPT_OK;
339339
}
@@ -684,11 +684,11 @@ print_hex("q", tmp, len);
684684

685685
/* sign a message with PKCS #1 v1.5 */
686686
len = sizeof(out);
687-
DO(rsa_sign_hash_ex(in, 20, out, &len, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 8, &privKey));
688-
DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 8, &stat, &pubKey));
687+
DO(rsa_sign_hash_ex(in, 20, out, &len, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 0, 8, &privKey));
688+
DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 0, 8, &stat, &pubKey));
689689
/* change a byte */
690690
in[0] ^= 1;
691-
DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 8, &stat2, &pubKey));
691+
DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 0, 8, &stat2, &pubKey));
692692

693693
if (!(stat == 1 && stat2 == 0)) {
694694
fprintf(stderr, "rsa_verify_hash_ex failed, %d, %d", stat, stat2);
@@ -721,9 +721,9 @@ print_hex("q", tmp, len);
721721
len = sizeof(in);
722722
len2 = sizeof(out);
723723
/* (1) */
724-
DO(rsa_sign_hash_ex(p, 20, p2, &len2, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 8, &privKey));
724+
DO(rsa_sign_hash_ex(p, 20, p2, &len2, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 0, 8, &privKey));
725725
/* (2) */
726-
DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey), "should succeed");
726+
DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, 0, -1, &stat, &pubKey), "should succeed");
727727
DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should succeed");
728728
len3 = sizeof(tmp);
729729
/* (3) */
@@ -757,7 +757,7 @@ print_hex("q", tmp, len);
757757

758758
len3 = sizeof(tmp);
759759
/* (6) */
760-
SHOULD_FAIL(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey));
760+
SHOULD_FAIL(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, -1, &stat, &pubKey));
761761
DOX(stat == 0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should fail");
762762
}
763763
rsa_free(&key);

0 commit comments

Comments
 (0)