• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <openssl/bio.h>
18 #include <openssl/pem.h>
19 #include <openssl/ssl.h>
20 
21 #include "pw_bytes/span.h"
22 #include "pw_result/result.h"
23 #include "pw_status/status.h"
24 #include "pw_stream/stream.h"
25 
26 namespace pw::tls_client::test {
27 
28 class FixedSizeFIFOBuffer : public stream::NonSeekableReaderWriter {
29  public:
30   FixedSizeFIFOBuffer() = delete;
31   FixedSizeFIFOBuffer(const FixedSizeFIFOBuffer&) = delete;
32   FixedSizeFIFOBuffer& operator=(const FixedSizeFIFOBuffer&) = delete;
33 
FixedSizeFIFOBuffer(ByteSpan buffer)34   FixedSizeFIFOBuffer(ByteSpan buffer) : buffer_(buffer) {}
clear()35   void clear() { current_size_ = 0; }
36 
37  private:
38   StatusWithSize DoRead(ByteSpan dest) override;
39   Status DoWrite(ConstByteSpan data) override;
40   ByteSpan buffer_;
41   size_t current_size_ = 0;
42 };
43 
44 // Writing to the server is equivalent to sending data to the server. Server
45 // will be invoked to process the data when being written. The write does
46 // not return until the server completes processing it.
47 // Reading from the server is equivalent to receiving data from the server.
48 //
49 // The server accepts is only for one client and echo messages it sends.
50 class InMemoryTestServer : public stream::NonSeekableReaderWriter {
51  public:
52   InMemoryTestServer() = delete;
53   InMemoryTestServer(const InMemoryTestServer&) = delete;
54   InMemoryTestServer& operator=(const InMemoryTestServer&) = delete;
55 
56   // `input_buffer` is for storing raw data sent from the client.
57   // `output_buffer` is for storing raw data server prepare and to be sent
58   // to the client.
59   //
60   // The required size of the buffer depends on the payload and needs to be
61   // determined by the users based on use cases.
62   InMemoryTestServer(ByteSpan input_buffer, ByteSpan output_buffer);
63 
64   // Initialize a test server with a private key, server certificate, and
65   // CA chains (all DER format)
66   Status Initialize(ConstByteSpan key,
67                     ConstByteSpan cert,
68                     std::span<const ConstByteSpan> chains);
69 
70   // Is handshake completed.
SessionEstablished()71   bool SessionEstablished() { return is_handshake_done_; }
72 
73   // Returns whether a shutdown request has been received from the client.
74   bool ClientShutdownReceived();
75 
GetLastBioStatus()76   Status GetLastBioStatus() { return last_bio_status_; }
77 
78  private:
79   bssl::UniquePtr<SSL_CTX> ctx_;
80   bssl::UniquePtr<SSL> ssl_;
81   bool is_handshake_done_ = false;
82 
83   // Buffer for storing data sent from the client.
84   FixedSizeFIFOBuffer input_buffer_;
85 
86   // Buffer for storing data prepared by the server to send to the client.
87   FixedSizeFIFOBuffer output_buffer_;
88 
89   // Store the last status of BIO operation (in BioRead() and BioWrite());
90   Status last_bio_status_ = OkStatus();
91 
92   // Process the data written to the server as much as possible.
93   // If server is in handshake process, it processes handshake and prepares data
94   // to send to the server . If server is in application data exchange
95   // phase, it decrypts data and echoes back to the client. Client can retrieve
96   // the message by reading from the server.
97   Status ProcessPackets();
98 
99   // Methods for loading private key, certificate, and intermediate CA chain.
100   Status LoadPrivateKey(ConstByteSpan key);
101   Status LoadCertificate(ConstByteSpan cert);
102   Status LoadCAChain(std::span<const ConstByteSpan> chains);
103 
104   // Methods for providing BIO interfaces.
105   static int BioRead(BIO* bio, char* out, int output_length);
106   static int BioWrite(BIO* bio, const char* in, int input_length);
107 
108   StatusWithSize DoRead(ByteSpan dest) override;
109   Status DoWrite(ConstByteSpan data) override;
110 };
111 
112 // A helper function to parse a DER format certificate.
113 pw::Result<X509*> ParseDerCertificate(pw::ConstByteSpan cert);
114 
115 }  // namespace pw::tls_client::test
116