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 pkcs_1_pss_decode.c 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PKCS #1 PSS Signature Padding, Tom St Denis 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef PKCS_1 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PKCS #1 v2.00 PSS decode 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param msghash The hash to verify 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param msghashlen The length of the hash (octets) 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param sig The signature data (encoded data) 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param siglen The length of the signature data (octets) 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param saltlen The length of the salt used (octets) 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param hash_idx The index of the hash desired 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param modulus_bitlen The bit length of the RSA modulus 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param res [out] The result of the comparison, 1==valid, 0==invalid 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK if successful (even if the comparison failed) 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const unsigned char *sig, unsigned long siglen, 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long saltlen, int hash_idx, 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long modulus_bitlen, int *res) 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *DB, *mask, *salt, *hash; 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long x, y, hLen, modulus_len; 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int err; 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hash_state md; 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(msghash != NULL); 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(res != NULL); 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* default to invalid */ 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *res = 0; 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* ensure hash is valid */ 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hLen = hash_descriptor[hash_idx].hashsize; 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check sizes */ 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((saltlen > modulus_len) || 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) { 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_PK_INVALID_SIZE; 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* allocate ram for DB/mask/salt/hash of size modulus_len */ 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project DB = XMALLOC(modulus_len); 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mask = XMALLOC(modulus_len); 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project salt = XMALLOC(modulus_len); 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hash = XMALLOC(modulus_len); 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (DB != NULL) { 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(DB); 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mask != NULL) { 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(mask); 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (salt != NULL) { 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(salt); 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (hash != NULL) { 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(hash); 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_MEM; 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* ensure the 0xBC byte */ 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (sig[siglen-1] != 0xBC) { 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_INVALID_PACKET; 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* copy out the DB */ 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = 0; 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XMEMCPY(DB, sig + x, modulus_len - hLen - 1); 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x += modulus_len - hLen - 1; 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* copy out the hash */ 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XMEMCPY(hash, sig + x, hLen); 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x += hLen; 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check the MSB */ 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) { 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_INVALID_PACKET; 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* generate mask of length modulus_len - hLen - 1 from hash */ 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* xor against DB */ 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < (modulus_len - hLen - 1); y++) { 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project DB[y] ^= mask[y]; 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now clear the first byte [make sure smaller than modulus] */ 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check for zeroes and 0x01 */ 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (DB[x] != 0x00) { 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_INVALID_PACKET; 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check for the 0x01 */ 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (DB[x++] != 0x01) { 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_INVALID_PACKET; 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(mask, 8); 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* mask == hash means valid signature */ 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (XMEMCMP(mask, hash, hLen) == 0) { 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *res = 1; 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_OK; 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source ProjectLBL_ERR: 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(DB, modulus_len); 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(mask, modulus_len); 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(salt, modulus_len); 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(hash, modulus_len); 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(hash); 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(salt); 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(mask); 168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(DB); 169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* PKCS_1 */ 174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c,v $ */ 176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.9 $ */ 177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/11/30 02:37:21 $ */ 178