Blame SOURCES/0009-semodule-libsemanage-move-module-hashing-into-libsem.patch

634418
From 066007029b3dd250305d7fac0bfd53aa1e4543cf Mon Sep 17 00:00:00 2001
634418
From: Ondrej Mosnacek <omosnace@redhat.com>
634418
Date: Thu, 3 Feb 2022 17:53:23 +0100
634418
Subject: [PATCH] semodule,libsemanage: move module hashing into libsemanage
634418
634418
The main goal of this move is to have the SHA-256 implementation under
634418
libsemanage, since upcoming patches will make use of SHA-256 for a
634418
different (but similar) purpose in libsemanage. Having the hashing code
634418
in libsemanage will reduce code duplication and allow for easier hash
634418
algorithm upgrade in the future.
634418
634418
Note that libselinux currently also contains a hash function
634418
implementation (for yet another different purpose). This patch doesn't
634418
make any effort to address that duplicity yet.
634418
634418
This patch also changes the format of the hash string printed by
634418
semodule to include the name of the hash. The intent is to avoid
634418
ambiguity and potential collisions when the algorithm is potentially
634418
changed in the future.
634418
634418
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
634418
---
634418
 libsemanage/include/semanage/modules.h |  26 +++
634418
 libsemanage/src/libsemanage.map        |   4 +
634418
 libsemanage/src/modules.c              |  59 +++++
634418
 libsemanage/src/sha256.c               | 294 +++++++++++++++++++++++++
634418
 libsemanage/src/sha256.h               |  89 ++++++++
634418
 5 files changed, 472 insertions(+)
634418
 create mode 100644 libsemanage/src/sha256.c
634418
 create mode 100644 libsemanage/src/sha256.h
634418
634418
diff --git a/libsemanage/include/semanage/modules.h b/libsemanage/include/semanage/modules.h
634418
index 4b93e54e..26ac40b2 100644
634418
--- a/libsemanage/include/semanage/modules.h
634418
+++ b/libsemanage/include/semanage/modules.h
634418
@@ -282,4 +282,30 @@ int semanage_module_get_enabled(semanage_handle_t *sh,
634418
 				const semanage_module_key_t *modkey,
634418
 				int *enabled);
634418
 
634418
+/* Compute checksum for @modkey module contents.
634418
+ *
634418
+ * If @checksum is NULL, the function will just return the length of the
634418
+ * checksum string in @checksum_len (checksum strings are guaranteed to
634418
+ * have a fixed length for a given libsemanage binary). @modkey and @cil
634418
+ * are ignored in this case and should be set to NULL and 0 (respectively).
634418
+ *
634418
+ * If @checksum is non-NULL, on success, @checksum will point to a buffer
634418
+ * containing the checksum string and @checksum_len will point to the
634418
+ * length of the string (without the null terminator). The semantics of
634418
+ * @cil are the same as for @extract_cil in semanage_module_extract().
634418
+ *
634418
+ * The caller is responsible to free the buffer returned in @checksum (using
634418
+ * free(3)).
634418
+ *
634418
+ * Callers may assume that if the checksum strings for two modules match,
634418
+ * the module content is the same (collisions are theoretically possible,
634418
+ * yet extremely unlikely).
634418
+ *
634418
+ * Returns 0 on success and -1 on error.
634418
+ */
634418
+extern int semanage_module_compute_checksum(semanage_handle_t *sh,
634418
+					    semanage_module_key_t *modkey,
634418
+					    int cil, char **checksum,
634418
+					    size_t *checksum_len);
634418
+
634418
 #endif
634418
diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
634418
index 02036696..a986b2d2 100644
634418
--- a/libsemanage/src/libsemanage.map
634418
+++ b/libsemanage/src/libsemanage.map
634418
@@ -63,3 +63,7 @@ LIBSEMANAGE_1.1 {
634418
 	  semanage_module_remove_key;
634418
 	  semanage_set_store_root;
634418
 } LIBSEMANAGE_1.0;
