1 /*
2 * PKCS #1 v1.5 signature padding
3 * (C) 1999-2008 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/emsa_pkcs1.h>
9 #include <botan/hash_id.h>
10 #include <botan/exceptn.h>
11 #include <botan/pk_keys.h>
12 #include <botan/internal/padding.h>
13
14 namespace Botan {
15
16 namespace {
17
emsa3_encoding(const secure_vector<uint8_t> & msg,size_t output_bits,const uint8_t hash_id[],size_t hash_id_length)18 secure_vector<uint8_t> emsa3_encoding(const secure_vector<uint8_t>& msg,
19 size_t output_bits,
20 const uint8_t hash_id[],
21 size_t hash_id_length)
22 {
23 size_t output_length = output_bits / 8;
24 if(output_length < hash_id_length + msg.size() + 10)
25 throw Encoding_Error("emsa3_encoding: Output length is too small");
26
27 secure_vector<uint8_t> T(output_length);
28 const size_t P_LENGTH = output_length - msg.size() - hash_id_length - 2;
29
30 T[0] = 0x01;
31 set_mem(&T[1], P_LENGTH, 0xFF);
32 T[P_LENGTH+1] = 0x00;
33
34 if(hash_id_length > 0)
35 {
36 BOTAN_ASSERT_NONNULL(hash_id);
37 buffer_insert(T, P_LENGTH+2, hash_id, hash_id_length);
38 }
39
40 buffer_insert(T, output_length-msg.size(), msg.data(), msg.size());
41 return T;
42 }
43
44 }
45
update(const uint8_t input[],size_t length)46 void EMSA_PKCS1v15::update(const uint8_t input[], size_t length)
47 {
48 m_hash->update(input, length);
49 }
50
raw_data()51 secure_vector<uint8_t> EMSA_PKCS1v15::raw_data()
52 {
53 return m_hash->final();
54 }
55
56 secure_vector<uint8_t>
encoding_of(const secure_vector<uint8_t> & msg,size_t output_bits,RandomNumberGenerator &)57 EMSA_PKCS1v15::encoding_of(const secure_vector<uint8_t>& msg,
58 size_t output_bits,
59 RandomNumberGenerator&)
60 {
61 if(msg.size() != m_hash->output_length())
62 throw Encoding_Error("EMSA_PKCS1v15::encoding_of: Bad input length");
63
64 return emsa3_encoding(msg, output_bits,
65 m_hash_id.data(), m_hash_id.size());
66 }
67
verify(const secure_vector<uint8_t> & coded,const secure_vector<uint8_t> & raw,size_t key_bits)68 bool EMSA_PKCS1v15::verify(const secure_vector<uint8_t>& coded,
69 const secure_vector<uint8_t>& raw,
70 size_t key_bits)
71 {
72 if(raw.size() != m_hash->output_length())
73 return false;
74
75 try
76 {
77 return (coded == emsa3_encoding(raw, key_bits,
78 m_hash_id.data(), m_hash_id.size()));
79 }
80 catch(...)
81 {
82 return false;
83 }
84 }
85
config_for_x509(const Private_Key & key,const std::string & cert_hash_name) const86 AlgorithmIdentifier EMSA_PKCS1v15::config_for_x509(const Private_Key& key,
87 const std::string& cert_hash_name) const
88 {
89 if(cert_hash_name != m_hash->name())
90 throw Invalid_Argument("Hash function from opts and hash_fn argument"
91 " need to be identical");
92 // check that the signature algorithm and the padding scheme fit
93 if(!sig_algo_and_pad_ok(key.algo_name(), "EMSA3"))
94 {
95 throw Invalid_Argument("Encoding scheme with canonical name EMSA3"
96 " not supported for signature algorithm " + key.algo_name());
97 }
98
99 // for RSA PKCSv1.5 parameters "SHALL" be NULL
100
101 const OID oid = OID::from_string(key.algo_name() + "/" + name());
102 return AlgorithmIdentifier(oid, AlgorithmIdentifier::USE_NULL_PARAM);
103 }
104
EMSA_PKCS1v15(HashFunction * hash)105 EMSA_PKCS1v15::EMSA_PKCS1v15(HashFunction* hash) : m_hash(hash)
106 {
107 m_hash_id = pkcs_hash_id(m_hash->name());
108 }
109
EMSA_PKCS1v15_Raw(const std::string & hash_algo)110 EMSA_PKCS1v15_Raw::EMSA_PKCS1v15_Raw(const std::string& hash_algo)
111 {
112 if(!hash_algo.empty())
113 {
114 m_hash_id = pkcs_hash_id(hash_algo);
115 std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw(hash_algo));
116 m_hash_name = hash->name();
117 m_hash_output_len = hash->output_length();
118 }
119 else
120 {
121 m_hash_output_len = 0;
122 }
123 }
124
update(const uint8_t input[],size_t length)125 void EMSA_PKCS1v15_Raw::update(const uint8_t input[], size_t length)
126 {
127 m_message += std::make_pair(input, length);
128 }
129
raw_data()130 secure_vector<uint8_t> EMSA_PKCS1v15_Raw::raw_data()
131 {
132 secure_vector<uint8_t> ret;
133 std::swap(ret, m_message);
134
135 if(m_hash_output_len > 0 && ret.size() != m_hash_output_len)
136 throw Encoding_Error("EMSA_PKCS1v15_Raw::encoding_of: Bad input length");
137
138 return ret;
139 }
140
141 secure_vector<uint8_t>
encoding_of(const secure_vector<uint8_t> & msg,size_t output_bits,RandomNumberGenerator &)142 EMSA_PKCS1v15_Raw::encoding_of(const secure_vector<uint8_t>& msg,
143 size_t output_bits,
144 RandomNumberGenerator&)
145 {
146 return emsa3_encoding(msg, output_bits, m_hash_id.data(), m_hash_id.size());
147 }
148
verify(const secure_vector<uint8_t> & coded,const secure_vector<uint8_t> & raw,size_t key_bits)149 bool EMSA_PKCS1v15_Raw::verify(const secure_vector<uint8_t>& coded,
150 const secure_vector<uint8_t>& raw,
151 size_t key_bits)
152 {
153 if(m_hash_output_len > 0 && raw.size() != m_hash_output_len)
154 return false;
155
156 try
157 {
158 return (coded == emsa3_encoding(raw, key_bits, m_hash_id.data(), m_hash_id.size()));
159 }
160 catch(...)
161 {
162 return false;
163 }
164 }
165
166 }
167