Skip to content

Commit 7e863d2

Browse files
authored
Merge pull request #612 from libtom/rsaaes_oaep_hashes
add possibility to use different hash algorithms in RSAES-OAEP
2 parents 91b7bbe + 63091c9 commit 7e863d2

File tree

10 files changed

+137
-87
lines changed

10 files changed

+137
-87
lines changed

doc/crypt.tex

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4190,7 +4190,8 @@ \subsection{OAEP Encoding}
41904190
unsigned long modulus_bitlen,
41914191
prng_state *prng,
41924192
int prng_idx,
4193-
int hash_idx,
4193+
int mgf_hash,
4194+
int lparam_hash,
41944195
unsigned char *out,
41954196
unsigned long *outlen);
41964197
\end{alltt}
@@ -4200,7 +4201,9 @@ \subsection{OAEP Encoding}
42004201
\textit{lparam} can be set to \textbf{NULL}.
42014202

42024203
OAEP encoding requires the length of the modulus in bits in order to calculate the size of the output. This is passed as the parameter
4203-
\textit{modulus\_bitlen}. \textit{hash\_idx} is the index into the hash descriptor table of the hash desired. PKCS \#1 allows any hash to be
4204+
\textit{modulus\_bitlen}. \textit{mgf\_hash} is the index into the hash descriptor table of the hash desired for the mask generation function (MGF).
4205+
\textit{lparam\_hash} is the index into the hash descriptor table of the hash desired for the \textit{lparam}. This value can also be set to $-1$
4206+
to indicate usage of the same algorithm than for the MGF. PKCS \#1 allows any hash to be
42044207
used but both the encoder and decoder must use the same hash in order for this to succeed. The size of hash output affects the maximum
42054208
sized input message. \textit{prng\_idx} and \textit{prng} are the random number generator arguments required to randomize the padding process.
42064209
The padded message is stored in \textit{out} along with the length in \textit{outlen}.
@@ -4221,7 +4224,8 @@ \subsection{OAEP Decoding}
42214224
const unsigned char *lparam,
42224225
unsigned long lparamlen,
42234226
unsigned long modulus_bitlen,
4224-
int hash_idx,
4227+
int mgf_hash,
4228+
int lparam_hash,
42254229
unsigned char *out,
42264230
unsigned long *outlen,
42274231
int *res);
@@ -4230,8 +4234,8 @@ \subsection{OAEP Decoding}
42304234
This function decodes an OAEP encoded message and outputs the original message that was passed to the OAEP encoder. \textit{msg} is the
42314235
output of pkcs\_1\_oaep\_encode() of length \textit{msglen}. \textit{lparam} is the same system variable passed to the OAEP encoder. If it does not
42324236
match what was used during encoding this function will not decode the packet. \textit{modulus\_bitlen} is the size of the RSA modulus in bits
4233-
and must match what was used during encoding. Similarly the \textit{hash\_idx} index into the hash descriptor table must match what was used
4234-
during encoding.
4237+
and must match what was used during encoding. Similarly the \textit{mgf\_hash} and \textit{lparam\_hash} indexes into the hash descriptor table must
4238+
match what was used during encoding.
42354239

42364240
If the function succeeds it decodes the OAEP encoded message into \textit{out} of length \textit{outlen} and stores a
42374241
$1$ in \textit{res}. If the packet is invalid it stores $0$ in \textit{res} and if the function fails for another reason
@@ -4426,7 +4430,8 @@ \subsection{Extended Encryption}
44264430
unsigned long lparamlen,
44274431
prng_state *prng,
44284432
int prng_idx,
4429-
int hash_idx,
4433+
int mgf_hash,
4434+
int lparam_hash,
44304435
int padding,
44314436
rsa_key *key);
44324437
\end{verbatim}
@@ -4447,7 +4452,8 @@ \subsection{Extended Encryption}
44474452
unsigned long *outlen,
44484453
const unsigned char *lparam,
44494454
unsigned long lparamlen,
4450-
int hash_idx,
4455+
int mgf_hash,
4456+
int lparam_hash,
44514457
int *stat,
44524458
rsa_key *key);
44534459
\end{verbatim}

