Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
CryptographyTransformStreams.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Common/CompilerMove.h"
5#include "AsyncStreams.h"
6
9namespace SC
10{
19template <typename T_Cipher>
21{
22 T_Cipher cipher;
23
25
26 template <typename T_Argument>
27 explicit AsyncCipherTransformStreamT(T_Argument&& argument) : cipher(forward<T_Argument>(argument))
28 {}
29
30 private:
31 static constexpr size_t BlockSize = 16;
32 static constexpr size_t MaximumUpdateOverhead = BlockSize - 1;
33
34 virtual Result onProcess(Span<const char> input, Span<char> output) override
35 {
36 if (output.sizeInBytes() < BlockSize)
37 {
38 cipher.reset();
40 Result::Error(AsyncStreamsResultCategory, AsyncStreamsError::CipherOutputBufferTooSmall));
41 AsyncTransformStream::afterProcess({}, output);
42 return Result(true);
43 }
44
45 const size_t inputSize = input.sizeInBytes() < output.sizeInBytes() - MaximumUpdateOverhead
46 ? input.sizeInBytes()
47 : output.sizeInBytes() - MaximumUpdateOverhead;
48 Span<const char> inputChunk;
49 SC_TRY(input.sliceStartLength(0, inputSize, inputChunk));
50
51 size_t bytesWritten = 0;
52 auto result = cipher.update(inputChunk.reinterpret_as_span_of<const uint8_t>(),
53 output.reinterpret_as_span_of<uint8_t>(), bytesWritten);
54 if (not result or bytesWritten > output.sizeInBytes())
55 {
56 cipher.reset();
57 if (result)
59 Result::Error(AsyncStreamsResultCategory, AsyncStreamsError::CipherInvalidOutputSize));
60 else
62 AsyncTransformStream::afterProcess({}, output);
63 return Result(true);
64 }
65
66 Span<const char> inputAfter;
67 Span<char> outputAfter;
68 SC_TRY(input.sliceStart(inputSize, inputAfter));
69 SC_TRY(output.sliceStart(bytesWritten, outputAfter));
70 AsyncTransformStream::afterProcess(inputAfter, outputAfter);
71 return Result(true);
72 }
73
74 virtual Result onFinalize(Span<char> output) override
75 {
76 if (output.sizeInBytes() < BlockSize)
77 {
78 cipher.reset();
80 Result::Error(AsyncStreamsResultCategory, AsyncStreamsError::CipherOutputBufferTooSmall));
81 AsyncTransformStream::afterFinalize(output, true);
82 return Result(true);
83 }
84
85 size_t bytesWritten = 0;
86 auto result = cipher.finish(output.reinterpret_as_span_of<uint8_t>(), bytesWritten);
87 if (not result or bytesWritten > output.sizeInBytes())
88 {
89 cipher.reset();
90 if (result)
92 Result::Error(AsyncStreamsResultCategory, AsyncStreamsError::CipherInvalidOutputSize));
93 else
95 AsyncTransformStream::afterFinalize(output, true);
96 return Result(true);
97 }
98
99 Span<char> outputAfter;
100 SC_TRY(output.sliceStart(bytesWritten, outputAfter));
101 AsyncTransformStream::afterFinalize(outputAfter, true);
102 return Result(true);
103 }
104
105 virtual Result asyncDestroyReadable() override
106 {
107 cipher.reset();
109 }
110
111 virtual Result asyncDestroyWritable() override
112 {
113 cipher.reset();
115 return Result(true);
116 }
117};
118
123template <typename T_Hmac>
125{
126 T_Hmac hmac;
127
128 AsyncHmacWritableStreamT() = default;
129
130 template <typename T_Argument>
131 explicit AsyncHmacWritableStreamT(T_Argument&& argument) : hmac(forward<T_Argument>(argument))
132 {}
133
134 private:
135 virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function<void(AsyncBufferView::ID)> callback) override
136 {
137 Span<const char> data;
138 SC_TRY(getBuffersPool().getReadableData(bufferID, data));
139 auto result = hmac.add(data.reinterpret_as_span_of<const uint8_t>());
140 if (not result)
141 hmac.reset();
142 finishedWriting(bufferID, move(callback), result);
143 return Result(true);
144 }
145
146 virtual Result asyncDestroyWritable() override
147 {
148 hmac.reset();
150 return Result(true);
151 }
152};
153} // namespace SC
Definition AsyncStreams.h:67
Adapts an allocation-free streaming cipher session to AsyncTransformStream.
Definition CryptographyTransformStreams.h:21
Adapts an incremental message-authentication session to AsyncWritableStream.
Definition CryptographyTransformStreams.h:125
Result finishedDestroyingReadable()
Called from inside asyncDestroy to transition from Destroying to Destroyed state (emitting eventClose...
A duplex stream that produces new buffers transforming received buffers.
Definition AsyncStreams.h:506
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:365
void emitError(Result error)
Signals an async error received.
void finishedDestroyingWritable()
Function that MUST be called by re-implementations of asyncDestroyWritable once they're done.
void finishedWriting(AsyncBufferView::ID bufferID, Function< void(AsyncBufferView::ID)> &&cb, Result res)
Signals that the given buffer (previously queued by write) has been fully written.
AsyncBuffersPool & getBuffersPool()
Obtains the buffers pool to access its data.