1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except
6  * in compliance with the License. You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <stddef.h>
20 #include <stdint.h>
21 
22 #include <functional>
23 #include <string_view>
24 #include <vector>
25 
26 #include <android-base/unique_fd.h>
27 #include <openssl/ssl.h>
28 #include <openssl/x509.h>
29 
30 namespace adb {
31 namespace tls {
32 
33 class TlsConnection {
34   public:
35     // This class will require both client and server to exchange valid
36     // certificates.
37     enum class Role {
38         Server,
39         Client,
40     };
41 
42     enum class TlsError : uint8_t {
43         Success = 0,
44         // An error indicating that we rejected the peer's certificate.
45         CertificateRejected,
46         // An error indicating that the peer rejected our certificate.
47         PeerRejectedCertificate,
48         // Add more if needed
49         UnknownFailure,
50     };
51 
52     using CertVerifyCb = std::function<int(X509_STORE_CTX*)>;
53     using SetCertCb = std::function<int(SSL*)>;
54 
55     virtual ~TlsConnection() = default;
56 
57     // Adds a trusted certificate to the list for the SSL connection.
58     // During the handshake phase, it will check the list of trusted certificates.
59     // The connection will fail if the peer's certificate is not in the list. If
60     // you would like to accept any certificate, use #SetCertVerifyCallback and
61     // set your callback to always return 1.
62     //
63     // Returns true if |cert| was successfully added, false otherwise.
64     virtual bool AddTrustedCertificate(std::string_view cert) = 0;
65 
66     // Sets a custom certificate verify callback. |cb| must return 1 if the
67     // certificate is trusted. Otherwise, return 0 if not.
68     virtual void SetCertVerifyCallback(CertVerifyCb cb) = 0;
69 
70     // Configures a client |ca_list| that the server sends to the client in the
71     // CertificateRequest message.
72     virtual void SetClientCAList(STACK_OF(X509_NAME) * ca_list) = 0;
73 
74     // Sets a callback that will be called to select a certificate. See
75     // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_cert_cb
76     // for more details.
77     virtual void SetCertificateCallback(SetCertCb cb) = 0;
78 
79     // Exports a value derived from the master secret used in the TLS
80     // connection. This value should be used alongside any PAKE to ensure the
81     // peer is the intended peer. |length| is the requested length for the
82     // keying material. This is only valid after |DoHandshake| succeeds.
83     virtual std::vector<uint8_t> ExportKeyingMaterial(size_t length) = 0;
84 
85     // Enable client-side check on whether server accepted the handshake. In TLS
86     // 1.3, client will not know the server rejected the handshake until after
87     // performing a read operation. Basically, this will perform an
88     // SSL_peek right after the handshake and see whether that succeeds.
89     //
90     // IMPORTANT: this will only work if the protocol is a server-speaks-first
91     // type. Enabling this for the server is a no-op. This is disabled by
92     // default.
93     virtual void EnableClientPostHandshakeCheck(bool enable) = 0;
94 
95     // Starts the handshake process. Returns TlsError::Success if handshake
96     // succeeded.
97     virtual TlsError DoHandshake() = 0;
98 
99     // Reads |size| bytes and returns the data. The returned data has either
100     // size |size| or zero, in which case the read failed.
101     virtual std::vector<uint8_t> ReadFully(size_t size) = 0;
102 
103     // Overloaded ReadFully method, which accepts a buffer for writing in.
104     // Returns true iff exactly |size| amount of data was written into |buf|,
105     // false otherwise.
106     virtual bool ReadFully(void* buf, size_t size) = 0;
107 
108     // Writes |size| bytes. Returns true if all |size| bytes were read.
109     // Returns false otherwise.
110     virtual bool WriteFully(std::string_view data) = 0;
111 
112     // Create a new TlsConnection instance. |cert| and |priv_key| cannot be
113     // empty.
114     static std::unique_ptr<TlsConnection> Create(Role role, std::string_view cert,
115                                                  std::string_view priv_key,
116                                                  android::base::borrowed_fd fd);
117 
118     // Helper to set the certificate and key strings to a SSL client/server.
119     // Useful when in the set-certificate callback.
120     static bool SetCertAndKey(SSL* ssl, std::string_view cert_chain, std::string_view priv_key);
121 
122   protected:
123     TlsConnection() = default;
124 };  // TlsConnection
125 
126 }  // namespace tls
127 }  // namespace adb
128