1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 * 3 * LibTomCrypt is a library that provides various cryptographic 4 * algorithms in a highly modular and flexible manner. 5 * 6 * The library is free for all purposes without any express 7 * guarantee it works. 8 * 9 * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com 10 */ 11 #include "tomcrypt.h" 12 13 /** 14 @file pkcs_1_pss_encode.c 15 PKCS #1 PSS Signature Padding, Tom St Denis 16 */ 17 18 #ifdef PKCS_1 19 20 /** 21 PKCS #1 v2.00 Signature Encoding 22 @param msghash The hash to encode 23 @param msghashlen The length of the hash (octets) 24 @param saltlen The length of the salt desired (octets) 25 @param prng An active PRNG context 26 @param prng_idx The index of the PRNG desired 27 @param hash_idx The index of the hash desired 28 @param modulus_bitlen The bit length of the RSA modulus 29 @param out [out] The destination of the encoding 30 @param outlen [in/out] The max size and resulting size of the encoded data 31 @return CRYPT_OK if successful 32 */ 33 int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, 34 unsigned long saltlen, prng_state *prng, 35 int prng_idx, int hash_idx, 36 unsigned long modulus_bitlen, 37 unsigned char *out, unsigned long *outlen) 38 { 39 unsigned char *DB, *mask, *salt, *hash; 40 unsigned long x, y, hLen, modulus_len; 41 int err; 42 hash_state md; 43 44 LTC_ARGCHK(msghash != NULL); 45 LTC_ARGCHK(out != NULL); 46 LTC_ARGCHK(outlen != NULL); 47 48 /* ensure hash and PRNG are valid */ 49 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 50 return err; 51 } 52 if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { 53 return err; 54 } 55 56 hLen = hash_descriptor[hash_idx].hashsize; 57 modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); 58 59 /* check sizes */ 60 if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { 61 return CRYPT_PK_INVALID_SIZE; 62 } 63 64 /* allocate ram for DB/mask/salt/hash of size modulus_len */ 65 DB = XMALLOC(modulus_len); 66 mask = XMALLOC(modulus_len); 67 salt = XMALLOC(modulus_len); 68 hash = XMALLOC(modulus_len); 69 if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { 70 if (DB != NULL) { 71 XFREE(DB); 72 } 73 if (mask != NULL) { 74 XFREE(mask); 75 } 76 if (salt != NULL) { 77 XFREE(salt); 78 } 79 if (hash != NULL) { 80 XFREE(hash); 81 } 82 return CRYPT_MEM; 83 } 84 85 86 /* generate random salt */ 87 if (saltlen > 0) { 88 if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { 89 err = CRYPT_ERROR_READPRNG; 90 goto LBL_ERR; 91 } 92 } 93 94 /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ 95 if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { 96 goto LBL_ERR; 97 } 98 zeromem(DB, 8); 99 if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { 100 goto LBL_ERR; 101 } 102 if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { 103 goto LBL_ERR; 104 } 105 if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { 106 goto LBL_ERR; 107 } 108 if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { 109 goto LBL_ERR; 110 } 111 112 /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ 113 x = 0; 114 XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2); 115 x += modulus_len - saltlen - hLen - 2; 116 DB[x++] = 0x01; 117 XMEMCPY(DB + x, salt, saltlen); 118 x += saltlen; 119 120 /* generate mask of length modulus_len - hLen - 1 from hash */ 121 if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { 122 goto LBL_ERR; 123 } 124 125 /* xor against DB */ 126 for (y = 0; y < (modulus_len - hLen - 1); y++) { 127 DB[y] ^= mask[y]; 128 } 129 130 /* output is DB || hash || 0xBC */ 131 if (*outlen < modulus_len) { 132 *outlen = modulus_len; 133 err = CRYPT_BUFFER_OVERFLOW; 134 goto LBL_ERR; 135 } 136 137 /* DB len = modulus_len - hLen - 1 */ 138 y = 0; 139 XMEMCPY(out + y, DB, modulus_len - hLen - 1); 140 y += modulus_len - hLen - 1; 141 142 /* hash */ 143 XMEMCPY(out + y, hash, hLen); 144 y += hLen; 145 146 /* 0xBC */ 147 out[y] = 0xBC; 148 149 /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ 150 out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); 151 152 /* store output size */ 153 *outlen = modulus_len; 154 err = CRYPT_OK; 155 LBL_ERR: 156 #ifdef LTC_CLEAN_STACK 157 zeromem(DB, modulus_len); 158 zeromem(mask, modulus_len); 159 zeromem(salt, modulus_len); 160 zeromem(hash, modulus_len); 161 #endif 162 163 XFREE(hash); 164 XFREE(salt); 165 XFREE(mask); 166 XFREE(DB); 167 168 return err; 169 } 170 171 #endif /* PKCS_1 */ 172 173 /* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c,v $ */ 174 /* $Revision: 1.7 $ */ 175 /* $Date: 2006/06/16 21:53:41 $ */ 176