Skip to content

Commit

Permalink
add possibility to use different hash algorithms in RSAES-OAEP
Browse files Browse the repository at this point in the history
The hash algorithms used in the MGF and to create the hash of the Label
must not forcibly be the same. This change allows to use different
algorithms.

Unfortunately this breaks API if you use `rsa_decrypt_key_ex()`.
The `rsa_decrypt_key()` macro is still the same.

Signed-off-by: Steffen Jaeckel <[email protected]>
  • Loading branch information
sjaeckel committed Mar 11, 2023
1 parent 3474ca3 commit 067c5e2
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 20 deletions.
5 changes: 3 additions & 2 deletions src/headers/tomcrypt_pk.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void rsa_free(rsa_key *key);
rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, LTC_PKCS_1_OAEP, key)

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

#define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \
rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key)
Expand All @@ -82,7 +82,8 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
const unsigned char *lparam, unsigned long lparamlen,
int hash_idx, int padding,
int mgf_hash, int lparam_hash,
int padding,
int *stat, const rsa_key *key);

int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
Expand Down
3 changes: 2 additions & 1 deletion src/headers/tomcrypt_pkcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,

int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
const unsigned char *lparam, unsigned long lparamlen,
unsigned long modulus_bitlen, int hash_idx,
unsigned long modulus_bitlen,
int mgf_hash, int lparam_hash,
unsigned char *out, unsigned long *outlen,
int *res);

Expand Down
28 changes: 19 additions & 9 deletions src/pk/pkcs1/pkcs_1_oaep_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@
@param lparam The session or system data (can be NULL)
@param lparamlen The length of the lparam
@param modulus_bitlen The bit length of the RSA modulus
@param hash_idx The index of the hash desired
@param mgf_hash The hash algorithm used for the MGF
@param lparam_hash The hash algorithm used when hashing the lparam (can be -1)
@param out [out] Destination of decoding
@param outlen [in/out] The max size and resulting size of the decoding
@param res [out] Result of decoding, 1==valid, 0==invalid
@return CRYPT_OK if successful
*/
int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
const unsigned char *lparam, unsigned long lparamlen,
unsigned long modulus_bitlen, int hash_idx,
unsigned long modulus_bitlen,
int mgf_hash, int lparam_hash,
unsigned char *out, unsigned long *outlen,
int *res)
{
unsigned char *DB, *seed, *mask;
unsigned long hLen, x, y, modulus_len;
int err, ret;
int err, ret, lparam_hash_;

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

/* test valid hash */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
return err;
}
hLen = hash_descriptor[hash_idx].hashsize;
if (lparam_hash != -1) {
if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) {
return err;
}
lparam_hash_ = lparam_hash;
} else {
lparam_hash_ = mgf_hash;
}
hLen = hash_descriptor[mgf_hash].hashsize;
modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);

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

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

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

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

Expand All @@ -118,12 +128,12 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
/* compute lhash and store it in seed [reuse temps!] */
x = modulus_len;
if (lparam != NULL) {
if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
if ((err = hash_memory(lparam_hash_, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
} else {
/* can't pass hash_memory a NULL so use DB with zero length */
if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) {
if ((err = hash_memory(lparam_hash_, DB, 0, seed, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/pk/rsa/rsa_decrypt_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
@param outlen [in/out] The max size and resulting size of the plaintext (octets)
@param lparam The system "lparam" value
@param lparamlen The length of the lparam value (octets)
@param hash_idx The index of the hash desired
@param mgf_hash The hash algorithm used for the MGF
@param lparam_hash The hash algorithm used when hashing the lparam (can be -1)
@param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5)
@param stat [out] Result of the decryption, 1==valid, 0==invalid
@param key The corresponding private RSA key
Expand All @@ -26,7 +27,8 @@
int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
const unsigned char *lparam, unsigned long lparamlen,
int hash_idx, int padding,
int mgf_hash, int lparam_hash,
int padding,
int *stat, const rsa_key *key)
{
unsigned long modulus_bitlen, modulus_bytelen, x;
Expand All @@ -50,7 +52,7 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen

if (padding == LTC_PKCS_1_OAEP) {
/* valid hash ? */
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
return err;
}
}
Expand Down Expand Up @@ -79,8 +81,8 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen

if (padding == LTC_PKCS_1_OAEP) {
/* now OAEP decode the packet */
err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx,
out, outlen, stat);
err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, mgf_hash,
lparam_hash, out, outlen, stat);
} else {
/* now PKCS #1 v1.5 depad the packet */
err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);
Expand Down
2 changes: 1 addition & 1 deletion tests/pkcs_1_eme_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int pkcs_1_eme_test(void)
prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, (void*)no_prng_desc);
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);
COMPARE_TESTVECTOR(obuf, obuflen, s->o3, s->o3_l,s->name, j);
DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, LTC_PKCS_1_V1_5, &stat, key), s->name);
DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, -1, LTC_PKCS_1_V1_5, &stat, key), s->name);
DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
} /* for */

Expand Down
2 changes: 1 addition & 1 deletion tests/pkcs_1_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ int pkcs_1_test(void)

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

if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) {
fprintf(stderr, "Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen);
Expand Down
2 changes: 1 addition & 1 deletion tests/rsa_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ print_hex("q", tmp, len);
DO(rsa_encrypt_key_ex(in, rsa_msgsize, out, &len, NULL, 0, &yarrow_prng, prng_idx, 0, LTC_PKCS_1_V1_5, &key));

len2 = rsa_msgsize;
DO(rsa_decrypt_key_ex(out, len, tmp, &len2, NULL, 0, 0, LTC_PKCS_1_V1_5, &stat, &key));
DO(rsa_decrypt_key_ex(out, len, tmp, &len2, NULL, 0, 0, -1, LTC_PKCS_1_V1_5, &stat, &key));
ENSURE(stat == 1);
DO(do_compare_testvector(tmp, len2, in, rsa_msgsize, "rsa_decrypt_key_ex", rsa_msgsize));
}
Expand Down

0 comments on commit 067c5e2

Please sign in to comment.