SolidSyslog coverage report
Current view: top level - Platform/WolfSsl/Source - SolidSyslogWolfSslHmacSha256Policy.c (source / functions) Coverage Total Hit
Test: SolidSyslog Lines: 100.0 % 64 64
Test Date: 2026-11-12 23:14:35 Functions: 100.0 % 11 11
Branches: 100.0 % 26 26

             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 "SolidSyslogWolfSslHmacSha256Policy.h"
       8                 :             : 
       9                 :             : #include <stdbool.h>
      10                 :             : #include <stddef.h>
      11                 :             : #include <stdint.h>
      12                 :             : #include <wolfssl/wolfcrypt/hmac.h>
      13                 :             : #include <wolfssl/wolfcrypt/memory.h>
      14                 :             : #include <wolfssl/wolfcrypt/types.h>
      15                 :             : 
      16                 :             : #include "SolidSyslogError.h"
      17                 :             : #include "SolidSyslogErrorCategory.h"
      18                 :             : #include "SolidSyslogPrival.h"
      19                 :             : #include "SolidSyslogSecurityPolicyCategories.h"
      20                 :             : #include "SolidSyslogSecurityPolicyDefinition.h"
      21                 :             : #include "SolidSyslogTunables.h"
      22                 :             : #include "SolidSyslogWolfSslHmacSha256PolicyErrors.h"
      23                 :             : #include "SolidSyslogWolfSslHmacSha256PolicyPrivate.h"
      24                 :             : 
      25                 :             : const struct SolidSyslogErrorSource SolidSyslogWolfSslHmacSha256PolicyErrorSource = {
      26                 :             :     "WolfSslHmacSha256Policy",
      27                 :             :     SolidSyslogHmacSha256PolicyErrors_Name
      28                 :             : };
      29                 :             : 
      30                 :             : enum
      31                 :             : {
      32                 :             :     HMAC_SHA256_TAG_SIZE = 32,
      33                 :             :     /* RFC 2104 / NIST SP 800-107: an HMAC key should be at least the hash
      34                 :             :      * output length. A shorter key (or an empty one) yields a well-defined but
      35                 :             :      * cryptographically worthless MAC, so we reject it and fail closed. */
      36                 :             :     HMAC_SHA256_MIN_KEY_SIZE = 32
      37                 :             : };
      38                 :             : 
      39                 :             : static inline struct SolidSyslogWolfSslHmacSha256Policy* WolfSslHmacSha256Policy_SelfFromBase(
      40                 :             :     struct SolidSyslogSecurityPolicy* base
      41                 :             : );
      42                 :             : static bool WolfSslHmacSha256Policy_SealRecord(
      43                 :             :     struct SolidSyslogSecurityPolicy* base,
      44                 :             :     const struct SolidSyslogSecurityRecord* record
      45                 :             : );
      46                 :             : static enum SolidSyslogSecurityPolicyOpenResult WolfSslHmacSha256Policy_OpenRecord(
      47                 :             :     struct SolidSyslogSecurityPolicy* base,
      48                 :             :     const struct SolidSyslogSecurityRecord* record
      49                 :             : );
      50                 :             : static bool WolfSslHmacSha256Policy_ComputeTag(
      51                 :             :     struct SolidSyslogWolfSslHmacSha256Policy* self,
      52                 :             :     const uint8_t* data,
      53                 :             :     uint16_t length,
      54                 :             :     uint8_t* tagOut,
      55                 :             :     uint16_t failureCategory
      56                 :             : );
      57                 :             : static bool WolfSslHmacSha256Policy_FetchKey(
      58                 :             :     struct SolidSyslogWolfSslHmacSha256Policy* self,
      59                 :             :     uint8_t* keyOut,
      60                 :             :     size_t* keyLengthOut
      61                 :             : );
      62                 :             : static bool WolfSslHmacSha256Policy_Hmac(
      63                 :             :     const uint8_t* key,
      64                 :             :     size_t keyLength,
      65                 :             :     const uint8_t* data,
      66                 :             :     uint16_t length,
      67                 :             :     uint8_t* tagOut
      68                 :             : );
      69                 :             : static void WolfSslHmacSha256Policy_ReportFault(
      70                 :             :     struct SolidSyslogWolfSslHmacSha256Policy* self,
      71                 :             :     uint16_t category,
      72                 :             :     enum SolidSyslogHmacSha256PolicyErrors code
      73                 :             : );
      74                 :             : static inline bool WolfSslHmacSha256Policy_KeyLengthIsValid(size_t keyLength);
      75                 :             : static inline bool WolfSslHmacSha256Policy_ConstantTimeEquals(const uint8_t* a, const uint8_t* b, size_t length);
      76                 :             : 
      77                 :          50 : void SolidSyslogWolfSslHmacSha256Policy_Initialise(
      78                 :             :     struct SolidSyslogSecurityPolicy* base,
      79                 :             :     const struct SolidSyslogWolfSslHmacSha256PolicyConfig* config
      80                 :             : )
      81                 :             : {
      82                 :          50 :     struct SolidSyslogWolfSslHmacSha256Policy* self = WolfSslHmacSha256Policy_SelfFromBase(base);
      83                 :          50 :     self->Base.TrailerSize = HMAC_SHA256_TAG_SIZE;
      84                 :          50 :     self->Base.SealRecord = WolfSslHmacSha256Policy_SealRecord;
      85                 :          50 :     self->Base.OpenRecord = WolfSslHmacSha256Policy_OpenRecord;
      86                 :          50 :     self->Config = *config;
      87                 :          50 :     self->FaultReported = false;
      88                 :          50 : }
      89                 :             : 
      90                 :          50 : void SolidSyslogWolfSslHmacSha256Policy_Cleanup(struct SolidSyslogSecurityPolicy* base)
      91                 :             : {
      92                 :             :     /* No owned resources to release - the key is fetched on demand via the
      93                 :             :      * GetKey callback and never stored on the instance. */
      94                 :             :     (void) base;
      95                 :          50 : }
      96                 :             : 
      97                 :         123 : static inline struct SolidSyslogWolfSslHmacSha256Policy* WolfSslHmacSha256Policy_SelfFromBase(
      98                 :             :     struct SolidSyslogSecurityPolicy* base
      99                 :             : )
     100                 :             : {
     101                 :             :     /* Base is the first member of the instance struct - see Private.h. */
     102                 :         123 :     return (struct SolidSyslogWolfSslHmacSha256Policy*) base;
     103                 :             : }
     104                 :             : 
     105                 :             : /* HMAC authenticates the whole content as one buffer - the header/body split
     106                 :             :  * only matters to AEAD policies, so HeaderLength is ignored here. */
     107                 :          42 : static bool WolfSslHmacSha256Policy_SealRecord(
     108                 :             :     struct SolidSyslogSecurityPolicy* base,
     109                 :             :     const struct SolidSyslogSecurityRecord* record
     110                 :             : )
     111                 :             : {
     112                 :          42 :     uint8_t* tag = record->Trailer;
     113                 :          42 :     return WolfSslHmacSha256Policy_ComputeTag(
     114                 :             :         WolfSslHmacSha256Policy_SelfFromBase(base),
     115                 :          42 :         record->Content,
     116                 :          42 :         record->ContentLength,
     117                 :             :         tag,
     118                 :             :         SOLIDSYSLOG_CAT_SECURITY_POLICY_SEAL_FAILED
     119                 :             :     );
     120                 :             : }
     121                 :             : 
     122                 :             : /* Fetches the key on demand into a transient buffer, computes HMAC-SHA256 over
     123                 :             :  * `data` into `tagOut`, then wipes the key buffer - the key never lingers
     124                 :             :  * beyond a single computation. Returns false and reports the reason if the key
     125                 :             :  * is unavailable or the HMAC computation fails: no tag, so a seal fails and an
     126                 :             :  * open could not run. Shared by seal (writes the record tag) and verify
     127                 :             :  * (recomputes for comparison). */
     128                 :          73 : static bool WolfSslHmacSha256Policy_ComputeTag(
     129                 :             :     struct SolidSyslogWolfSslHmacSha256Policy* self,
     130                 :             :     const uint8_t* data,
     131                 :             :     uint16_t length,
     132                 :             :     uint8_t* tagOut,
     133                 :             :     uint16_t failureCategory
     134                 :             : )
     135                 :             : {
     136                 :             :     uint8_t key[SOLIDSYSLOG_MAX_HMAC_KEY_SIZE];
     137                 :          73 :     size_t keyLength = 0U;
     138                 :          73 :     bool computed = false;
     139         [ +  + ]:          73 :     if (WolfSslHmacSha256Policy_FetchKey(self, key, &keyLength))
     140                 :             :     {
     141         [ +  + ]:          54 :         if (WolfSslHmacSha256Policy_Hmac(key, keyLength, data, length, tagOut))
     142                 :             :         {
     143                 :             :             /* A tag to seal with or verify against: the run of faults is over. */
     144                 :          45 :             computed = true;
     145                 :          45 :             self->FaultReported = false;
     146                 :             :         }
     147                 :             :         else
     148                 :             :         {
     149                 :           9 :             WolfSslHmacSha256Policy_ReportFault(
     150                 :             :                 self,
     151                 :             :                 failureCategory,
     152                 :             :                 SOLIDSYSLOG_HMAC_SHA256_POLICY_ERROR_HMAC_FAILED
     153                 :             :             );
     154                 :             :         }
     155                 :             :     }
     156                 :             :     /* Wipe the whole key buffer - the full region GetKey was handed, not just
     157                 :             :      * the bytes written - so no key material lingers on the stack. */
     158                 :          73 :     wc_ForceZero(key, sizeof key);
     159                 :          73 :     return computed;
     160                 :             : }
     161                 :             : 
     162                 :             : /* Fetches the key on demand and validates its length. Fails closed (and
     163                 :             :  * reports) if the key is unavailable, or if its length falls outside
     164                 :             :  * [HMAC_SHA256_MIN_KEY_SIZE, sizeof buffer]. */
     165                 :          73 : static bool WolfSslHmacSha256Policy_FetchKey(
     166                 :             :     struct SolidSyslogWolfSslHmacSha256Policy* self,
     167                 :             :     uint8_t* keyOut,
     168                 :             :     size_t* keyLengthOut
     169                 :             : )
     170                 :             : {
     171                 :          73 :     size_t keyLength = 0U;
     172                 :          73 :     bool fetched = false;
     173         [ +  + ]:          73 :     if (self->Config.GetKey(self->Config.KeyContext, keyOut, SOLIDSYSLOG_MAX_HMAC_KEY_SIZE, &keyLength))
     174                 :             :     {
     175         [ +  + ]:          58 :         if (WolfSslHmacSha256Policy_KeyLengthIsValid(keyLength))
     176                 :             :         {
     177                 :          54 :             *keyLengthOut = keyLength;
     178                 :          54 :             fetched = true;
     179                 :             :         }
     180                 :             :         else
     181                 :             :         {
     182                 :           4 :             WolfSslHmacSha256Policy_ReportFault(
     183                 :             :                 self,
     184                 :             :                 SOLIDSYSLOG_CAT_SECURITY_POLICY_KEY_UNAVAILABLE,
     185                 :             :                 SOLIDSYSLOG_HMAC_SHA256_POLICY_ERROR_KEY_TOO_SHORT
     186                 :             :             );
     187                 :             :         }
     188                 :             :     }
     189                 :             :     else
     190                 :             :     {
     191                 :          15 :         WolfSslHmacSha256Policy_ReportFault(
     192                 :             :             self,
     193                 :             :             SOLIDSYSLOG_CAT_SECURITY_POLICY_KEY_UNAVAILABLE,
     194                 :             :             SOLIDSYSLOG_HMAC_SHA256_POLICY_ERROR_KEY_UNAVAILABLE
     195                 :             :         );
     196                 :             :     }
     197                 :          73 :     return fetched;
     198                 :             : }
     199                 :             : 
     200                 :             : /* One HMAC-SHA256 over `data` with a transient wolfCrypt context. Any step
     201                 :             :  * failing is one fault to the caller; the context is freed either way. */
     202                 :          54 : static bool WolfSslHmacSha256Policy_Hmac(
     203                 :             :     const uint8_t* key,
     204                 :             :     size_t keyLength,
     205                 :             :     const uint8_t* data,
     206                 :             :     uint16_t length,
     207                 :             :     uint8_t* tagOut
     208                 :             : )
     209                 :             : {
     210                 :             :     Hmac hmac;
     211                 :          54 :     bool ok = false;
     212         [ +  + ]:          54 :     if (wc_HmacInit(&hmac, NULL, INVALID_DEVID) == 0)
     213                 :             :     {
     214         [ +  + ]:         102 :         ok = (wc_HmacSetKey(&hmac, WC_SHA256, key, (word32) keyLength) == 0) &&
     215   [ +  +  +  + ]:         102 :              (wc_HmacUpdate(&hmac, data, length) == 0) && (wc_HmacFinal(&hmac, tagOut) == 0);
     216                 :          52 :         wc_HmacFree(&hmac);
     217                 :             :     }
     218                 :          54 :     return ok;
     219                 :             : }
     220                 :             : 
     221                 :             : /* The first fault in a run is the one reported. */
     222                 :          28 : static void WolfSslHmacSha256Policy_ReportFault(
     223                 :             :     struct SolidSyslogWolfSslHmacSha256Policy* self,
     224                 :             :     uint16_t category,
     225                 :             :     enum SolidSyslogHmacSha256PolicyErrors code
     226                 :             : )
     227                 :             : {
     228         [ +  + ]:          28 :     if (!self->FaultReported)
     229                 :             :     {
     230                 :          25 :         WolfSslHmacSha256Policy_Report(SOLIDSYSLOG_SEVERITY_ERROR, category, code);
     231                 :          25 :         self->FaultReported = true;
     232                 :             :     }
     233                 :          28 : }
     234                 :             : 
     235                 :          58 : static inline bool WolfSslHmacSha256Policy_KeyLengthIsValid(size_t keyLength)
     236                 :             : {
     237   [ +  +  +  + ]:          58 :     return (keyLength >= (size_t) HMAC_SHA256_MIN_KEY_SIZE) && (keyLength <= (size_t) SOLIDSYSLOG_MAX_HMAC_KEY_SIZE);
     238                 :             : }
     239                 :             : 
     240                 :          31 : static enum SolidSyslogSecurityPolicyOpenResult WolfSslHmacSha256Policy_OpenRecord(
     241                 :             :     struct SolidSyslogSecurityPolicy* base,
     242                 :             :     const struct SolidSyslogSecurityRecord* record
     243                 :             : )
     244                 :             : {
     245                 :             :     uint8_t expected[HMAC_SHA256_TAG_SIZE];
     246                 :          31 :     enum SolidSyslogSecurityPolicyOpenResult result = SOLIDSYSLOG_SECURITY_POLICY_OPEN_COULD_NOT_RUN;
     247         [ +  + ]:          31 :     if (WolfSslHmacSha256Policy_ComputeTag(
     248                 :             :             WolfSslHmacSha256Policy_SelfFromBase(base),
     249                 :          31 :             record->Content,
     250                 :          31 :             record->ContentLength,
     251                 :             :             expected,
     252                 :             :             SOLIDSYSLOG_CAT_SECURITY_POLICY_OPEN_FAILED
     253                 :             :         ))
     254                 :             :     {
     255                 :          16 :         result = WolfSslHmacSha256Policy_ConstantTimeEquals(expected, record->Trailer, HMAC_SHA256_TAG_SIZE)
     256                 :             :                      ? SOLIDSYSLOG_SECURITY_POLICY_OPEN_OPENED
     257                 :          16 :                      : SOLIDSYSLOG_SECURITY_POLICY_OPEN_REJECTED;
     258                 :             :     }
     259                 :          31 :     return result;
     260                 :             : }
     261                 :             : 
     262                 :          16 : static inline bool WolfSslHmacSha256Policy_ConstantTimeEquals(const uint8_t* a, const uint8_t* b, size_t length)
     263                 :             : {
     264                 :             :     /* Accumulate every byte difference so the loop runs the full length
     265                 :             :      * regardless of where a mismatch occurs - no early exit, no timing oracle
     266                 :             :      * on the tag comparison. */
     267                 :          16 :     uint8_t difference = 0U;
     268         [ +  + ]:         528 :     for (size_t index = 0U; index < length; index++)
     269                 :             :     {
     270                 :         512 :         difference |= (uint8_t) (a[index] ^ b[index]);
     271                 :             :     }
     272                 :          16 :     return difference == 0U;
     273                 :             : }
        

Generated by: LCOV version 2.0-1