/src/botan/src/lib/tls/tls_callbacks.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * TLS Callbacks |
3 | | * (C) 2016 Jack Lloyd |
4 | | * 2017 Harry Reimann, Rohde & Schwarz Cybersecurity |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | */ |
8 | | |
9 | | #include <botan/tls_callbacks.h> |
10 | | #include <botan/tls_policy.h> |
11 | | #include <botan/tls_algos.h> |
12 | | #include <botan/x509path.h> |
13 | | #include <botan/ocsp.h> |
14 | | #include <botan/dh.h> |
15 | | #include <botan/ecdh.h> |
16 | | #include <botan/tls_exceptn.h> |
17 | | #include <botan/internal/ct_utils.h> |
18 | | |
19 | | #if defined(BOTAN_HAS_CURVE_25519) |
20 | | #include <botan/curve25519.h> |
21 | | #endif |
22 | | |
23 | | namespace Botan { |
24 | | |
25 | | void TLS::Callbacks::tls_inspect_handshake_msg(const Handshake_Message&) |
26 | 130k | { |
27 | 130k | // default is no op |
28 | 130k | } |
29 | | |
30 | | std::string TLS::Callbacks::tls_server_choose_app_protocol(const std::vector<std::string>&) |
31 | 0 | { |
32 | 0 | return ""; |
33 | 0 | } |
34 | | |
35 | | std::string TLS::Callbacks::tls_peer_network_identity() |
36 | 6.93k | { |
37 | 6.93k | return ""; |
38 | 6.93k | } |
39 | | |
40 | | void TLS::Callbacks::tls_modify_extensions(Extensions&, Connection_Side) |
41 | 29.1k | { |
42 | 29.1k | } |
43 | | |
44 | | void TLS::Callbacks::tls_examine_extensions(const Extensions&, Connection_Side) |
45 | 28.0k | { |
46 | 28.0k | } |
47 | | |
48 | | std::string TLS::Callbacks::tls_decode_group_param(Group_Params group_param) |
49 | 22.4k | { |
50 | 22.4k | return group_param_to_string(group_param); |
51 | 22.4k | } |
52 | | |
53 | | void TLS::Callbacks::tls_verify_cert_chain( |
54 | | const std::vector<X509_Certificate>& cert_chain, |
55 | | const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses, |
56 | | const std::vector<Certificate_Store*>& trusted_roots, |
57 | | Usage_Type usage, |
58 | | const std::string& hostname, |
59 | | const TLS::Policy& policy) |
60 | 755 | { |
61 | 755 | if(cert_chain.empty()) |
62 | 0 | throw Invalid_Argument("Certificate chain was empty"); |
63 | 755 | |
64 | 755 | Path_Validation_Restrictions restrictions(policy.require_cert_revocation_info(), |
65 | 755 | policy.minimum_signature_strength()); |
66 | 755 | |
67 | 755 | Path_Validation_Result result = |
68 | 755 | x509_path_validate(cert_chain, |
69 | 755 | restrictions, |
70 | 755 | trusted_roots, |
71 | 755 | (usage == Usage_Type::TLS_SERVER_AUTH ? hostname : ""), |
72 | 755 | usage, |
73 | 755 | std::chrono::system_clock::now(), |
74 | 755 | tls_verify_cert_chain_ocsp_timeout(), |
75 | 755 | ocsp_responses); |
76 | 755 | |
77 | 755 | if(!result.successful_validation()) |
78 | 755 | { |
79 | 755 | throw TLS_Exception(Alert::BAD_CERTIFICATE, |
80 | 755 | "Certificate validation failure: " + result.result_string()); |
81 | 755 | } |
82 | 755 | } |
83 | | |
84 | | std::vector<uint8_t> TLS::Callbacks::tls_sign_message( |
85 | | const Private_Key& key, |
86 | | RandomNumberGenerator& rng, |
87 | | const std::string& emsa, |
88 | | Signature_Format format, |
89 | | const std::vector<uint8_t>& msg) |
90 | 0 | { |
91 | 0 | PK_Signer signer(key, rng, emsa, format); |
92 | 0 |
|
93 | 0 | return signer.sign_message(msg, rng); |
94 | 0 | } |
95 | | |
96 | | bool TLS::Callbacks::tls_verify_message( |
97 | | const Public_Key& key, |
98 | | const std::string& emsa, |
99 | | Signature_Format format, |
100 | | const std::vector<uint8_t>& msg, |
101 | | const std::vector<uint8_t>& sig) |
102 | 268 | { |
103 | 268 | PK_Verifier verifier(key, emsa, format); |
104 | 268 | |
105 | 268 | return verifier.verify_message(msg, sig); |
106 | 268 | } |
107 | | |
108 | | std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_dh_agree( |
109 | | const std::vector<uint8_t>& modulus, |
110 | | const std::vector<uint8_t>& generator, |
111 | | const std::vector<uint8_t>& peer_public_value, |
112 | | const Policy& policy, |
113 | | RandomNumberGenerator& rng) |
114 | 177 | { |
115 | 177 | BigInt p = BigInt::decode(modulus); |
116 | 177 | BigInt g = BigInt::decode(generator); |
117 | 177 | BigInt Y = BigInt::decode(peer_public_value); |
118 | 177 | |
119 | 177 | /* |
120 | 177 | * A basic check for key validity. As we do not know q here we |
121 | 177 | * cannot check that Y is in the right subgroup. However since |
122 | 177 | * our key is ephemeral there does not seem to be any |
123 | 177 | * advantage to bogus keys anyway. |
124 | 177 | */ |
125 | 177 | if(Y <= 1 || Y >= p - 1) |
126 | 3 | throw TLS_Exception(Alert::ILLEGAL_PARAMETER, |
127 | 3 | "Server sent bad DH key for DHE exchange"); |
128 | 174 | |
129 | 174 | DL_Group group(p, g); |
130 | 174 | |
131 | 174 | if(!group.verify_group(rng, false)) |
132 | 90 | throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, |
133 | 90 | "DH group validation failed"); |
134 | 84 | |
135 | 84 | DH_PublicKey peer_key(group, Y); |
136 | 84 | |
137 | 84 | policy.check_peer_key_acceptable(peer_key); |
138 | 84 | |
139 | 84 | DH_PrivateKey priv_key(rng, group); |
140 | 84 | PK_Key_Agreement ka(priv_key, rng, "Raw"); |
141 | 84 | secure_vector<uint8_t> dh_secret = CT::strip_leading_zeros( |
142 | 84 | ka.derive_key(0, peer_key.public_value()).bits_of()); |
143 | 84 | |
144 | 84 | return std::make_pair(dh_secret, priv_key.public_value()); |
145 | 84 | } |
146 | | |
147 | | std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_ecdh_agree( |
148 | | const std::string& curve_name, |
149 | | const std::vector<uint8_t>& peer_public_value, |
150 | | const Policy& policy, |
151 | | RandomNumberGenerator& rng, |
152 | | bool compressed) |
153 | 175 | { |
154 | 175 | secure_vector<uint8_t> ecdh_secret; |
155 | 175 | std::vector<uint8_t> our_public_value; |
156 | 175 | |
157 | 175 | if(curve_name == "x25519") |
158 | 12 | { |
159 | 12 | #if defined(BOTAN_HAS_CURVE_25519) |
160 | 12 | if(peer_public_value.size() != 32) |
161 | 1 | { |
162 | 1 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid X25519 key size"); |
163 | 1 | } |
164 | 11 | |
165 | 11 | Curve25519_PublicKey peer_key(peer_public_value); |
166 | 11 | policy.check_peer_key_acceptable(peer_key); |
167 | 11 | Curve25519_PrivateKey priv_key(rng); |
168 | 11 | PK_Key_Agreement ka(priv_key, rng, "Raw"); |
169 | 11 | ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of(); |
170 | 11 | |
171 | 11 | // X25519 is always compressed but sent as "uncompressed" in TLS |
172 | 11 | our_public_value = priv_key.public_value(); |
173 | | #else |
174 | | throw Internal_Error("Negotiated X25519 somehow, but it is disabled"); |
175 | | #endif |
176 | | } |
177 | 163 | else |
178 | 163 | { |
179 | 163 | EC_Group group(OID::from_string(curve_name)); |
180 | 163 | ECDH_PublicKey peer_key(group, group.OS2ECP(peer_public_value)); |
181 | 163 | policy.check_peer_key_acceptable(peer_key); |
182 | 163 | ECDH_PrivateKey priv_key(rng, group); |
183 | 163 | PK_Key_Agreement ka(priv_key, rng, "Raw"); |
184 | 163 | ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of(); |
185 | 163 | our_public_value = priv_key.public_value(compressed ? PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED); |
186 | 163 | } |
187 | 175 | |
188 | 175 | return std::make_pair(ecdh_secret, our_public_value); |
189 | 175 | } |
190 | | |
191 | | } |