1/* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 * 3 * LibTomCrypt is a library that provides various cryptographic 4 * algorithms in a highly modular and flexible manner. 5 * 6 * The library is free for all purposes without any express 7 * guarantee it works. 8 * 9 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com 10 */ 11#include "tomcrypt.h" 12 13/** 14 @file rsa_sign_hash.c 15 RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange 16*/ 17 18#ifdef MRSA 19 20/** 21 PKCS #1 pad then sign 22 @param in The hash to sign 23 @param inlen The length of the hash to sign (octets) 24 @param out [out] The signature 25 @param outlen [in/out] The max size and resulting size of the signature 26 @param padding Type of padding (LTC_PKCS_1_PSS or LTC_PKCS_1_V1_5) 27 @param prng An active PRNG state 28 @param prng_idx The index of the PRNG desired 29 @param hash_idx The index of the hash desired 30 @param saltlen The length of the salt desired (octets) 31 @param key The private RSA key to use 32 @return CRYPT_OK if successful 33*/ 34int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, 35 unsigned char *out, unsigned long *outlen, 36 int padding, 37 prng_state *prng, int prng_idx, 38 int hash_idx, unsigned long saltlen, 39 rsa_key *key) 40{ 41 unsigned long modulus_bitlen, modulus_bytelen, x, y; 42 int err; 43 44 LTC_ARGCHK(in != NULL); 45 LTC_ARGCHK(out != NULL); 46 LTC_ARGCHK(outlen != NULL); 47 LTC_ARGCHK(key != NULL); 48 49 /* valid padding? */ 50 if ((padding != LTC_PKCS_1_V1_5) && (padding != LTC_PKCS_1_PSS)) { 51 return CRYPT_PK_INVALID_PADDING; 52 } 53 54 if (padding == LTC_PKCS_1_PSS) { 55 /* valid prng and hash ? */ 56 if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { 57 return err; 58 } 59 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 60 return err; 61 } 62 } 63 64 /* get modulus len in bits */ 65 modulus_bitlen = mp_count_bits((key->N)); 66 67 /* outlen must be at least the size of the modulus */ 68 modulus_bytelen = mp_unsigned_bin_size((key->N)); 69 if (modulus_bytelen > *outlen) { 70 *outlen = modulus_bytelen; 71 return CRYPT_BUFFER_OVERFLOW; 72 } 73 74 if (padding == LTC_PKCS_1_PSS) { 75 /* PSS pad the key */ 76 x = *outlen; 77 if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, 78 hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { 79 return err; 80 } 81 } else { 82 /* PKCS #1 v1.5 pad the hash */ 83 unsigned char *tmpin; 84 ltc_asn1_list digestinfo[2], siginfo[2]; 85 86 /* not all hashes have OIDs... so sad */ 87 if (hash_descriptor[hash_idx].OIDlen == 0) { 88 return CRYPT_INVALID_ARG; 89 } 90 91 /* construct the SEQUENCE 92 SEQUENCE { 93 SEQUENCE {hashoid OID 94 blah NULL 95 } 96 hash OCTET STRING 97 } 98 */ 99 LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen); 100 LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); 101 LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); 102 LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); 103 104 /* allocate memory for the encoding */ 105 y = mp_unsigned_bin_size(key->N); 106 tmpin = XMALLOC(y); 107 if (tmpin == NULL) { 108 return CRYPT_MEM; 109 } 110 111 if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { 112 XFREE(tmpin); 113 return err; 114 } 115 116 x = *outlen; 117 if ((err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, 118 modulus_bitlen, NULL, 0, 119 out, &x)) != CRYPT_OK) { 120 XFREE(tmpin); 121 return err; 122 } 123 XFREE(tmpin); 124 } 125 126 /* RSA encode it */ 127 return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); 128} 129 130#endif /* MRSA */ 131 132/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_sign_hash.c,v $ */ 133/* $Revision: 1.9 $ */ 134/* $Date: 2006/11/09 23:15:39 $ */ 135