1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner. 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works. 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h" 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @file rsa_verify_hash.c 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef MRSA 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PKCS #1 de-sign then v1.5 or PSS depad 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param sig The signature data 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param siglen The length of the signature data (octets) 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param hash The hash of the message that was signed 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param hashlen The length of the hash of the message that was signed (octets) 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param padding Type of padding (LTC_PKCS_1_PSS or LTC_PKCS_1_V1_5) 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param hash_idx The index of the desired hash 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param saltlen The length of the salt used during signature 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param stat [out] The result of the signature comparison, 1==valid, 0==invalid 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param key The public RSA key corresponding to the key that performed the signature 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK on success (even if the signature is invalid) 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const unsigned char *hash, unsigned long hashlen, 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int padding, 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int hash_idx, unsigned long saltlen, 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int *stat, rsa_key *key) 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long modulus_bitlen, modulus_bytelen, x; 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int err; 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *tmpbuf; 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(hash != NULL); 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(sig != NULL); 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(stat != NULL); 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(key != NULL); 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* default to invalid */ 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *stat = 0; 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* valid padding? */ 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((padding != LTC_PKCS_1_V1_5) && 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (padding != LTC_PKCS_1_PSS)) { 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_PK_INVALID_PADDING; 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (padding == LTC_PKCS_1_PSS) { 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* valid hash ? */ 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* get modulus len in bits */ 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project modulus_bitlen = mp_count_bits( (key->N)); 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* outlen must be at least the size of the modulus */ 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project modulus_bytelen = mp_unsigned_bin_size( (key->N)); 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (modulus_bytelen != siglen) { 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_PACKET; 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* allocate temp buffer for decoded sig */ 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tmpbuf = XMALLOC(siglen); 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (tmpbuf == NULL) { 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_MEM; 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* RSA decode it */ 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = siglen; 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(tmpbuf); 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* make sure the output is the right size */ 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (x != siglen) { 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(tmpbuf); 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_PACKET; 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (padding == LTC_PKCS_1_PSS) { 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* PSS decode and verify it */ 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* PKCS #1 v1.5 decode it */ 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *out; 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long outlen, loid[16]; 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int decoded; 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ltc_asn1_list digestinfo[2], siginfo[2]; 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* not all hashes have OIDs... so sad */ 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (hash_descriptor[hash_idx].OIDlen == 0) { 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_INVALID_ARG; 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto bail_2; 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* allocate temp buffer for decoded hash */ 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3; 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project out = XMALLOC(outlen); 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (out == NULL) { 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_MEM; 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto bail_2; 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) { 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(out); 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto bail_2; 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */ 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* construct the SEQUENCE 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project SEQUENCE { 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project SEQUENCE {hashoid OID 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project blah NULL 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hash OCTET STRING 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0])); 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen); 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) { 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(out); 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto bail_2; 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* test OID */ 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) && 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) && 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (siginfo[1].size == hashlen) && 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) { 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *stat = 1; 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(out, outlen); 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(out); 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectbail_2: 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(tmpbuf, siglen); 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(tmpbuf); 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* MRSA */ 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_verify_hash.c,v $ */ 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.11 $ */ 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/12/04 03:09:28 $ */ 168