Branch data Line data Source code
1 : : /* SPDX-FileCopyrightText: Copyright 2026 Cozens Software Solutions Limited
2 : : * SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0 OR LicenseRef-COSOSO-Commercial
3 : : */
4 : :
5 : : #include "SolidSyslogWolfSslSettings.h"
6 : :
7 : : #include "SolidSyslogWolfSslAesGcmPolicy.h"
8 : :
9 : : #include <stdbool.h>
10 : : #include <stddef.h>
11 : : #include <stdint.h>
12 : : #include <wolfssl/wolfcrypt/memory.h>
13 : : #include <wolfssl/wolfcrypt/random.h>
14 : : #include <wolfssl/wolfcrypt/types.h>
15 : :
16 : : #include "SolidSyslogError.h"
17 : : #include "SolidSyslogErrorCategory.h"
18 : : #include "SolidSyslogWolfSslAesGcmPolicyErrors.h"
19 : : #include "SolidSyslogWolfSslAesGcmPolicyPrivate.h"
20 : : #include "SolidSyslogPrival.h"
21 : : #include "SolidSyslogSecurityPolicyCategories.h"
22 : : #include "SolidSyslogSecurityPolicyDefinition.h"
23 : :
24 : : const struct SolidSyslogErrorSource SolidSyslogWolfSslAesGcmPolicyErrorSource = {
25 : : "WolfSslAesGcmPolicy",
26 : : SolidSyslogAesGcmPolicyErrors_Name
27 : : };
28 : :
29 : : static inline struct SolidSyslogWolfSslAesGcmPolicy* WolfSslAesGcmPolicy_SelfFromBase(
30 : : struct SolidSyslogSecurityPolicy* base
31 : : );
32 : : static bool WolfSslAesGcmPolicy_SealRecord(
33 : : struct SolidSyslogSecurityPolicy* base,
34 : : const struct SolidSyslogSecurityRecord* record
35 : : );
36 : : static enum SolidSyslogSecurityPolicyOpenResult WolfSslAesGcmPolicy_OpenRecord(
37 : : struct SolidSyslogSecurityPolicy* base,
38 : : const struct SolidSyslogSecurityRecord* record
39 : : );
40 : : static bool WolfSslAesGcmPolicy_FetchKey(struct SolidSyslogWolfSslAesGcmPolicy* self, uint8_t* keyOut);
41 : : static void WolfSslAesGcmPolicy_ReportFault(
42 : : struct SolidSyslogWolfSslAesGcmPolicy* self,
43 : : uint16_t category,
44 : : enum SolidSyslogAesGcmPolicyErrors code
45 : : );
46 : :
47 : 59 : void SolidSyslogWolfSslAesGcmPolicy_Initialise(
48 : : struct SolidSyslogSecurityPolicy* base,
49 : : const struct SolidSyslogWolfSslAesGcmPolicyConfig* config
50 : : )
51 : : {
52 : 59 : struct SolidSyslogWolfSslAesGcmPolicy* self = WolfSslAesGcmPolicy_SelfFromBase(base);
53 : 59 : self->Base.TrailerSize = SOLIDSYSLOG_WOLFSSL_AES_GCM_POLICY_TRAILER_SIZE;
54 : 59 : self->Base.SealRecord = WolfSslAesGcmPolicy_SealRecord;
55 : 59 : self->Base.OpenRecord = WolfSslAesGcmPolicy_OpenRecord;
56 : 59 : self->Config = *config;
57 : 59 : self->FaultReported = false;
58 : 59 : }
59 : :
60 : 59 : void SolidSyslogWolfSslAesGcmPolicy_Cleanup(struct SolidSyslogSecurityPolicy* base)
61 : : {
62 : : /* No owned resources to release - the key is fetched on demand via the
63 : : * GetKey callback and never stored on the instance, and the RNG is
64 : : * caller-owned. */
65 : : (void) base;
66 : 59 : }
67 : :
68 : 149 : static inline struct SolidSyslogWolfSslAesGcmPolicy* WolfSslAesGcmPolicy_SelfFromBase(
69 : : struct SolidSyslogSecurityPolicy* base
70 : : )
71 : : {
72 : : /* Base is the first member of the instance struct - see Private.h. */
73 : 149 : return (struct SolidSyslogWolfSslAesGcmPolicy*) base;
74 : : }
75 : :
76 : : /* Seals in place: draws a fresh nonce into Trailer[0..SOLIDSYSLOG_WOLFSSL_AES_GCM_POLICY_NONCE_SIZE), then
77 : : * GcmEncrypt encrypts the body (Content past HeaderLength) and writes the tag to
78 : : * the remaining trailer bytes, authenticating the header (Content[0..HeaderLength))
79 : : * as associated data. Fetches the key on demand and wipes it before returning. */
80 : 52 : static bool WolfSslAesGcmPolicy_SealRecord(
81 : : struct SolidSyslogSecurityPolicy* base,
82 : : const struct SolidSyslogSecurityRecord* record
83 : : )
84 : : {
85 : 52 : struct SolidSyslogWolfSslAesGcmPolicy* self = WolfSslAesGcmPolicy_SelfFromBase(base);
86 : :
87 : 52 : bool sealed = false;
88 : : uint8_t key[SOLIDSYSLOG_WOLFSSL_AES_GCM_POLICY_KEY_SIZE];
89 [ + + ]: 52 : if (WolfSslAesGcmPolicy_FetchKey(self, key))
90 : : {
91 : : /* Draw the per-record nonce straight into the trailer; GcmEncrypt reads
92 : : * it back from there and writes the tag immediately after it. */
93 [ + + ]: 46 : if (wc_RNG_GenerateBlock(self->Config.Rng, record->Trailer, SOLIDSYSLOG_WOLFSSL_AES_GCM_POLICY_NONCE_SIZE) == 0)
94 : : {
95 [ + + ]: 44 : if (SolidSyslogWolfSslAesGcmPolicy_GcmEncrypt(record, key))
96 : : {
97 : 39 : sealed = true;
98 : 39 : self->FaultReported = false;
99 : : }
100 : : else
101 : : {
102 : 5 : WolfSslAesGcmPolicy_ReportFault(
103 : : self,
104 : : SOLIDSYSLOG_CAT_SECURITY_POLICY_SEAL_FAILED,
105 : : SOLIDSYSLOG_AES_GCM_POLICY_ERROR_ENCRYPT_FAILED
106 : : );
107 : : }
108 : : }
109 : : else
110 : : {
111 : 2 : WolfSslAesGcmPolicy_ReportFault(
112 : : self,
113 : : SOLIDSYSLOG_CAT_SECURITY_POLICY_SEAL_FAILED,
114 : : SOLIDSYSLOG_AES_GCM_POLICY_ERROR_NONCE_FAILED
115 : : );
116 : : }
117 : : }
118 : 52 : wc_ForceZero(key, sizeof key);
119 : 52 : return sealed;
120 : : }
121 : :
122 : : /* Fetches the AES-256 key on demand. Fails closed (and reports) if the key is
123 : : * unavailable or not exactly 32 bytes - AES-256 admits no other key length. */
124 : 90 : static bool WolfSslAesGcmPolicy_FetchKey(struct SolidSyslogWolfSslAesGcmPolicy* self, uint8_t* keyOut)
125 : : {
126 : 90 : size_t keyLength = 0U;
127 : 90 : bool fetched =
128 [ + + ]: 163 : self->Config.GetKey(self->Config.KeyContext, keyOut, SOLIDSYSLOG_WOLFSSL_AES_GCM_POLICY_KEY_SIZE, &keyLength) &&
129 [ + + ]: 73 : (keyLength == (size_t) SOLIDSYSLOG_WOLFSSL_AES_GCM_POLICY_KEY_SIZE);
130 [ + + ]: 90 : if (!fetched)
131 : : {
132 : 18 : WolfSslAesGcmPolicy_ReportFault(
133 : : self,
134 : : SOLIDSYSLOG_CAT_SECURITY_POLICY_KEY_UNAVAILABLE,
135 : : SOLIDSYSLOG_AES_GCM_POLICY_ERROR_KEY_UNAVAILABLE
136 : : );
137 : : }
138 : 90 : return fetched;
139 : : }
140 : :
141 : : /* The first fault in a run is the one reported. */
142 : 30 : static void WolfSslAesGcmPolicy_ReportFault(
143 : : struct SolidSyslogWolfSslAesGcmPolicy* self,
144 : : uint16_t category,
145 : : enum SolidSyslogAesGcmPolicyErrors code
146 : : )
147 : : {
148 [ + + ]: 30 : if (!self->FaultReported)
149 : : {
150 : 25 : WolfSslAesGcmPolicy_Report(SOLIDSYSLOG_SEVERITY_ERROR, category, code);
151 : 25 : self->FaultReported = true;
152 : : }
153 : 30 : }
154 : :
155 : 38 : static enum SolidSyslogSecurityPolicyOpenResult WolfSslAesGcmPolicy_OpenRecord(
156 : : struct SolidSyslogSecurityPolicy* base,
157 : : const struct SolidSyslogSecurityRecord* record
158 : : )
159 : : {
160 : 38 : struct SolidSyslogWolfSslAesGcmPolicy* self = WolfSslAesGcmPolicy_SelfFromBase(base);
161 : :
162 : 38 : enum SolidSyslogSecurityPolicyOpenResult result = SOLIDSYSLOG_SECURITY_POLICY_OPEN_COULD_NOT_RUN;
163 : : uint8_t key[SOLIDSYSLOG_WOLFSSL_AES_GCM_POLICY_KEY_SIZE];
164 [ + + ]: 38 : if (WolfSslAesGcmPolicy_FetchKey(self, key))
165 : : {
166 : 26 : result = SolidSyslogWolfSslAesGcmPolicy_GcmDecrypt(record, key);
167 [ + + ]: 26 : if (result == SOLIDSYSLOG_SECURITY_POLICY_OPEN_COULD_NOT_RUN)
168 : : {
169 : 5 : WolfSslAesGcmPolicy_ReportFault(
170 : : self,
171 : : SOLIDSYSLOG_CAT_SECURITY_POLICY_OPEN_FAILED,
172 : : SOLIDSYSLOG_AES_GCM_POLICY_ERROR_DECRYPT_FAILED
173 : : );
174 : : }
175 : : else
176 : : {
177 : : /* A verdict: the run of faults is over. */
178 : 21 : self->FaultReported = false;
179 : : }
180 : : }
181 : 38 : wc_ForceZero(key, sizeof key);
182 : 38 : return result;
183 : : }
|