• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 25139258422

29 Apr 2026 08:02PM UTC coverage: 89.37% (-0.02%) from 89.385%
25139258422

push

github

web-flow
Merge pull request #5550 from randombit/jack/tls-misc

TLS conformance, hardening, and performance fixes

107055 of 119789 relevant lines covered (89.37%)

11415549.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.87
/src/lib/tls/tls13/msg_cert_verify_13.cpp
1
/*
2
* Certificate Verify Message
3
* (C) 2021-2022 Jack Lloyd
4
*     2021 Elektrobit Automotive GmbH
5
*     2022 René Meusel, Hannes Rantzsch - neXenio GmbH
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9

10
#include <botan/tls_messages_13.h>
11

12
#include <botan/credentials_manager.h>
13
#include <botan/pk_keys.h>
14
#include <botan/tls_callbacks.h>
15
#include <botan/tls_exceptn.h>
16
#include <botan/tls_policy.h>
17
#include <botan/internal/stl_util.h>
18

19
namespace Botan::TLS {
20

21
namespace {
22

23
std::vector<uint8_t> message(Connection_Side side, const Transcript_Hash& hash) {
658✔
24
   std::vector<uint8_t> msg(64, 0x20);
658✔
25
   msg.reserve(64 + 33 + 1 + hash.size());
658✔
26

27
   const std::string context_string = (side == TLS::Connection_Side::Server) ? "TLS 1.3, server CertificateVerify"
658✔
28
                                                                             : "TLS 1.3, client CertificateVerify";
752✔
29

30
   msg.insert(msg.end(), context_string.cbegin(), context_string.cend());
658✔
31
   msg.push_back(0x00);
658✔
32

33
   msg.insert(msg.end(), hash.cbegin(), hash.cend());
658✔
34
   return msg;
658✔
35
}
658✔
36

37
Signature_Scheme choose_signature_scheme(const Private_Key& key,
308✔
38
                                         const std::vector<Signature_Scheme>& allowed_schemes,
39
                                         const std::vector<Signature_Scheme>& peer_allowed_schemes) {
40
   for(Signature_Scheme scheme : allowed_schemes) {
538✔
41
      // RFC 8446 4.4.3 forbids the rsa_pkcs1_* schemes in CertificateVerify, those are TLS 1.2 only.
42
      if(scheme.is_available() && scheme.is_compatible_with(Protocol_Version::TLS_V13) && scheme.is_suitable_for(key) &&
549✔
43
         value_exists(peer_allowed_schemes, scheme)) {
319✔
44
         return scheme;
307✔
45
      }
46
   }
47

48
   throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on a signature algorithm");
1✔
49
}
50

51
}  // namespace
52

53
/*
54
* Create a new Certificate Verify message for TLS 1.3
55
*/
56
Certificate_Verify_13::Certificate_Verify_13(const Certificate_13& certificate_msg,
308✔
57
                                             const std::vector<Signature_Scheme>& peer_allowed_schemes,
58
                                             std::string_view hostname,
59
                                             const Transcript_Hash& hash,
60
                                             Connection_Side whoami,
61
                                             Credentials_Manager& creds_mgr,
62
                                             const Policy& policy,
63
                                             Callbacks& callbacks,
64
                                             RandomNumberGenerator& rng) :
308✔
65
      m_side(whoami) {
308✔
66
   BOTAN_ASSERT_NOMSG(!certificate_msg.empty());
308✔
67

68
   const std::string op_type((m_side == Connection_Side::Client) ? "tls-client" : "tls-server");
571✔
69
   const auto context = std::string(hostname);
618✔
70

71
   const auto private_key = (certificate_msg.has_certificate_chain())
308✔
72
                               ? creds_mgr.private_key_for(certificate_msg.leaf(), op_type, context)
308✔
73
                               : creds_mgr.private_key_for(*certificate_msg.public_key(), op_type, context);
312✔
74
   if(!private_key) {
308✔
75
      throw TLS_Exception(Alert::InternalError, "Application did not provide a private key for its credential");
×
76
   }
77

78
   m_scheme = choose_signature_scheme(*private_key, policy.allowed_signature_schemes(), peer_allowed_schemes);
308✔
79
   BOTAN_ASSERT_NOMSG(m_scheme.is_available());
307✔
80
   BOTAN_ASSERT_NOMSG(m_scheme.is_compatible_with(Protocol_Version::TLS_V13));
307✔
81

82
   m_signature = callbacks.tls_sign_message(
613✔
83
      *private_key, rng, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, hash));
922✔
84
}
312✔
85

86
Certificate_Verify_13::Certificate_Verify_13(const std::vector<uint8_t>& buf, const Connection_Side side) :
377✔
87
      Certificate_Verify(buf), m_side(side) {
377✔
88
   if(!m_scheme.is_available()) {
375✔
89
      throw TLS_Exception(Alert::IllegalParameter, "Peer sent unknown signature scheme");
2✔
90
   }
91

92
   if(!m_scheme.is_compatible_with(Protocol_Version::TLS_V13)) {
373✔
93
      throw TLS_Exception(Alert::IllegalParameter, "Peer sent signature algorithm that is not suitable for TLS 1.3");
12✔
94
   }
95
}
375✔
96

97
/*
98
* Verify a Certificate Verify message
99
*/
100
bool Certificate_Verify_13::verify(const Public_Key& public_key,
354✔
101
                                   Callbacks& callbacks,
102
                                   const Transcript_Hash& transcript_hash) const {
103
   BOTAN_ASSERT_NOMSG(m_scheme.is_available());
354✔
104

105
   // RFC 8446 4.2.3
106
   //    The keys found in certificates MUST [...] be of appropriate type for
107
   //    the signature algorithms they are used with.
108
   if(m_scheme.key_algorithm_identifier() != public_key.algorithm_identifier()) {
354✔
109
      throw TLS_Exception(Alert::IllegalParameter, "Signature algorithm does not match certificate's public key");
3✔
110
   }
111

112
   const bool signature_valid = callbacks.tls_verify_message(
351✔
113
      public_key, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, transcript_hash), m_signature);
702✔
114

115
#if defined(BOTAN_UNSAFE_FUZZER_MODE)
116
   BOTAN_UNUSED(signature_valid);
117
   return true;
118
#else
119
   return signature_valid;
351✔
120
#endif
121
}
122

123
}  // namespace Botan::TLS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc