9#include <botan/exceptn.h>
11#include <botan/mgf1.h>
12#include <botan/internal/bit_ops.h>
13#include <botan/der_enc.h>
14#include <botan/pk_keys.h>
15#include <botan/internal/padding.h>
24secure_vector<uint8_t> pss_encode(HashFunction&
hash,
25 const secure_vector<uint8_t>& msg,
26 const secure_vector<uint8_t>& salt,
29 const size_t HASH_SIZE =
hash.output_length();
30 const size_t SALT_SIZE = salt.size();
32 if(msg.size() != HASH_SIZE)
33 throw Encoding_Error(
"Cannot encode PSS string, input length invalid for hash");
34 if(output_bits < 8*HASH_SIZE + 8*SALT_SIZE + 9)
35 throw Encoding_Error(
"Cannot encode PSS string, output length too small");
37 const size_t output_length = (output_bits + 7) / 8;
39 for(
size_t i = 0; i != 8; ++i)
43 secure_vector<uint8_t> H =
hash.final();
45 secure_vector<uint8_t> EM(output_length);
47 EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01;
48 buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt);
49 mgf1_mask(
hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - 1);
50 EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
52 EM[output_length-1] = 0xBC;
56bool pss_verify(HashFunction&
hash,
57 const secure_vector<uint8_t>& pss_repr,
58 const secure_vector<uint8_t>& message_hash,
60 size_t* out_salt_size)
62 const size_t HASH_SIZE =
hash.output_length();
63 const size_t KEY_BYTES = (key_bits + 7) / 8;
65 if(key_bits < 8*HASH_SIZE + 9)
68 if(message_hash.size() != HASH_SIZE)
71 if(pss_repr.size() > KEY_BYTES || pss_repr.size() <= 1)
74 if(pss_repr[pss_repr.size()-1] != 0xBC)
77 secure_vector<uint8_t> coded = pss_repr;
78 if(coded.size() < KEY_BYTES)
80 secure_vector<uint8_t> temp(KEY_BYTES);
85 const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
86 if(TOP_BITS > 8 -
high_bit(coded[0]))
89 uint8_t* DB = coded.data();
90 const size_t DB_size = coded.size() - HASH_SIZE - 1;
92 const uint8_t* H = &coded[DB_size];
93 const size_t H_size = HASH_SIZE;
96 DB[0] &= 0xFF >> TOP_BITS;
98 size_t salt_offset = 0;
99 for(
size_t j = 0; j != DB_size; ++j)
102 { salt_offset = j + 1;
break; }
109 const size_t salt_size = DB_size - salt_offset;
111 for(
size_t j = 0; j != 8; ++j)
113 hash.update(message_hash);
116 const secure_vector<uint8_t> H2 =
hash.final();
120 if(out_salt_size && ok)
130 m_salt_size(m_hash->output_length()),
131 m_required_salt_len(false)
138 m_required_salt_len(true)
145void PSSR::update(
const uint8_t input[],
size_t length)
147 m_hash->update(input, length);
153secure_vector<uint8_t> PSSR::raw_data()
155 return m_hash->final();
158secure_vector<uint8_t> PSSR::encoding_of(
const secure_vector<uint8_t>& msg,
160 RandomNumberGenerator& rng)
162 const secure_vector<uint8_t> salt = rng.random_vec(m_salt_size);
163 return pss_encode(*m_hash, msg, salt, output_bits);
169bool PSSR::verify(
const secure_vector<uint8_t>& coded,
170 const secure_vector<uint8_t>& raw,
174 const bool ok = pss_verify(*m_hash, coded, raw, key_bits, &
salt_size);
176 if(m_required_salt_len &&
salt_size != m_salt_size)
184 return new PSSR(m_hash->clone(), m_salt_size);
189 return "EMSA4(" + m_hash->name() +
",MGF1," +
std::to_string(m_salt_size) +
")";
193 const std::string& cert_hash_name)
const
195 if(cert_hash_name != m_hash->name())
197 " need to be identical");
202 " not supported for signature algorithm " + key.
algo_name());
208 std::vector<uint8_t> parameters;
223 m_salt_size(m_hash->output_length()),
224 m_required_salt_len(false)
231 m_required_salt_len(true)
238void PSSR_Raw::update(
const uint8_t input[],
size_t length)
240 m_msg.insert(m_msg.end(), input, input + length);
246secure_vector<uint8_t> PSSR_Raw::raw_data()
248 secure_vector<uint8_t> ret;
249 std::swap(ret, m_msg);
251 if(ret.size() != m_hash->output_length())
252 throw Encoding_Error(
"PSSR_Raw Bad input length, did not match hash");
257secure_vector<uint8_t> PSSR_Raw::encoding_of(
const secure_vector<uint8_t>& msg,
259 RandomNumberGenerator& rng)
261 secure_vector<uint8_t> salt = rng.random_vec(m_salt_size);
262 return pss_encode(*m_hash, msg, salt, output_bits);
268bool PSSR_Raw::verify(
const secure_vector<uint8_t>& coded,
269 const secure_vector<uint8_t>& raw,
273 const bool ok = pss_verify(*m_hash, coded, raw, key_bits, &
salt_size);
275 if(m_required_salt_len &&
salt_size != m_salt_size)
283 return new PSSR_Raw(m_hash->clone(), m_salt_size);
288 return "PSSR_Raw(" + m_hash->name() +
",MGF1," +
std::to_string(m_salt_size) +
")";
std::vector< uint8_t > BER_encode() const
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
DER_Encoder & encode(bool b)
std::string name() const override
PSSR_Raw(HashFunction *hash)
std::string name() const override
AlgorithmIdentifier config_for_x509(const Private_Key &key, const std::string &cert_hash_name) const override
virtual std::string algo_name() const =0
std::string to_string(const BER_Object &obj)
void mgf1_mask(HashFunction &hash, const uint8_t in[], size_t in_len, uint8_t out[], size_t out_len)
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
bool sig_algo_and_pad_ok(const std::string algo, const std::string padding)