Path: blob/master/libs/tomcrypt/src/pk/rsa/rsa_sign_hash.c
4396 views
/* LibTomCrypt, modular cryptographic library -- Tom St Denis1*2* LibTomCrypt is a library that provides various cryptographic3* algorithms in a highly modular and flexible manner.4*5* The library is free for all purposes without any express6* guarantee it works.7*/8#include "tomcrypt.h"910/**11@file rsa_sign_hash.c12RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange13*/1415#ifdef LTC_MRSA1617/**18PKCS #1 pad then sign19@param in The hash to sign20@param inlen The length of the hash to sign (octets)21@param out [out] The signature22@param outlen [in/out] The max size and resulting size of the signature23@param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1)24@param prng An active PRNG state25@param prng_idx The index of the PRNG desired26@param hash_idx The index of the hash desired27@param saltlen The length of the salt desired (octets)28@param key The private RSA key to use29@return CRYPT_OK if successful30*/31int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,32unsigned char *out, unsigned long *outlen,33int padding,34prng_state *prng, int prng_idx,35int hash_idx, unsigned long saltlen,36rsa_key *key)37{38unsigned long modulus_bitlen, modulus_bytelen, x, y;39int err;4041LTC_ARGCHK(in != NULL);42LTC_ARGCHK(out != NULL);43LTC_ARGCHK(outlen != NULL);44LTC_ARGCHK(key != NULL);4546/* valid padding? */47if ((padding != LTC_PKCS_1_V1_5) &&48(padding != LTC_PKCS_1_PSS) &&49(padding != LTC_PKCS_1_V1_5_NA1)) {50return CRYPT_PK_INVALID_PADDING;51}5253if (padding == LTC_PKCS_1_PSS) {54/* valid prng ? */55if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {56return err;57}58}5960if (padding != LTC_PKCS_1_V1_5_NA1) {61/* valid hash ? */62if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {63return err;64}65}6667/* get modulus len in bits */68modulus_bitlen = mp_count_bits((key->N));6970/* outlen must be at least the size of the modulus */71modulus_bytelen = mp_unsigned_bin_size((key->N));72if (modulus_bytelen > *outlen) {73*outlen = modulus_bytelen;74return CRYPT_BUFFER_OVERFLOW;75}7677if (padding == LTC_PKCS_1_PSS) {78/* PSS pad the key */79x = *outlen;80if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx,81hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) {82return err;83}84} else {85/* PKCS #1 v1.5 pad the hash */86unsigned char *tmpin;8788if (padding == LTC_PKCS_1_V1_5) {89ltc_asn1_list digestinfo[2], siginfo[2];90/* not all hashes have OIDs... so sad */91if (hash_descriptor[hash_idx].OIDlen == 0) {92return CRYPT_INVALID_ARG;93}9495/* construct the SEQUENCE96SEQUENCE {97SEQUENCE {hashoid OID98blah NULL99}100hash OCTET STRING101}102*/103LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen);104LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);105LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);106LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen);107108/* allocate memory for the encoding */109y = mp_unsigned_bin_size(key->N);110tmpin = XMALLOC(y);111if (tmpin == NULL) {112return CRYPT_MEM;113}114115if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) {116XFREE(tmpin);117return err;118}119} else {120/* set the pointer and data-length to the input values */121tmpin = (unsigned char *)in;122y = inlen;123}124125x = *outlen;126err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x);127128if (padding == LTC_PKCS_1_V1_5) {129XFREE(tmpin);130}131132if (err != CRYPT_OK) {133return err;134}135}136137/* RSA encode it */138return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key);139}140141#endif /* LTC_MRSA */142143144