diff options
Diffstat (limited to 'libtomcrypt/src/pk/rsa/rsa_sign_hash.c')
-rw-r--r-- | libtomcrypt/src/pk/rsa/rsa_sign_hash.c | 129 |
1 files changed, 92 insertions, 37 deletions
diff --git a/libtomcrypt/src/pk/rsa/rsa_sign_hash.c b/libtomcrypt/src/pk/rsa/rsa_sign_hash.c index d31bda3..f10a97a 100644 --- a/libtomcrypt/src/pk/rsa/rsa_sign_hash.c +++ b/libtomcrypt/src/pk/rsa/rsa_sign_hash.c @@ -6,23 +6,24 @@ * The library is free for all purposes without any express * guarantee it works. * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com */ #include "tomcrypt.h" /** @file rsa_sign_hash.c - RSA PKCS v2 PSS sign hash, Tom St Denis -*/ + RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange +*/ #ifdef MRSA /** - (PKCS #1, v2.0) PSS pad then sign + PKCS #1 pad then sign @param in The hash to sign @param inlen The length of the hash to sign (octets) @param out [out] The signature - @param outlen [in/out] The max size and resulting size of the signature + @param outlen [in/out] The max size and resulting size of the signature + @param padding Type of padding (LTC_PKCS_1_PSS or LTC_PKCS_1_V1_5) @param prng An active PRNG state @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @@ -30,50 +31,104 @@ @param key The private RSA key to use @return CRYPT_OK if successful */ -int rsa_sign_hash(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int prng_idx, - int hash_idx, unsigned long saltlen, - rsa_key *key) +int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int padding, + prng_state *prng, int prng_idx, + int hash_idx, unsigned long saltlen, + rsa_key *key) { - unsigned long modulus_bitlen, modulus_bytelen, x; + unsigned long modulus_bitlen, modulus_bytelen, x, y; int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* valid prng and hash ? */ - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { - return err; - } - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - /* get modulus len in bits */ - modulus_bitlen = mp_count_bits(&(key->N)); + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* valid padding? */ + if ((padding != LTC_PKCS_1_V1_5) && (padding != LTC_PKCS_1_PSS)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == LTC_PKCS_1_PSS) { + /* valid prng and hash ? */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits((key->N)); /* outlen must be at least the size of the modulus */ - modulus_bytelen = mp_unsigned_bin_size(&(key->N)); + modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen > *outlen) { + *outlen = modulus_bytelen; return CRYPT_BUFFER_OVERFLOW; } - - /* PSS pad the key */ - x = *outlen; - if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, - hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { - return err; + + if (padding == LTC_PKCS_1_PSS) { + /* PSS pad the key */ + x = *outlen; + if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, + hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { + return err; + } + } else { + /* PKCS #1 v1.5 pad the hash */ + unsigned char *tmpin; + ltc_asn1_list digestinfo[2], siginfo[2]; + + /* not all hashes have OIDs... so sad */ + if (hash_descriptor[hash_idx].OIDlen == 0) { + return CRYPT_INVALID_ARG; + } + + /* construct the SEQUENCE + SEQUENCE { + SEQUENCE {hashoid OID + blah NULL + } + hash OCTET STRING + } + */ + LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen); + LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); + LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); + + /* allocate memory for the encoding */ + y = mp_unsigned_bin_size(key->N); + tmpin = XMALLOC(y); + if (tmpin == NULL) { + return CRYPT_MEM; + } + + if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { + XFREE(tmpin); + return err; + } + + x = *outlen; + if ((err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, + modulus_bitlen, NULL, 0, + out, &x)) != CRYPT_OK) { + XFREE(tmpin); + return err; + } + XFREE(tmpin); } /* RSA encode it */ - return rsa_exptmod(out, x, out, outlen, PK_PRIVATE, key); + return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); } #endif /* MRSA */ /* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_sign_hash.c,v $ */ -/* $Revision: 1.3 $ */ -/* $Date: 2005/05/05 14:35:59 $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/11/09 23:15:39 $ */ |