src/headers/tomcrypt_pk.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ void rsa_free(rsa_key *key);
5757

5858
/* These use PKCS #1 v2.0 padding */
5959
#define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \
60-
rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, LTC_PKCS_1_OAEP, key)
60+
rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, -1, LTC_PKCS_1_OAEP, key)
6161

6262
#define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \
63-
rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, LTC_PKCS_1_OAEP, stat, key)
63+
rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key)
6464

6565
#define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \
6666
rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key)
@@ -76,13 +76,15 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
7676
unsigned char *out, unsigned long *outlen,
7777
const unsigned char *lparam, unsigned long lparamlen,
7878
prng_state *prng, int prng_idx,
79-
int hash_idx, int padding,
79+
int mgf_hash, int lparam_hash,
80+
int padding,
8081
const rsa_key *key);
8182

8283
int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
8384
unsigned char *out, unsigned long *outlen,
8485
const unsigned char *lparam, unsigned long lparamlen,
85-
int hash_idx, int padding,
86+
int mgf_hash, int lparam_hash,
87+
int padding,
8688
int *stat, const rsa_key *key);
8789

8890
int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,

src/headers/tomcrypt_pkcs.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,14 @@ int pkcs_1_v1_5_decode(const unsigned char *msg,
4949
int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
5050
const unsigned char *lparam, unsigned long lparamlen,
5151
unsigned long modulus_bitlen, prng_state *prng,
52-
int prng_idx, int hash_idx,
52+
int prng_idx,
53+
int mgf_hash, int lparam_hash,
5354
unsigned char *out, unsigned long *outlen);
5455

5556
int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
5657
const unsigned char *lparam, unsigned long lparamlen,
57-
unsigned long modulus_bitlen, int hash_idx,
58+
unsigned long modulus_bitlen,
59+
int mgf_hash, int lparam_hash,
5860
unsigned char *out, unsigned long *outlen,
5961
int *res);
6062

src/pk/pkcs1/pkcs_1_oaep_decode.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,23 @@
1616
@param lparam The session or system data (can be NULL)
1717
@param lparamlen The length of the lparam
1818
@param modulus_bitlen The bit length of the RSA modulus
19-
@param hash_idx The index of the hash desired
19+
@param mgf_hash The hash algorithm used for the MGF
20+
@param lparam_hash The hash algorithm used when hashing the lparam (can be -1)
2021
@param out [out] Destination of decoding
2122
@param outlen [in/out] The max size and resulting size of the decoding
2223
@param res [out] Result of decoding, 1==valid, 0==invalid
2324
@return CRYPT_OK if successful
2425
*/
2526
int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
2627
const unsigned char *lparam, unsigned long lparamlen,
27-
unsigned long modulus_bitlen, int hash_idx,
28+
unsigned long modulus_bitlen,
29+
int mgf_hash, int lparam_hash,
2830
unsigned char *out, unsigned long *outlen,
2931
int *res)
3032
{
3133
unsigned char *DB, *seed, *mask;
3234
unsigned long hLen, x, y, modulus_len;
33-
int err, ret;
35+
int err, ret, lparam_hash_used;
3436

3537
LTC_ARGCHK(msg != NULL);
3638
LTC_ARGCHK(out != NULL);
@@ -41,10 +43,18 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
4143
*res = 0;
4244

4345
/* test valid hash */
44-
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
46+
if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
4547
return err;
4648
}
47-
hLen = hash_descriptor[hash_idx].hashsize;
49+
if (lparam_hash != -1) {
50+
if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) {
51+
return err;
52+
}
53+
lparam_hash_used = lparam_hash;
54+
} else {
55+
lparam_hash_used = mgf_hash;
56+
}
57+
hLen = hash_descriptor[lparam_hash_used].hashsize;
4858
modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
4959

