Botan 3.12.0
Crypto and TLS for C&
pkcs1_sig_padding.cpp
Go to the documentation of this file.
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/pkcs1_sig_padding.h>
9
10#include <botan/exceptn.h>
11#include <botan/hash.h>
12#include <botan/mem_ops.h>
13#include <botan/internal/buffer_stuffer.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/hash_id.h>
16
17namespace Botan {
18
19namespace {
20
21std::vector<uint8_t> pkcs1v15_sig_encoding(std::span<const uint8_t> msg,
22 size_t output_bits,
23 std::span<const uint8_t> hash_id) {
24 const size_t output_length = output_bits / 8;
25
26 if(output_length < hash_id.size() + msg.size() + 2 + 8) {
27 throw Encoding_Error("pkcs1v15_sig_encoding: Output length is too small");
28 }
29
30 std::vector<uint8_t> padded(output_length);
31 BufferStuffer stuffer(padded);
32
33 stuffer.append(0x01);
34 stuffer.append(0xFF, stuffer.remaining_capacity() - (1 + hash_id.size() + msg.size()));
35 stuffer.append(0x00);
36 stuffer.append(hash_id);
37 stuffer.append(msg);
38 BOTAN_ASSERT_NOMSG(stuffer.full());
39
40 return padded;
41}
42
43} // namespace
44
45void PKCS1v15_SignaturePaddingScheme::update(const uint8_t input[], size_t length) {
46 m_hash->update(input, length);
47}
48
50 return m_hash->final_stdvec();
51}
52
53std::vector<uint8_t> PKCS1v15_SignaturePaddingScheme::encoding_of(std::span<const uint8_t> msg,
54 size_t output_bits,
55 RandomNumberGenerator& /*rng*/) {
56 if(msg.size() != m_hash->output_length()) {
57 throw Encoding_Error("PKCS1v15_SignaturePaddingScheme::encoding_of: Bad input length");
58 }
59
60 return pkcs1v15_sig_encoding(msg, output_bits, m_hash_id);
61}
62
63bool PKCS1v15_SignaturePaddingScheme::verify(std::span<const uint8_t> coded,
64 std::span<const uint8_t> raw,
65 size_t key_bits) {
66 if(raw.size() != m_hash->output_length()) {
67 return false;
68 }
69
70 try {
71 const auto pkcs1 = pkcs1v15_sig_encoding(raw, key_bits, m_hash_id);
72 return constant_time_compare(coded, pkcs1);
73 } catch(...) {
74 return false;
75 }
76}
77
79 m_hash(std::move(hash)) {
80 m_hash_id = pkcs_hash_id(m_hash->name());
81}
82
84 return m_hash->name();
85}
86
88 return fmt("PKCS1v15({})", m_hash->name());
89}
90
92 if(m_hash_name.empty()) {
93 return "PKCS1v15(Raw)";
94 } else {
95 return fmt("PKCS1v15(Raw,{})", m_hash_name);
96 }
97}
98
100 // m_hash_id, m_hash_name left empty
101}
102
104 std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw(hash_algo));
105 m_hash_id = pkcs_hash_id(hash_algo);
106 m_hash_name = hash->name();
107 m_hash_output_len = hash->output_length();
108}
109
110void PKCS1v15_Raw_SignaturePaddingScheme::update(const uint8_t input[], size_t length) {
111 m_message += std::make_pair(input, length);
112 // A sanity check to prevent someone from accidentally feeding an entire message
113 // into PKCS1v15(Raw), which would have to be buffered in memory
114 if(m_message.size() > 16384 / 8) {
115 throw Invalid_Argument("PKCS1v15(Raw) message too long");
116 }
117}
118
120 std::vector<uint8_t> ret;
121 std::swap(ret, m_message);
122
123 if(m_hash_output_len > 0 && ret.size() != m_hash_output_len) {
124 throw Encoding_Error("PKCS1v15_Raw_SignaturePaddingScheme::encoding_of: Bad input length");
125 }
126
127 return ret;
128}
129
130std::vector<uint8_t> PKCS1v15_Raw_SignaturePaddingScheme::encoding_of(std::span<const uint8_t> msg,
131 size_t output_bits,
132 RandomNumberGenerator& /*rng*/) {
133 return pkcs1v15_sig_encoding(msg, output_bits, m_hash_id);
134}
135
136bool PKCS1v15_Raw_SignaturePaddingScheme::verify(std::span<const uint8_t> coded,
137 std::span<const uint8_t> raw,
138 size_t key_bits) {
139 if(m_hash_output_len > 0 && raw.size() != m_hash_output_len) {
140 return false;
141 }
142
143 try {
144 const auto pkcs1 = pkcs1v15_sig_encoding(raw, key_bits, m_hash_id);
145 return constant_time_compare(coded, pkcs1);
146 } catch(...) {
147 return false;
148 }
149}
150
151} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
Helper class to ease in-place marshalling of concatenated fixed-length values.
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:308
std::vector< uint8_t > encoding_of(std::span< const uint8_t > msg, size_t output_bits, RandomNumberGenerator &rng) override
std::vector< uint8_t > raw_data() override
void update(const uint8_t input[], size_t length) override
bool verify(std::span< const uint8_t > coded, std::span< const uint8_t > raw, size_t key_bits) override
PKCS1v15_SignaturePaddingScheme(std::unique_ptr< HashFunction > hash)
void update(const uint8_t input[], size_t length) override
std::vector< uint8_t > encoding_of(std::span< const uint8_t > msg, size_t output_bits, RandomNumberGenerator &rng) override
std::vector< uint8_t > raw_data() override
bool verify(std::span< const uint8_t > coded, std::span< const uint8_t > raw, size_t key_bits) override
std::string hash_function() const override
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::vector< uint8_t > pkcs_hash_id(std::string_view name)
Definition hash_id.cpp:78
bool constant_time_compare(std::span< const uint8_t > x, std::span< const uint8_t > y)
Definition mem_ops.cpp:17