Coverage Report

Created: 2025-04-11 06:34

/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