5060
/* test hash/message size */
@@ -94,7 +104,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
94104
x += modulus_len - hLen - 1;
95105

96106
/* compute MGF1 of maskedDB (hLen) */
97-
if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
107+
if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
98108
goto LBL_ERR;
99109
}
100110

@@ -104,7 +114,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
104114
}
105115

106116
/* compute MGF1 of seed (k - hlen - 1) */
107-
if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
117+
if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
108118
goto LBL_ERR;
109119
}
110120

@@ -118,12 +128,12 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
118128
/* compute lhash and store it in seed [reuse temps!] */
119129
x = modulus_len;
120130
if (lparam != NULL) {
121-
if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
131+
if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
122132
goto LBL_ERR;
123133
}
124134
} else {
125135
/* can't pass hash_memory a NULL so use DB with zero length */
126-
if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) {
136+
if ((err = hash_memory(lparam_hash_used, DB, 0, seed, &x)) != CRYPT_OK) {
127137
goto LBL_ERR;
128138
}
129139
}

src/pk/pkcs1/pkcs_1_oaep_encode.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,37 @@
2626
int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
2727
const unsigned char *lparam, unsigned long lparamlen,
2828
unsigned long modulus_bitlen, prng_state *prng,
29-
int prng_idx, int hash_idx,
29+
int prng_idx,
30+
int mgf_hash, int lparam_hash,
3031
unsigned char *out, unsigned long *outlen)
3132
{
3233
unsigned char *DB, *seed, *mask;
3334
unsigned long hLen, x, y, modulus_len;
34-
int err;
35+
int err, lparam_hash_used;
3536

3637
LTC_ARGCHK((msglen == 0) || (msg != NULL));
3738
LTC_ARGCHK(out != NULL);
3839
LTC_ARGCHK(outlen != NULL);
3940

4041
/* test valid hash */
41-
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
42+
if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
4243
return err;
4344
}
45+
if (lparam_hash != -1) {
46+
if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) {
47+
return err;
48+
}
49+
lparam_hash_used = lparam_hash;
50+
} else {
51+
lparam_hash_used = mgf_hash;
52+
}
4453

4554
/* valid prng */
4655
if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
4756
return err;
4857
}
4958

50-
hLen = hash_descriptor[hash_idx].hashsize;
59+
hLen = hash_descriptor[lparam_hash_used].hashsize;
5160
modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
5261

5362
/* test message size */
@@ -76,12 +85,12 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
7685
/* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
7786
x = modulus_len;
7887
if (lparam != NULL) {
79-
if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
88+
if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
8089
goto LBL_ERR;
8190
}
8291
} else {
8392
/* can't pass hash_memory a NULL so use DB with zero length */
84-
if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) {
93+
if ((err = hash_memory(lparam_hash_used, DB, 0, DB, &x)) != CRYPT_OK) {
8594
goto LBL_ERR;
8695
}
8796
}
@@ -108,7 +117,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
108117
}
109118

110119
/* compute MGF1 of seed (k - hlen - 1) */
111-
if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
120+
if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
112121
goto LBL_ERR;
113122
}
114123

@@ -118,7 +127,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
118127
}
119128

120129
/* compute MGF1 of maskedDB (hLen) */
121-
if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
130+
if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
122131
goto LBL_ERR;
123132
}
124133

