| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | /* LibTomCrypt, modular cryptographic library -- Tom St Denis
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * LibTomCrypt is a library that provides various cryptographic | 
					
						
							|  |  |  |  * algorithms in a highly modular and flexible manner. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The library is free for all purposes without any express | 
					
						
							|  |  |  |  * guarantee it works. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-20 17:48:02 +00:00
										 |  |  |  * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
 | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  | #include "tomcrypt.h"
 | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-03 15:16:59 +01:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |   @file pkcs_1_pss_decode.c | 
					
						
							| 
									
										
										
										
											2014-01-03 15:16:59 +01:00
										 |  |  |   PKCS #1 PSS Signature Padding, Tom St Denis | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-20 17:48:02 +00:00
										 |  |  | #ifdef LTC_PKCS_1
 | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-01-03 15:16:59 +01:00
										 |  |  |    PKCS #1 v2.00 PSS decode | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |    @param  msghash         The hash to verify | 
					
						
							|  |  |  |    @param  msghashlen      The length of the hash (octets) | 
					
						
							|  |  |  |    @param  sig             The signature data (encoded data) | 
					
						
							|  |  |  |    @param  siglen          The length of the signature data (octets) | 
					
						
							|  |  |  |    @param  saltlen         The length of the salt used (octets) | 
					
						
							|  |  |  |    @param  hash_idx        The index of the hash desired | 
					
						
							|  |  |  |    @param  modulus_bitlen  The bit length of the RSA modulus | 
					
						
							|  |  |  |    @param  res             [out] The result of the comparison, 1==valid, 0==invalid | 
					
						
							|  |  |  |    @return CRYPT_OK if successful (even if the comparison failed) | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, | 
					
						
							|  |  |  |                       const unsigned char *sig,     unsigned long siglen, | 
					
						
							|  |  |  |                             unsigned long saltlen,  int           hash_idx, | 
					
						
							|  |  |  |                             unsigned long modulus_bitlen, int    *res) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-06-20 02:41:49 +00:00
										 |  |  |    unsigned char *DB, *mask, *salt, *hash; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    unsigned long x, y, hLen, modulus_len; | 
					
						
							|  |  |  |    int           err; | 
					
						
							|  |  |  |    hash_state    md; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |    LTC_ARGCHK(msghash != NULL); | 
					
						
							|  |  |  |    LTC_ARGCHK(res     != NULL); | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* default to invalid */ | 
					
						
							|  |  |  |    *res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* ensure hash is valid */ | 
					
						
							|  |  |  |    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { | 
					
						
							|  |  |  |       return err; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    hLen        = hash_descriptor[hash_idx].hashsize; | 
					
						
							| 
									
										
										
										
											2008-01-20 22:45:58 -08:00
										 |  |  |    modulus_bitlen--; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-17 11:37:13 +00:00
										 |  |  |    /* check sizes */ | 
					
						
							| 
									
										
										
										
											2014-01-03 15:16:59 +01:00
										 |  |  |    if ((saltlen > modulus_len) || | 
					
						
							| 
									
										
										
										
											2008-01-20 22:45:58 -08:00
										 |  |  |        (modulus_len < hLen + saltlen + 2)) { | 
					
						
							| 
									
										
										
										
											2005-04-17 11:37:13 +00:00
										 |  |  |       return CRYPT_PK_INVALID_SIZE; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-20 02:41:49 +00:00
										 |  |  |    /* allocate ram for DB/mask/salt/hash of size modulus_len */ | 
					
						
							|  |  |  |    DB   = XMALLOC(modulus_len); | 
					
						
							|  |  |  |    mask = XMALLOC(modulus_len); | 
					
						
							|  |  |  |    salt = XMALLOC(modulus_len); | 
					
						
							|  |  |  |    hash = XMALLOC(modulus_len); | 
					
						
							|  |  |  |    if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { | 
					
						
							|  |  |  |       if (DB != NULL) { | 
					
						
							|  |  |  |          XFREE(DB); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (mask != NULL) { | 
					
						
							|  |  |  |          XFREE(mask); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (salt != NULL) { | 
					
						
							|  |  |  |          XFREE(salt); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (hash != NULL) { | 
					
						
							|  |  |  |          XFREE(hash); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return CRYPT_MEM; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    /* ensure the 0xBC byte */ | 
					
						
							|  |  |  |    if (sig[siglen-1] != 0xBC) { | 
					
						
							| 
									
										
										
										
											2006-12-16 18:10:04 +00:00
										 |  |  |       err = CRYPT_INVALID_PACKET; | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* copy out the DB */ | 
					
						
							| 
									
										
										
										
											2005-06-09 00:08:13 +00:00
										 |  |  |    x = 0; | 
					
						
							|  |  |  |    XMEMCPY(DB, sig + x, modulus_len - hLen - 1); | 
					
						
							|  |  |  |    x += modulus_len - hLen - 1; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* copy out the hash */ | 
					
						
							| 
									
										
										
										
											2005-06-09 00:08:13 +00:00
										 |  |  |    XMEMCPY(hash, sig + x, hLen); | 
					
						
							|  |  |  |    x += hLen; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-20 22:45:58 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    /* check the MSB */ | 
					
						
							| 
									
										
										
										
											2008-01-20 22:45:58 -08:00
										 |  |  |    if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen)))) != 0) { | 
					
						
							| 
									
										
										
										
											2006-12-16 18:10:04 +00:00
										 |  |  |       err = CRYPT_INVALID_PACKET; | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* generate mask of length modulus_len - hLen - 1 from hash */ | 
					
						
							| 
									
										
										
										
											2005-11-18 05:15:37 +00:00
										 |  |  |    if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* xor against DB */ | 
					
						
							|  |  |  |    for (y = 0; y < (modulus_len - hLen - 1); y++) { | 
					
						
							|  |  |  |       DB[y] ^= mask[y]; | 
					
						
							|  |  |  |    } | 
					
						
							| 
									
										
										
										
											2014-01-03 15:16:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-31 02:36:47 +00:00
										 |  |  |    /* now clear the first byte [make sure smaller than modulus] */ | 
					
						
							| 
									
										
										
										
											2008-01-20 22:45:58 -08:00
										 |  |  |    DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen)); | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* check for zeroes and 0x01 */ | 
					
						
							|  |  |  |    for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { | 
					
						
							|  |  |  |        if (DB[x] != 0x00) { | 
					
						
							| 
									
										
										
										
											2006-12-16 18:10:04 +00:00
										 |  |  |           err = CRYPT_INVALID_PACKET; | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |           goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |        } | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-23 19:55:24 +00:00
										 |  |  |    /* check for the 0x01 */ | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    if (DB[x++] != 0x01) { | 
					
						
							| 
									
										
										
										
											2006-12-16 18:10:04 +00:00
										 |  |  |       err = CRYPT_INVALID_PACKET; | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ | 
					
						
							| 
									
										
										
										
											2004-10-30 03:00:26 +00:00
										 |  |  |    if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-10-30 03:00:26 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    zeromem(mask, 8); | 
					
						
							|  |  |  |    if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |    if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |    if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |    if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  |       goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* mask == hash means valid signature */ | 
					
						
							| 
									
										
										
										
											2015-02-26 12:38:21 +01:00
										 |  |  |    if (XMEM_NEQ(mask, hash, hLen) == 0) { | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  |       *res = 1; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-20 02:41:49 +00:00
										 |  |  |    err = CRYPT_OK; | 
					
						
							| 
									
										
										
										
											2004-12-30 23:55:53 +00:00
										 |  |  | LBL_ERR: | 
					
						
							|  |  |  | #ifdef LTC_CLEAN_STACK
 | 
					
						
							| 
									
										
										
										
											2014-01-03 15:16:59 +01:00
										 |  |  |    zeromem(DB,   modulus_len); | 
					
						
							|  |  |  |    zeromem(mask, modulus_len); | 
					
						
							|  |  |  |    zeromem(salt, modulus_len); | 
					
						
							|  |  |  |    zeromem(hash, modulus_len); | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-20 02:41:49 +00:00
										 |  |  |    XFREE(hash); | 
					
						
							|  |  |  |    XFREE(salt); | 
					
						
							|  |  |  |    XFREE(mask); | 
					
						
							|  |  |  |    XFREE(DB); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    return err; | 
					
						
							| 
									
										
										
										
											2004-05-12 20:42:16 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-20 17:48:02 +00:00
										 |  |  | #endif /* LTC_PKCS_1 */
 | 
					
						
							| 
									
										
										
										
											2005-06-09 00:08:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* $Source$ */ | 
					
						
							|  |  |  | /* $Revision$ */ | 
					
						
							|  |  |  | /* $Date$ */ |