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