src/pk/rsa/rsa_decrypt_key.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
@param outlen [in/out] The max size and resulting size of the plaintext (octets)
1818
@param lparam The system "lparam" value
1919
@param lparamlen The length of the lparam value (octets)
20-
@param hash_idx The index of the hash desired
20+
@param mgf_hash The hash algorithm used for the MGF
21+
@param lparam_hash The hash algorithm used when hashing the lparam (can be -1)
2122
@param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5)
2223
@param stat [out] Result of the decryption, 1==valid, 0==invalid
2324
@param key The corresponding private RSA key
@@ -26,7 +27,8 @@
2627
int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
2728
unsigned char *out, unsigned long *outlen,
2829
const unsigned char *lparam, unsigned long lparamlen,
29-
int hash_idx, int padding,
30+
int mgf_hash, int lparam_hash,
31+
int padding,
3032
int *stat, const rsa_key *key)
3133
{
3234
unsigned long modulus_bitlen, modulus_bytelen, x;
@@ -43,15 +45,14 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen
4345
*stat = 0;
4446

4547
/* valid padding? */
46-
4748
if ((padding != LTC_PKCS_1_V1_5) &&
4849
(padding != LTC_PKCS_1_OAEP)) {
4950
return CRYPT_PK_INVALID_PADDING;
5051
}
5152

5253
if (padding == LTC_PKCS_1_OAEP) {
5354
/* valid hash ? */
54-
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
55+
if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
5556
return err;
5657
}
5758
}
@@ -80,8 +81,8 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen
8081

8182
if (padding == LTC_PKCS_1_OAEP) {
8283
/* now OAEP decode the packet */
83-
err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx,
84-
out, outlen, stat);
84+
err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, mgf_hash,
85+
lparam_hash, out, outlen, stat);
8586
} else {
8687
/* now PKCS #1 v1.5 depad the packet */
8788
err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);

src/pk/rsa/rsa_encrypt_key.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
2828
unsigned char *out, unsigned long *outlen,
2929
const unsigned char *lparam, unsigned long lparamlen,
3030
prng_state *prng, int prng_idx,
31-
int hash_idx, int padding,
31+
int mgf_hash, int lparam_hash,
32+
int padding,
3233
const rsa_key *key)
3334
{
3435
unsigned long modulus_bitlen, modulus_bytelen, x;
@@ -52,7 +53,7 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
5253

5354
if (padding == LTC_PKCS_1_OAEP) {
5455
/* valid hash? */
55-
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
56+
if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
5657
return err;
5758
}
5859
}
@@ -71,8 +72,8 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
7172
/* OAEP pad the key */
7273
x = *outlen;
7374
if ((err = pkcs_1_oaep_encode(in, inlen, lparam,
74-
lparamlen, modulus_bitlen, prng, prng_idx, hash_idx,
75-
out, &x)) != CRYPT_OK) {
75+
lparamlen, modulus_bitlen, prng, prng_idx, mgf_hash,
76+
lparam_hash, out, &x)) != CRYPT_OK) {
7677
return err;
7778
}
7879
} else {

tests/pkcs_1_eme_test.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ int pkcs_1_eme_test(void)
4343
unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf);
4444
int stat;
4545
prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, (void*)no_prng_desc);
46-
DOX(rsa_encrypt_key_ex(s->o1, s->o1_l, obuf, &obuflen, NULL, 0, (void*)no_prng_desc, prng_idx, -1, LTC_PKCS_1_V1_5, key), s->name);
46+
DOX(rsa_encrypt_key_ex(s->o1, s->o1_l, obuf, &obuflen, NULL, 0, (void*)no_prng_desc, prng_idx, -1, -1, LTC_PKCS_1_V1_5, key), s->name);
4747
COMPARE_TESTVECTOR(obuf, obuflen, s->o3, s->o3_l,s->name, j);
48-
DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, LTC_PKCS_1_V1_5, &stat, key), s->name);
48+
DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, -1, LTC_PKCS_1_V1_5, &stat, key), s->name);
4949
DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
5050
} /* for */
5151

tests/pkcs_1_test.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ int pkcs_1_test(void)
4646

4747
/* encode it */
4848
l1 = sizeof(buf[1]);
49-
DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &yarrow_prng, prng_idx, hash_idx, buf[1], &l1));
49+
DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &yarrow_prng, prng_idx, hash_idx, -1, buf[1], &l1));
5050

5151
/* decode it */
5252
l2 = sizeof(buf[2]);
53-
DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, buf[2], &l2, &res1));
53+
DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, -1, buf[2], &l2, &res1));
5454

5555
if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) {
5656
fprintf(stderr, "Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen);

0 commit comments

Comments
 (0)