Path: blob/master/libs/tomcrypt/src/pk/rsa/rsa_verify_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_verify_hash.c12RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange13*/1415#ifdef LTC_MRSA1617/**18PKCS #1 de-sign then v1.5 or PSS depad19@param sig The signature data20@param siglen The length of the signature data (octets)21@param hash The hash of the message that was signed22@param hashlen The length of the hash of the message that was signed (octets)23@param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1)24@param hash_idx The index of the desired hash25@param saltlen The length of the salt used during signature26@param stat [out] The result of the signature comparison, 1==valid, 0==invalid27@param key The public RSA key corresponding to the key that performed the signature28@return CRYPT_OK on success (even if the signature is invalid)29*/30int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,31const unsigned char *hash, unsigned long hashlen,32int padding,33int hash_idx, unsigned long saltlen,34int *stat, rsa_key *key)35{36unsigned long modulus_bitlen, modulus_bytelen, x;37int err;38unsigned char *tmpbuf;3940LTC_ARGCHK(hash != NULL);41LTC_ARGCHK(sig != NULL);42LTC_ARGCHK(stat != NULL);43LTC_ARGCHK(key != NULL);4445/* default to invalid */46*stat = 0;4748/* valid padding? */4950if ((padding != LTC_PKCS_1_V1_5) &&51(padding != LTC_PKCS_1_PSS) &&52(padding != LTC_PKCS_1_V1_5_NA1)) {53return CRYPT_PK_INVALID_PADDING;54}5556if (padding != LTC_PKCS_1_V1_5_NA1) {57/* valid hash ? */58if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {59return err;60}61}6263/* get modulus len in bits */64modulus_bitlen = mp_count_bits( (key->N));6566/* outlen must be at least the size of the modulus */67modulus_bytelen = mp_unsigned_bin_size( (key->N));68if (modulus_bytelen != siglen) {69return CRYPT_INVALID_PACKET;70}7172/* allocate temp buffer for decoded sig */73tmpbuf = XMALLOC(siglen);74if (tmpbuf == NULL) {75return CRYPT_MEM;76}7778/* RSA decode it */79x = siglen;80if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {81XFREE(tmpbuf);82return err;83}8485/* make sure the output is the right size */86if (x != siglen) {87XFREE(tmpbuf);88return CRYPT_INVALID_PACKET;89}9091if (padding == LTC_PKCS_1_PSS) {92/* PSS decode and verify it */9394if(modulus_bitlen%8 == 1){95err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat);96}97else{98err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);99}100101} else {102/* PKCS #1 v1.5 decode it */103unsigned char *out;104unsigned long outlen;105int decoded;106107/* allocate temp buffer for decoded hash */108outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3;109out = XMALLOC(outlen);110if (out == NULL) {111err = CRYPT_MEM;112goto bail_2;113}114115if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) {116XFREE(out);117goto bail_2;118}119120if (padding == LTC_PKCS_1_V1_5) {121unsigned long loid[16], reallen;122ltc_asn1_list digestinfo[2], siginfo[2];123124/* not all hashes have OIDs... so sad */125if (hash_descriptor[hash_idx].OIDlen == 0) {126err = CRYPT_INVALID_ARG;127goto bail_2;128}129130/* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */131/* construct the SEQUENCE132SEQUENCE {133SEQUENCE {hashoid OID134blah NULL135}136hash OCTET STRING137}138*/139LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0]));140LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);141LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);142LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);143144if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {145/* fallback to Legacy:missing NULL */146LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1);147if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {148XFREE(out);149goto bail_2;150}151}152153if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) {154XFREE(out);155goto bail_2;156}157158/* test OID */159if ((reallen == outlen) &&160(digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) &&161(XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) &&162(siginfo[1].size == hashlen) &&163(XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) {164*stat = 1;165}166} else {167/* only check if the hash is equal */168if ((hashlen == outlen) &&169(XMEMCMP(out, hash, hashlen) == 0)) {170*stat = 1;171}172}173174#ifdef LTC_CLEAN_STACK175zeromem(out, outlen);176#endif177XFREE(out);178}179180bail_2:181#ifdef LTC_CLEAN_STACK182zeromem(tmpbuf, siglen);183#endif184XFREE(tmpbuf);185return err;186}187188#endif /* LTC_MRSA */189190191