/ src / rsa / rsa_pss_sig_pad.c
rsa_pss_sig_pad.c
  1  /*
  2   * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
  3   *
  4   * Permission is hereby granted, free of charge, to any person obtaining 
  5   * a copy of this software and associated documentation files (the
  6   * "Software"), to deal in the Software without restriction, including
  7   * without limitation the rights to use, copy, modify, merge, publish,
  8   * distribute, sublicense, and/or sell copies of the Software, and to
  9   * permit persons to whom the Software is furnished to do so, subject to
 10   * the following conditions:
 11   *
 12   * The above copyright notice and this permission notice shall be 
 13   * included in all copies or substantial portions of the Software.
 14   *
 15   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 16   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 17   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 18   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 19   * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 20   * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 21   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 22   * SOFTWARE.
 23   */
 24  
 25  #include "inner.h"
 26  
 27  /* see inner.h */
 28  uint32_t
 29  br_rsa_pss_sig_pad(const br_prng_class **rng,
 30  	const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
 31  	const unsigned char *hash, size_t salt_len,
 32  	uint32_t n_bitlen, unsigned char *x)
 33  {
 34  	size_t xlen, hash_len;
 35  	br_hash_compat_context hc;
 36  	unsigned char *salt, *seed;
 37  
 38  	hash_len = br_digest_size(hf_data);
 39  
 40  	/*
 41  	 * The padded string is one bit smaller than the modulus;
 42  	 * notably, if the modulus length is equal to 1 modulo 8, then
 43  	 * the padded string will be one _byte_ smaller, and the first
 44  	 * byte will be set to 0. We apply these transformations here.
 45  	 */
 46  	n_bitlen --;
 47  	if ((n_bitlen & 7) == 0) {
 48  		*x ++ = 0;
 49  	}
 50  	xlen = (n_bitlen + 7) >> 3;
 51  
 52  	/*
 53  	 * Check that the modulus is large enough for the hash value
 54  	 * length combined with the intended salt length.
 55  	 */
 56  	if (hash_len > xlen || salt_len > xlen
 57  		|| (hash_len + salt_len + 2) > xlen)
 58  	{
 59  		return 0;
 60  	}
 61  
 62  	/*
 63  	 * Produce a random salt.
 64  	 */
 65  	salt = x + xlen - hash_len - salt_len - 1;
 66  	if (salt_len != 0) {
 67  		(*rng)->generate(rng, salt, salt_len);
 68  	}
 69  
 70  	/*
 71  	 * Compute the seed for MGF1.
 72  	 */
 73  	seed = x + xlen - hash_len - 1;
 74  	hf_data->init(&hc.vtable);
 75  	memset(seed, 0, 8);
 76  	hf_data->update(&hc.vtable, seed, 8);
 77  	hf_data->update(&hc.vtable, hash, hash_len);
 78  	hf_data->update(&hc.vtable, salt, salt_len);
 79  	hf_data->out(&hc.vtable, seed);
 80  
 81  	/*
 82  	 * Prepare string PS (padded salt). The salt is already at the
 83  	 * right place.
 84  	 */
 85  	memset(x, 0, xlen - salt_len - hash_len - 2);
 86  	x[xlen - salt_len - hash_len - 2] = 0x01;
 87  
 88  	/*
 89  	 * Generate the mask and XOR it into PS.
 90  	 */
 91  	br_mgf1_xor(x, xlen - hash_len - 1, hf_mgf1, seed, hash_len);
 92  
 93  	/*
 94  	 * Clear the top bits to ensure the value is lower than the
 95  	 * modulus.
 96  	 */
 97  	x[0] &= 0xFF >> (((uint32_t)xlen << 3) - n_bitlen);
 98  
 99  	/*
100  	 * The seed (H) is already in the right place. We just set the
101  	 * last byte.
102  	 */
103  	x[xlen - 1] = 0xBC;
104  
105  	return 1;
106  }