8#include <botan/x509_obj.h>
10#include <botan/assert.h>
11#include <botan/ber_dec.h>
12#include <botan/data_src.h>
13#include <botan/der_enc.h>
15#include <botan/pubkey.h>
16#include <botan/internal/fmt.h>
32 std::string got_label;
36 bool is_alternate =
false;
38 if(got_label == alt_label) {
63 return m_signed_data->m_sig;
70 return m_signed_data->m_tbs_bits;
77 return m_signed_data->m_sig_algo;
94 auto data = std::make_shared<Signed_Data>();
104 m_signed_data = std::move(data);
156 std::span<const uint8_t> tbs_bits) {
159 std::vector<uint8_t> output;
172std::string x509_signature_padding_for(
const std::string& algo_name,
173 std::string_view hash_fn,
174 std::string_view user_specified_padding) {
175 if(algo_name ==
"DSA" || algo_name ==
"ECDSA" || algo_name ==
"ECGDSA" || algo_name ==
"ECKCDSA" ||
176 algo_name ==
"GOST-34.10" || algo_name ==
"GOST-34.10-2012-256" || algo_name ==
"GOST-34.10-2012-512") {
177 BOTAN_ARG_CHECK(user_specified_padding.empty() || user_specified_padding ==
"EMSA1",
178 "Invalid padding scheme for DSA-like scheme");
180 return hash_fn.empty() ?
"SHA-256" : std::string(hash_fn);
181 }
else if(algo_name ==
"RSA") {
184 if(user_specified_padding.empty()) {
185 if(hash_fn.empty()) {
186 return "PKCS1v15(SHA-256)";
188 return fmt(
"PKCS1v15({})", hash_fn);
191 if(hash_fn.empty()) {
192 return fmt(
"{}(SHA-256)", user_specified_padding);
194 return fmt(
"{}({})", user_specified_padding, hash_fn);
197 }
else if(algo_name ==
"Ed25519" || algo_name ==
"Ed448") {
198 return user_specified_padding.empty() ?
"Pure" : std::string(user_specified_padding);
199 }
else if(algo_name.starts_with(
"Dilithium-") || algo_name ==
"ML-DSA") {
200 return user_specified_padding.empty() ?
"Randomized" : std::string(user_specified_padding);
201 }
else if(algo_name ==
"XMSS" || algo_name ==
"HSS-LMS" || algo_name ==
"SLH-DSA") {
203 return std::string(user_specified_padding);
209std::string format_padding_error_message(std::string_view key_name,
210 std::string_view signer_hash_fn,
211 std::string_view user_hash_fn,
212 std::string_view chosen_padding,
213 std::string_view user_specified_padding) {
214 std::ostringstream oss;
216 oss <<
"Specified hash function " << user_hash_fn <<
" is incompatible with " << key_name;
218 if(!signer_hash_fn.empty()) {
219 oss <<
" chose hash function " << signer_hash_fn;
222 if(!chosen_padding.empty()) {
223 oss <<
" chose padding " << chosen_padding;
225 if(!user_specified_padding.empty()) {
226 oss <<
" with user specified padding " << user_specified_padding;
239 std::string_view hash_fn,
240 std::string_view user_specified_padding) {
243 if(!user_specified_padding.empty()) {
245 auto pk_signer = std::make_unique<PK_Signer>(key, rng, user_specified_padding, format);
246 if(!hash_fn.empty() && pk_signer->hash_function() != hash_fn) {
248 key.
algo_name(), pk_signer->hash_function(), hash_fn,
"", user_specified_padding));
254 const std::string padding = x509_signature_padding_for(key.
algo_name(), hash_fn, user_specified_padding);
257 auto pk_signer = std::make_unique<PK_Signer>(key, rng, padding, format);
258 if(!hash_fn.empty() && pk_signer->hash_function() != hash_fn) {
260 key.
algo_name(), pk_signer->hash_function(), hash_fn, padding, user_specified_padding));
#define BOTAN_ARG_CHECK(expr, msg)
std::vector< uint8_t > BER_encode() const
virtual std::string algo_name() const =0
virtual Signature_Format _default_x509_signature_format() const
BER_Decoder & decode(bool &out)
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
BER_Decoder start_sequence()
DER_Encoder & start_sequence()
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
DER_Encoder & encode(bool b)
std::vector< uint8_t > sign_message(const uint8_t in[], size_t length, RandomNumberGenerator &rng)
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
std::string hash_function() const
const std::vector< uint8_t > & signed_body() const
void decode_from(BER_Decoder &from) override
std::string PEM_encode() const
const AlgorithmIdentifier & signature_algorithm() const
virtual std::vector< std::string > alternate_PEM_labels() const
static std::unique_ptr< PK_Signer > choose_sig_format(const Private_Key &key, RandomNumberGenerator &rng, std::string_view hash_fn, std::string_view padding_algo)
std::vector< uint8_t > tbs_data() const
const std::vector< uint8_t > & signature() const
static std::vector< uint8_t > make_signed(PK_Signer &signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, std::span< const uint8_t > tbs)
void encode_into(DER_Encoder &to) const override
std::pair< Certificate_Status_Code, std::string > verify_signature(const Public_Key &key) const
void load_data(DataSource &src)
virtual std::string PEM_label() const =0
bool check_signature(const Public_Key &key) const
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
bool maybe_BER(DataSource &source)
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
bool matches(DataSource &source, std::string_view extra, size_t search_range)
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
std::string fmt(std::string_view format, const T &... args)
@ SIGNATURE_ALGO_BAD_PARAMS