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

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