/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 | | |
10 | | #include <botan/exceptn.h> |
11 | | #include <botan/mem_ops.h> |
12 | | #include <botan/internal/hash_id.h> |
13 | | #include <botan/internal/stl_util.h> |
14 | | |
15 | | namespace Botan { |
16 | | |
17 | | namespace { |
18 | | |
19 | | std::vector<uint8_t> pkcs1v15_sig_encoding(std::span<const uint8_t> msg, |
20 | | size_t output_bits, |
21 | 2.94k | std::span<const uint8_t> hash_id) { |
22 | 2.94k | const size_t output_length = output_bits / 8; |
23 | | |
24 | 2.94k | if(output_length < hash_id.size() + msg.size() + 2 + 8) { |
25 | 1.32k | throw Encoding_Error("pkcs1v15_sig_encoding: Output length is too small"); |
26 | 1.32k | } |
27 | | |
28 | 1.62k | std::vector<uint8_t> padded(output_length); |
29 | 1.62k | BufferStuffer stuffer(padded); |
30 | | |
31 | 1.62k | stuffer.append(0x01); |
32 | 1.62k | stuffer.append(0xFF, stuffer.remaining_capacity() - (1 + hash_id.size() + msg.size())); |
33 | 1.62k | stuffer.append(0x00); |
34 | 1.62k | stuffer.append(hash_id); |
35 | 1.62k | stuffer.append(msg); |
36 | 1.62k | BOTAN_ASSERT_NOMSG(stuffer.full()); |
37 | | |
38 | 1.62k | return padded; |
39 | 2.94k | } |
40 | | |
41 | | } // namespace |
42 | | |
43 | 3.05k | void EMSA_PKCS1v15::update(const uint8_t input[], size_t length) { |
44 | 3.05k | m_hash->update(input, length); |
45 | 3.05k | } |
46 | | |
47 | 3.05k | std::vector<uint8_t> EMSA_PKCS1v15::raw_data() { |
48 | 3.05k | return m_hash->final_stdvec(); |
49 | 3.05k | } |
50 | | |
51 | | std::vector<uint8_t> EMSA_PKCS1v15::encoding_of(std::span<const uint8_t> msg, |
52 | | size_t output_bits, |
53 | 0 | RandomNumberGenerator& /*rng*/) { |
54 | 0 | if(msg.size() != m_hash->output_length()) { |
55 | 0 | throw Encoding_Error("EMSA_PKCS1v15::encoding_of: Bad input length"); |
56 | 0 | } |
57 | | |
58 | 0 | return pkcs1v15_sig_encoding(msg, output_bits, m_hash_id); |
59 | 0 | } |
60 | | |
61 | 2.94k | bool EMSA_PKCS1v15::verify(std::span<const uint8_t> coded, std::span<const uint8_t> raw, size_t key_bits) { |
62 | 2.94k | if(raw.size() != m_hash->output_length()) { |
63 | 0 | return false; |
64 | 0 | } |
65 | | |
66 | 2.94k | try { |
67 | 2.94k | const auto pkcs1 = pkcs1v15_sig_encoding(raw, key_bits, m_hash_id); |
68 | 2.94k | return constant_time_compare(coded, pkcs1); |
69 | 2.94k | } catch(...) { |
70 | 1.32k | return false; |
71 | 1.32k | } |
72 | 2.94k | } |
73 | | |
74 | 3.05k | EMSA_PKCS1v15::EMSA_PKCS1v15(std::unique_ptr<HashFunction> hash) : m_hash(std::move(hash)) { |
75 | 3.05k | m_hash_id = pkcs_hash_id(m_hash->name()); |
76 | 3.05k | } |
77 | | |
78 | 0 | std::string EMSA_PKCS1v15::name() const { |
79 | 0 | return "PKCS1v15(" + m_hash->name() + ")"; |
80 | 0 | } |
81 | | |
82 | 0 | std::string EMSA_PKCS1v15_Raw::name() const { |
83 | 0 | if(m_hash_name.empty()) { |
84 | 0 | return "PKCS1v15(Raw)"; |
85 | 0 | } else { |
86 | 0 | return "PKCS1v15(Raw," + m_hash_name + ")"; |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | 0 | EMSA_PKCS1v15_Raw::EMSA_PKCS1v15_Raw() { |
91 | 0 | m_hash_output_len = 0; |
92 | | // m_hash_id, m_hash_name left empty |
93 | 0 | } |
94 | | |
95 | 0 | EMSA_PKCS1v15_Raw::EMSA_PKCS1v15_Raw(std::string_view hash_algo) { |
96 | 0 | std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw(hash_algo)); |
97 | 0 | m_hash_id = pkcs_hash_id(hash_algo); |
98 | 0 | m_hash_name = hash->name(); |
99 | 0 | m_hash_output_len = hash->output_length(); |
100 | 0 | } |
101 | | |
102 | 0 | void EMSA_PKCS1v15_Raw::update(const uint8_t input[], size_t length) { |
103 | 0 | m_message += std::make_pair(input, length); |
104 | 0 | } |
105 | | |
106 | 0 | std::vector<uint8_t> EMSA_PKCS1v15_Raw::raw_data() { |
107 | 0 | std::vector<uint8_t> ret; |
108 | 0 | std::swap(ret, m_message); |
109 | |
|
110 | 0 | if(m_hash_output_len > 0 && ret.size() != m_hash_output_len) { |
111 | 0 | throw Encoding_Error("EMSA_PKCS1v15_Raw::encoding_of: Bad input length"); |
112 | 0 | } |
113 | | |
114 | 0 | return ret; |
115 | 0 | } |
116 | | |
117 | | std::vector<uint8_t> EMSA_PKCS1v15_Raw::encoding_of(std::span<const uint8_t> msg, |
118 | | size_t output_bits, |
119 | 0 | RandomNumberGenerator& /*rng*/) { |
120 | 0 | return pkcs1v15_sig_encoding(msg, output_bits, m_hash_id); |
121 | 0 | } |
122 | | |
123 | 0 | bool EMSA_PKCS1v15_Raw::verify(std::span<const uint8_t> coded, std::span<const uint8_t> raw, size_t key_bits) { |
124 | 0 | if(m_hash_output_len > 0 && raw.size() != m_hash_output_len) { |
125 | 0 | return false; |
126 | 0 | } |
127 | | |
128 | 0 | try { |
129 | 0 | const auto pkcs1 = pkcs1v15_sig_encoding(raw, key_bits, m_hash_id); |
130 | 0 | return constant_time_compare(coded, pkcs1); |
131 | 0 | } catch(...) { |
132 | 0 | return false; |
133 | 0 | } |
134 | 0 | } |
135 | | |
136 | | } // namespace Botan |