634418
+
634418
+LIBSEMANAGE_3.4 {
634418
+    semanage_module_compute_checksum;
634418
+} LIBSEMANAGE_1.1;
634418
diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
634418
index fa84d33e..3a82d275 100644
634418
--- a/libsemanage/src/modules.c
634418
+++ b/libsemanage/src/modules.c
634418
@@ -34,11 +34,13 @@
634418
 #include <fcntl.h>
634418
 #include <sys/types.h>
634418
 #include <sys/stat.h>
634418
+#include <sys/mman.h>
634418
 #include <errno.h>
634418
 #include <ctype.h>
634418
 
634418
 #include "handle.h"
634418
 #include "modules.h"
634418
+#include "sha256.h"
634418
 #include "debug.h"
634418
 
634418
 asm(".symver semanage_module_get_enabled_1_1,semanage_module_get_enabled@@LIBSEMANAGE_1.1");
634418
@@ -1146,3 +1148,60 @@ int semanage_module_remove_key(semanage_handle_t *sh,
634418
 	return sh->funcs->remove_key(sh, modkey);
634418
 }
634418
 
634418
+static const char CHECKSUM_TYPE[] = "sha256";
634418
+static const size_t CHECKSUM_CONTENT_SIZE = sizeof(CHECKSUM_TYPE) + 1 + 2 * SHA256_HASH_SIZE;
634418
+
634418
+static void semanage_hash_to_checksum_string(const uint8_t *hash, char *checksum)
634418
+{
634418
+	size_t i;
634418
+
634418
+	checksum += sprintf(checksum, "%s:", CHECKSUM_TYPE);
634418
+	for (i = 0; i < SHA256_HASH_SIZE; i++) {
634418
+		checksum += sprintf(checksum, "%02x", (unsigned)hash[i]);
634418
+	}
634418
+}
634418
+
634418
+int semanage_module_compute_checksum(semanage_handle_t *sh,
634418
+				     semanage_module_key_t *modkey,
634418
+				     int cil, char **checksum,
634418
+				     size_t *checksum_len)
634418
+{
634418
+	semanage_module_info_t *extract_info = NULL;
634418
+	Sha256Context context;
634418
+	SHA256_HASH sha256_hash;
634418
+	char *checksum_str;
634418
+	void *data;
634418
+	size_t data_len = 0;
634418
+	int result;
634418
+
634418
+	if (!checksum_len)
634418
+		return -1;
634418
+
634418
+	if (!checksum) {
634418
+		*checksum_len = CHECKSUM_CONTENT_SIZE;
634418
+		return 0;
634418
+	}
634418
+
634418
+	result = semanage_module_extract(sh, modkey, cil, &data, &data_len, &extract_info);
634418
+	if (result != 0)
634418
+		return -1;
634418
+
634418
+	semanage_module_info_destroy(sh, extract_info);
634418
+	free(extract_info);
634418
+
634418
+	Sha256Initialise(&context);
634418
+	Sha256Update(&context, data, data_len);
634418
+	Sha256Finalise(&context, &sha256_hash);
634418
+
634418
+	munmap(data, data_len);
634418
+
634418
+	checksum_str = malloc(CHECKSUM_CONTENT_SIZE + 1 /* '\0' */);
634418
+	if (!checksum_str)
634418
+		return -1;
634418
+
634418
+	semanage_hash_to_checksum_string(sha256_hash.bytes, checksum_str);
634418
+
634418
+	*checksum = checksum_str;
634418
+	*checksum_len = CHECKSUM_CONTENT_SIZE;
634418
+	return 0;
634418
+}
634418
diff --git a/libsemanage/src/sha256.c b/libsemanage/src/sha256.c
634418
new file mode 100644
634418
index 00000000..fe2aeef0
634418
--- /dev/null
634418
+++ b/libsemanage/src/sha256.c
634418
@@ -0,0 +1,294 @@
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  WjCryptLib_Sha256
634418
+//
634418
+//  Implementation of SHA256 hash function.
634418
+//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
634418
+//  Modified by WaterJuice retaining Public Domain license.
634418
+//
634418
+//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  IMPORTS
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+#include "sha256.h"
634418
+#include <memory.h>
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  MACROS
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
634418
+
634418
+#define MIN(x, y) ( ((x)<(y))?(x):(y) )
634418
+
634418
+#define STORE32H(x, y)                                                                     \
634418
+     { (y)[0] = (uint8_t)(((x)>>24)&255); (y)[1] = (uint8_t)(((x)>>16)&255);   \
634418
+       (y)[2] = (uint8_t)(((x)>>8)&255); (y)[3] = (uint8_t)((x)&255); }
634418
+
634418
+#define LOAD32H(x, y)                            \
634418
+     { x = ((uint32_t)((y)[0] & 255)<<24) | \
634418
+           ((uint32_t)((y)[1] & 255)<<16) | \
634418
+           ((uint32_t)((y)[2] & 255)<<8)  | \
634418
+           ((uint32_t)((y)[3] & 255)); }
634418
+
634418
+#define STORE64H(x, y)                                                                     \
634418
+   { (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255);     \
634418
+     (y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255);     \
634418
+     (y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255);     \
634418
+     (y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); }
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  CONSTANTS
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+// The K array
634418
+static const uint32_t K[64] = {
634418
+    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
634418
+    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
634418
+    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
634418
+    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
634418
+    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
634418
+    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
634418
+    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
634418
+    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
634418
+    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
634418
+    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
634418
+    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
634418
+    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
634418
+    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
634418
+};
634418
+
634418
+#define BLOCK_SIZE          64
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  INTERNAL FUNCTIONS
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+// Various logical functions
634418
+#define Ch( x, y, z )     (z ^ (x & (y ^ z)))
634418
+#define Maj( x, y, z )    (((x | y) & z) | (x & y))
634418
+#define S( x, n )         ror((x),(n))
634418
+#define R( x, n )         (((x)&0xFFFFFFFFUL)>>(n))
634418
+#define Sigma0( x )       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
634418
+#define Sigma1( x )       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
634418
+#define Gamma0( x )       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
634418
+#define Gamma1( x )       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
634418
+
634418
+#define Sha256Round( a, b, c, d, e, f, g, h, i )       \
634418
+     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
634418
+     t1 = Sigma0(a) + Maj(a, b, c);                    \
634418
+     d += t0;                                          \
634418
+     h  = t0 + t1;
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  TransformFunction
634418
+//
634418
+//  Compress 512-bits
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+static
634418
+void
634418
+    TransformFunction
634418
+    (
634418
+        Sha256Context*      Context,
634418
+        uint8_t const*      Buffer
634418
+    )
634418
+{
634418
+    uint32_t    S[8];
634418
+    uint32_t    W[64];
634418
+    uint32_t    t0;
634418
+    uint32_t    t1;
634418
+    uint32_t    t;
634418
+    int         i;
634418
+
634418
+    // Copy state into S
634418
+    for( i=0; i<8; i++ )
634418
+    {
634418
+        S[i] = Context->state[i];
634418
+    }
634418
+
634418
+    // Copy the state into 512-bits into W[0..15]
634418
+    for( i=0; i<16; i++ )
634418
+    {
634418
+        LOAD32H( W[i], Buffer + (4*i) );
634418
+    }
634418
+
634418
+    // Fill W[16..63]
634418
+    for( i=16; i<64; i++ )
634418
+    {
634418
+        W[i] = Gamma1( W[i-2]) + W[i-7] + Gamma0( W[i-15] ) + W[i-16];
634418
+    }
634418
+
634418
+    // Compress
634418
+    for( i=0; i<64; i++ )
634418
+    {
634418
+        Sha256Round( S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i );
634418
+        t = S[7];
634418
+        S[7] = S[6];
634418
+        S[6] = S[5];
634418
+        S[5] = S[4];
634418
+        S[4] = S[3];
634418
+        S[3] = S[2];
634418
+        S[2] = S[1];
634418
+        S[1] = S[0];
634418
+        S[0] = t;
634418
+    }
634418
+
634418
+    // Feedback
634418
+    for( i=0; i<8; i++ )
634418
+    {
634418
+        Context->state[i] = Context->state[i] + S[i];
634418
+    }
634418
+}
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  PUBLIC FUNCTIONS
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  Sha256Initialise
634418
+//
634418
+//  Initialises a SHA256 Context. Use this to initialise/reset a context.
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+void
634418
+    Sha256Initialise
634418
+    (
634418
+        Sha256Context*      Context         // [out]
634418
+    )
634418
+{
634418
+    Context->curlen = 0;
634418
+    Context->length = 0;
634418
+    Context->state[0] = 0x6A09E667UL;
634418
+    Context->state[1] = 0xBB67AE85UL;
634418
+    Context->state[2] = 0x3C6EF372UL;
634418
+    Context->state[3] = 0xA54FF53AUL;
634418
+    Context->state[4] = 0x510E527FUL;
634418
+    Context->state[5] = 0x9B05688CUL;
634418
+    Context->state[6] = 0x1F83D9ABUL;
634418
+    Context->state[7] = 0x5BE0CD19UL;
634418
+}
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  Sha256Update
634418
+//
634418
+//  Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
634418
+//  calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+void
634418
+    Sha256Update
634418
+    (
634418
+        Sha256Context*      Context,        // [in out]
634418
+        void const*         Buffer,         // [in]
634418
+        uint32_t            BufferSize      // [in]
634418
+    )
634418
+{
634418
+    uint32_t n;
634418
+
634418
+    if( Context->curlen > sizeof(Context->buf) )
634418
+    {
634418
+       return;
634418
+    }
634418
+
634418
+    while( BufferSize > 0 )
634418
+    {
634418
+        if( Context->curlen == 0 && BufferSize >= BLOCK_SIZE )
634418
+        {
634418
+           TransformFunction( Context, (uint8_t*)Buffer );
634418
+           Context->length += BLOCK_SIZE * 8;
634418
+           Buffer = (uint8_t*)Buffer + BLOCK_SIZE;
634418
+           BufferSize -= BLOCK_SIZE;
634418
+        }
634418
+        else
634418
+        {
634418
+           n = MIN( BufferSize, (BLOCK_SIZE - Context->curlen) );
634418
+           memcpy( Context->buf + Context->curlen, Buffer, (size_t)n );
634418
+           Context->curlen += n;
634418
+           Buffer = (uint8_t*)Buffer + n;
634418
+           BufferSize -= n;
634418
+           if( Context->curlen == BLOCK_SIZE )
634418
+           {
634418
+              TransformFunction( Context, Context->buf );
634418
+              Context->length += 8*BLOCK_SIZE;
634418
+              Context->curlen = 0;
634418
+           }
634418
+       }
634418
+    }
634418
+}
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  Sha256Finalise
634418
+//
634418
+//  Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
634418
+//  calling this, Sha256Initialised must be used to reuse the context.
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+void
634418
+    Sha256Finalise
634418
+    (
634418
+        Sha256Context*      Context,        // [in out]
634418
+        SHA256_HASH*        Digest          // [out]
634418
+    )
634418
+{
634418
+    int i;
634418
+
634418
+    if( Context->curlen >= sizeof(Context->buf) )
634418
+    {
634418
+       return;
634418
+    }
634418
+
634418
+    // Increase the length of the message
634418
+    Context->length += Context->curlen * 8;
634418
+
634418
+    // Append the '1' bit
634418
+    Context->buf[Context->curlen++] = (uint8_t)0x80;
634418
+
634418
+    // if the length is currently above 56 bytes we append zeros
634418
+    // then compress.  Then we can fall back to padding zeros and length
634418
+    // encoding like normal.
634418
+    if( Context->curlen > 56 )
634418
+    {
634418
+        while( Context->curlen < 64 )
634418
+        {
634418
+            Context->buf[Context->curlen++] = (uint8_t)0;
634418
+        }
634418
+        TransformFunction(Context, Context->buf);
634418
+        Context->curlen = 0;
634418
+    }
634418
+
634418
+    // Pad up to 56 bytes of zeroes
634418
+    while( Context->curlen < 56 )
634418
+    {
634418
+        Context->buf[Context->curlen++] = (uint8_t)0;
634418
+    }
634418
+
634418
+    // Store length
634418
+    STORE64H( Context->length, Context->buf+56 );
634418
+    TransformFunction( Context, Context->buf );
634418
+
634418
+    // Copy output
634418
+    for( i=0; i<8; i++ )
634418
+    {
634418
+        STORE32H( Context->state[i], Digest->bytes+(4*i) );
634418
+    }
634418
+}
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  Sha256Calculate
634418
+//
634418
+//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
634418
+//  buffer.
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+void
634418
+    Sha256Calculate
634418
+    (
634418
+        void  const*        Buffer,         // [in]
634418
+        uint32_t            BufferSize,     // [in]
634418
+        SHA256_HASH*        Digest          // [in]
634418
+    )
634418
+{
634418
+    Sha256Context context;
634418
+
634418
+    Sha256Initialise( &context );
634418
+    Sha256Update( &context, Buffer, BufferSize );
634418
+    Sha256Finalise( &context, Digest );
634418
+}
634418
diff --git a/libsemanage/src/sha256.h b/libsemanage/src/sha256.h
634418
new file mode 100644
634418
index 00000000..406ed869
634418
--- /dev/null
634418
+++ b/libsemanage/src/sha256.h
634418
@@ -0,0 +1,89 @@
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  WjCryptLib_Sha256
634418
+//
634418
+//  Implementation of SHA256 hash function.
634418
+//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
634418
+//  Modified by WaterJuice retaining Public Domain license.
634418
+//
634418
+//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+#pragma once
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  IMPORTS
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+#include <stdint.h>
634418
+#include <stdio.h>
634418
+
634418
+typedef struct
634418
+{
634418
+    uint64_t    length;
634418
+    uint32_t    state[8];
634418
+    uint32_t    curlen;
634418
+    uint8_t     buf[64];
634418
+} Sha256Context;
634418
+
634418
+#define SHA256_HASH_SIZE           ( 256 / 8 )
634418
+
634418
+typedef struct
634418
+{
634418
+    uint8_t      bytes [SHA256_HASH_SIZE];
634418
+} SHA256_HASH;
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  PUBLIC FUNCTIONS
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  Sha256Initialise
634418
+//
634418
+//  Initialises a SHA256 Context. Use this to initialise/reset a context.
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+void
634418
+    Sha256Initialise
634418
+    (
634418
+        Sha256Context*      Context         // [out]
634418
+    );
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  Sha256Update
634418
+//
634418
+//  Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
634418
+//  calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+void
634418
+    Sha256Update
634418
+    (
634418
+        Sha256Context*      Context,        // [in out]
634418
+        void const*         Buffer,         // [in]
634418
+        uint32_t            BufferSize      // [in]
634418
+    );
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  Sha256Finalise
634418
+//
634418
+//  Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
634418
+//  calling this, Sha256Initialised must be used to reuse the context.
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+void
634418
+    Sha256Finalise
634418
+    (
634418
+        Sha256Context*      Context,        // [in out]
634418
+        SHA256_HASH*        Digest          // [out]
634418
+    );
634418
+
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+//  Sha256Calculate
634418
+//
634418
+//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
634418
+//  buffer.
634418
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634418
+void
634418
+    Sha256Calculate
634418
+    (
634418
+        void  const*        Buffer,         // [in]
634418
+        uint32_t            BufferSize,     // [in]
634418
+        SHA256_HASH*        Digest          // [in]
634418
+    );
634418
-- 
634418
2.30.2
634418