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