xref: /aosp_15_r20/external/pigweed/pw_tls_client/public/pw_tls_client/test/test_server.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 
17 #include "pw_preprocessor/compiler.h"
18 
19 PW_MODIFY_DIAGNOSTICS_PUSH();
20 PW_MODIFY_DIAGNOSTIC(ignored, "-Wcast-qual");
21 PW_MODIFY_DIAGNOSTIC(ignored, "-Wignored-qualifiers");
22 PW_MODIFY_DIAGNOSTIC(ignored, "-Wpedantic");
23 #include <openssl/bio.h>
24 #include <openssl/pem.h>
25 #include <openssl/ssl.h>
26 PW_MODIFY_DIAGNOSTICS_POP();
27 
28 #include "pw_bytes/span.h"
29 #include "pw_result/result.h"
30 #include "pw_status/status.h"
31 #include "pw_stream/stream.h"
32 
33 namespace pw::tls_client::test {
34 
35 class FixedSizeFIFOBuffer : public stream::NonSeekableReaderWriter {
36  public:
37   FixedSizeFIFOBuffer() = delete;
38   FixedSizeFIFOBuffer(const FixedSizeFIFOBuffer&) = delete;
39   FixedSizeFIFOBuffer& operator=(const FixedSizeFIFOBuffer&) = delete;
40 
FixedSizeFIFOBuffer(ByteSpan buffer)41   FixedSizeFIFOBuffer(ByteSpan buffer) : buffer_(buffer) {}
clear()42   void clear() { current_size_ = 0; }
43 
44  private:
45   StatusWithSize DoRead(ByteSpan dest) override;
46   Status DoWrite(ConstByteSpan data) override;
47   ByteSpan buffer_;
48   size_t current_size_ = 0;
49 };
50 
51 // Writing to the server is equivalent to sending data to the server. Server
52 // will be invoked to process the data when being written. The write does
53 // not return until the server completes processing it.
54 // Reading from the server is equivalent to receiving data from the server.
55 //
56 // The server accepts is only for one client and echo messages it sends.
57 class InMemoryTestServer : public stream::NonSeekableReaderWriter {
58  public:
59   InMemoryTestServer() = delete;
60   InMemoryTestServer(const InMemoryTestServer&) = delete;
61   InMemoryTestServer& operator=(const InMemoryTestServer&) = delete;
62 
63   // `input_buffer` is for storing raw data sent from the client.
64   // `output_buffer` is for storing raw data server prepare and to be sent
65   // to the client.
66   //
67   // The required size of the buffer depends on the payload and needs to be
68   // determined by the users based on use cases.
69   InMemoryTestServer(ByteSpan input_buffer, ByteSpan output_buffer);
70 
71   // Initialize a test server with a private key, server certificate, and
72   // CA chains (all DER format)
73   Status Initialize(ConstByteSpan key,
74                     ConstByteSpan cert,
75                     span<const ConstByteSpan> chains);
76 
77   // Is handshake completed.
SessionEstablished()78   bool SessionEstablished() { return is_handshake_done_; }
79 
80   // Returns whether a shutdown request has been received from the client.
81   bool ClientShutdownReceived();
82 
GetLastBioStatus()83   Status GetLastBioStatus() { return last_bio_status_; }
84 
85  private:
86   bssl::UniquePtr<SSL_CTX> ctx_;
87   bssl::UniquePtr<SSL> ssl_;
88   bool is_handshake_done_ = false;
89 
90   // Buffer for storing data sent from the client.
91   FixedSizeFIFOBuffer input_buffer_;
92 
93   // Buffer for storing data prepared by the server to send to the client.
94   FixedSizeFIFOBuffer output_buffer_;
95 
96   // Store the last status of BIO operation (in BioRead() and BioWrite());
97   Status last_bio_status_ = OkStatus();
98 
99   // Process the data written to the server as much as possible.
100   // If server is in handshake process, it processes handshake and prepares data
101   // to send to the server . If server is in application data exchange
102   // phase, it decrypts data and echoes back to the client. Client can retrieve
103   // the message by reading from the server.
104   Status ProcessPackets();
105 
106   // Methods for loading private key, certificate, and intermediate CA chain.
107   Status LoadPrivateKey(ConstByteSpan key);
108   Status LoadCertificate(ConstByteSpan cert);
109   Status LoadCAChain(span<const ConstByteSpan> chains);
110 
111   // Methods for providing BIO interfaces.
112   static int BioRead(BIO* bio, char* out, int output_length);
113   static int BioWrite(BIO* bio, const char* in, int input_length);
114 
115   StatusWithSize DoRead(ByteSpan dest) override;
116   Status DoWrite(ConstByteSpan data) override;
117 };
118 
119 // A helper function to parse a DER format certificate.
120 pw::Result<X509*> ParseDerCertificate(pw::ConstByteSpan cert);
121 
122 }  // namespace pw::tls_client::test
123