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