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("AsyncCipherTransformStreamT - output buffers must be at least 16 bytes"));
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 Result 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 AsyncWritableStream::emitError(result ? Result::Error("AsyncCipherTransformStreamT - invalid output size")
58 : result);
59 AsyncTransformStream::afterProcess({}, output);
60 return Result(true);
61 }
62
63 Span<const char> inputAfter;
64 Span<char> outputAfter;
65 SC_TRY(input.sliceStart(inputSize, inputAfter));
66 SC_TRY(output.sliceStart(bytesWritten, outputAfter));
67 AsyncTransformStream::afterProcess(inputAfter, outputAfter);
68 return Result(true);
69 }
70
71 virtual Result onFinalize(Span<char> output) override
72 {
73 if (output.sizeInBytes() < BlockSize)
74 {
75 cipher.reset();
77 Result::Error("AsyncCipherTransformStreamT - output buffers must be at least 16 bytes"));
78 AsyncTransformStream::afterFinalize(output, true);
79 return Result(true);
80 }
81
82 size_t bytesWritten = 0;
83 Result result = cipher.finish(output.reinterpret_as_span_of<uint8_t>(), bytesWritten);
84 if (not result or bytesWritten > output.sizeInBytes())
85 {
86 cipher.reset();
87 AsyncWritableStream::emitError(result ? Result::Error("AsyncCipherTransformStreamT - invalid output size")
88 : result);
89 AsyncTransformStream::afterFinalize(output, true);
90 return Result(true);
91 }
92
93 Span<char> outputAfter;
94 SC_TRY(output.sliceStart(bytesWritten, outputAfter));
95 AsyncTransformStream::afterFinalize(outputAfter, true);
96 return Result(true);
97 }
98
99 virtual Result asyncDestroyReadable() override
100 {
101 cipher.reset();
103 }
104
105 virtual Result asyncDestroyWritable() override
106 {
107 cipher.reset();
109 return Result(true);
110 }
111};
112
117template <typename T_Hmac>
119{
120 T_Hmac hmac;
121
122 AsyncHmacWritableStreamT() = default;
123
124 template <typename T_Argument>
125 explicit AsyncHmacWritableStreamT(T_Argument&& argument) : hmac(forward<T_Argument>(argument))
126 {}
127
128 private:
129 virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function<void(AsyncBufferView::ID)> callback) override
130 {
131 Span<const char> data;
132 SC_TRY(getBuffersPool().getReadableData(bufferID, data));
133 Result result = hmac.add(data.reinterpret_as_span_of<const uint8_t>());
134 if (not result)
135 hmac.reset();
136 finishedWriting(bufferID, move(callback), result);
137 return Result(true);
138 }
139
140 virtual Result asyncDestroyWritable() override
141 {
142 hmac.reset();
144 return Result(true);
145 }
146};
147} // namespace SC
Definition AsyncStreams.h:66
Adapts an allocation-free streaming cipher session to AsyncTransformStream.
Definition CryptographyTransformStreams.h:21
Adapts an incremental message-authentication session to AsyncWritableStream.
Definition CryptographyTransformStreams.h:119
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:503
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:364
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.