Blame SOURCES/0041-semodule-add-m-checksum-option.patch

e061da
From e748832819b781507903838483376d308c90ca79 Mon Sep 17 00:00:00 2001
e061da
From: Petr Lautrbach <plautrba@redhat.com>
e061da
Date: Tue, 16 Nov 2021 14:27:11 +0100
e061da
Subject: [PATCH] semodule: add -m | --checksum option
e061da
e061da
Since cil doesn't store module name and module version in module itself,
e061da
there's no simple way how to compare that installed module is the same
e061da
version as the module which is supposed to be installed. Even though the
e061da
version was not used by semodule itself, it was apparently used by some
e061da
team.
e061da
e061da
With `semodule -l --checksum` users get SHA256 hashes of modules and
e061da
could compare them with their files which is faster than installing
e061da
modules again and again.
e061da
e061da
E.g.
e061da
e061da
    # time (
e061da
    semodule -l --checksum | grep localmodule
e061da
    /usr/libexec/selinux/hll/pp localmodule.pp | sha256sum
e061da
    )
e061da
    localmodule db002f64ddfa3983257b42b54da7b182c9b2e476f47880ae3494f9099e1a42bd
e061da
    db002f64ddfa3983257b42b54da7b182c9b2e476f47880ae3494f9099e1a42bd  -
e061da
e061da
    real    0m0.876s
e061da
    user    0m0.849s
e061da
    sys     0m0.028s
e061da
e061da
vs
e061da
e061da
    # time semodule -i localmodule.pp
e061da
e061da
    real    0m6.147s
e061da
    user    0m5.800s
e061da
    sys     0m0.231s
e061da
e061da
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
e061da
Acked-by: James Carter <jwcart2@gmail.com>
e061da
---
e061da
 policycoreutils/semodule/Makefile   |   2 +-
e061da
 policycoreutils/semodule/semodule.8 |   6 +
e061da
 policycoreutils/semodule/semodule.c |  95 ++++++++-
e061da
 policycoreutils/semodule/sha256.c   | 294 ++++++++++++++++++++++++++++
e061da
 policycoreutils/semodule/sha256.h   |  89 +++++++++
e061da
 5 files changed, 480 insertions(+), 6 deletions(-)
e061da
 create mode 100644 policycoreutils/semodule/sha256.c
e061da
 create mode 100644 policycoreutils/semodule/sha256.h
e061da
e061da
diff --git a/policycoreutils/semodule/Makefile b/policycoreutils/semodule/Makefile
e061da
index 73801e487a76..9875ac383280 100644
e061da
--- a/policycoreutils/semodule/Makefile
e061da
+++ b/policycoreutils/semodule/Makefile
e061da
@@ -6,7 +6,7 @@ MANDIR = $(PREFIX)/share/man
e061da
 
e061da
 CFLAGS ?= -Werror -Wall -W
e061da
 override LDLIBS += -lsepol -lselinux -lsemanage
e061da
-SEMODULE_OBJS = semodule.o
e061da
+SEMODULE_OBJS = semodule.o sha256.o
e061da
 
e061da
 all: semodule genhomedircon
e061da
 
e061da
diff --git a/policycoreutils/semodule/semodule.8 b/policycoreutils/semodule/semodule.8
e061da
index 18d4f708661c..3a2fb21c2481 100644
e061da
--- a/policycoreutils/semodule/semodule.8
e061da
+++ b/policycoreutils/semodule/semodule.8
e061da
@@ -95,6 +95,9 @@ only modules listed in \-\-extract after this option.
e061da
 .B  \-H,\-\-hll
e061da
 Extract module as an HLL file. This only affects the \-\-extract option and
e061da
 only modules listed in \-\-extract after this option.
e061da
+.TP
e061da
+.B  \-m,\-\-checksum
e061da
+Add SHA256 checksum of modules to the list output.
e061da
 
e061da
 .SH EXAMPLE
e061da
 .nf
e061da
@@ -130,6 +133,9 @@ $ semodule \-B \-S "/tmp/var/lib/selinux"
e061da
 # Write the HLL version of puppet and the CIL version of wireshark
e061da
 # modules at priority 400 to the current working directory
e061da
 $ semodule \-X 400 \-\-hll \-E puppet \-\-cil \-E wireshark
e061da
+# Check whether a module in "localmodule.pp" file is same as installed module "localmodule"
e061da
+$ /usr/libexec/selinux/hll/pp localmodule.pp | sha256sum
e061da
+$ semodule -l -m | grep localmodule
e061da
 .fi
e061da
 
e061da
 .SH SEE ALSO
e061da
diff --git a/policycoreutils/semodule/semodule.c b/policycoreutils/semodule/semodule.c
e061da
index a76797f505cd..300a97d735cc 100644
e061da
--- a/policycoreutils/semodule/semodule.c
e061da
+++ b/policycoreutils/semodule/semodule.c
e061da
@@ -24,6 +24,8 @@
e061da
 
e061da
 #include <semanage/modules.h>
e061da
 
e061da
+#include "sha256.h"
e061da
+
e061da
 enum client_modes {
e061da
 	NO_MODE, INSTALL_M, REMOVE_M, EXTRACT_M, CIL_M, HLL_M,
e061da
 	LIST_M, RELOAD, PRIORITY_M, ENABLE_M, DISABLE_M
e061da
@@ -56,6 +58,7 @@ static semanage_handle_t *sh = NULL;
e061da
 static char *store;
e061da
 static char *store_root;
e061da
 int extract_cil = 0;
e061da
+static int checksum = 0;
e061da
 
e061da
 extern char *optarg;
e061da
 extern int optind;
e061da
@@ -146,6 +149,7 @@ static void usage(char *progname)
e061da
 	printf("  -S,--store-path  use an alternate path for the policy store root\n");
e061da
 	printf("  -c, --cil extract module as cil. This only affects module extraction.\n");
e061da
 	printf("  -H, --hll extract module as hll. This only affects module extraction.\n");
e061da
+	printf("  -m, --checksum   print module checksum (SHA256).\n");
e061da
 }
e061da
 
e061da
 /* Sets the global mode variable to new_mode, but only if no other
e061da
@@ -199,6 +203,7 @@ static void parse_command_line(int argc, char **argv)
e061da
 		{"disable", required_argument, NULL, 'd'},
e061da
 		{"path", required_argument, NULL, 'p'},
e061da
 		{"store-path", required_argument, NULL, 'S'},
e061da
+		{"checksum", 0, NULL, 'm'},
e061da
 		{NULL, 0, NULL, 0}
e061da
 	};
e061da
 	int extract_selected = 0;
e061da
@@ -209,7 +214,7 @@ static void parse_command_line(int argc, char **argv)
e061da
 	no_reload = 0;
e061da
 	priority = 400;
e061da
 	while ((i =
e061da
-		getopt_long(argc, argv, "s:b:hi:l::vr:u:RnNBDCPX:e:d:p:S:E:cH", opts,
e061da
+		getopt_long(argc, argv, "s:b:hi:l::vr:u:RnNBDCPX:e:d:p:S:E:cHm", opts,
e061da
 			    NULL)) != -1) {
e061da
 		switch (i) {
e061da
 		case 'b':
e061da
@@ -286,6 +291,9 @@ static void parse_command_line(int argc, char **argv)
e061da
 		case 'd':
e061da
 			set_mode(DISABLE_M, optarg);
e061da
 			break;
e061da
+		case 'm':
e061da
+			checksum = 1;
e061da
+			break;
e061da
 		case '?':
e061da
 		default:{
e061da
 				usage(argv[0]);
e061da
@@ -337,6 +345,61 @@ static void parse_command_line(int argc, char **argv)
e061da
 	}
e061da
 }
e061da
 
e061da
+/* Get module checksum */
e061da
+static char *hash_module_data(const char *module_name, const int prio) {
e061da
+	semanage_module_info_t *extract_info = NULL;
e061da
+	semanage_module_key_t *modkey = NULL;
e061da
+	Sha256Context context;
e061da
+	uint8_t sha256_hash[SHA256_HASH_SIZE];
e061da
+	char *sha256_buf = NULL;
e061da
+	void *data;
e061da
+	size_t data_len = 0, i;
e061da
+	int result;
e061da
+
e061da
+	result = semanage_module_key_create(sh, &modkey);
e061da
+	if (result != 0) {
e061da
+		goto cleanup_extract;
e061da
+	}
e061da
+
e061da
+	result = semanage_module_key_set_name(sh, modkey, module_name);
e061da
+	if (result != 0) {
e061da
+		goto cleanup_extract;
e061da
+	}
e061da
+
e061da
+	result = semanage_module_key_set_priority(sh, modkey, prio);
e061da
+	if (result != 0) {
e061da
+		goto cleanup_extract;
e061da
+	}
e061da
+
e061da
+	result = semanage_module_extract(sh, modkey, 1, &data, &data_len,
e061da
+									 &extract_info);
e061da
+	if (result != 0) {
e061da
+		goto cleanup_extract;
e061da
+	}
e061da
+
e061da
+	Sha256Initialise(&context);
e061da
+	Sha256Update(&context, data, data_len);
e061da
+
e061da
+	Sha256Finalise(&context, (SHA256_HASH *)sha256_hash);
e061da
+
e061da
+	sha256_buf = calloc(1, SHA256_HASH_SIZE * 2 + 1);
e061da
+
e061da
+	if (sha256_buf == NULL)
e061da
+		goto cleanup_extract;
e061da
+
e061da
+	for (i = 0; i < SHA256_HASH_SIZE; i++) {
e061da
+		sprintf((&sha256_buf[i * 2]), "%02x", sha256_hash[i]);
e061da
+	}
e061da
+	sha256_buf[i * 2] = 0;
e061da
+
e061da
+cleanup_extract:
e061da
+	semanage_module_info_destroy(sh, extract_info);
e061da
+	free(extract_info);
e061da
+	semanage_module_key_destroy(sh, modkey);
e061da
+	free(modkey);
e061da
+	return sha256_buf;
e061da
+}
e061da
+
e061da
 int main(int argc, char *argv[])
e061da
 {
e061da
 	int i, commit = 0;
e061da
@@ -544,6 +607,8 @@ cleanup_extract:
e061da
 				int modinfos_len = 0;
e061da
 				semanage_module_info_t *m = NULL;
e061da
 				int j = 0;
e061da
+				char *module_checksum = NULL;
e061da
+				uint16_t pri = 0;
e061da
 
e061da
 				if (verbose) {
e061da
 					printf
e061da
@@ -568,7 +633,18 @@ cleanup_extract:
e061da
 						result = semanage_module_info_get_name(sh, m, &name);
e061da
 						if (result != 0) goto cleanup_list;
e061da
 
e061da
-						printf("%s\n", name);
e061da
+						result = semanage_module_info_get_priority(sh, m, &pri);
e061da
+						if (result != 0) goto cleanup_list;
e061da
+
e061da
+						printf("%s", name);
e061da
+						if (checksum) {
e061da
+							module_checksum = hash_module_data(name, pri);
e061da
+							if (module_checksum) {
e061da
+								printf(" %s", module_checksum);
e061da
+								free(module_checksum);
e061da
+							}
e061da
+						}
e061da
+						printf("\n");
e061da
 					}
e061da
 				}
e061da
 				else if (strcmp(mode_arg, "full") == 0) {
e061da
@@ -583,11 +659,12 @@ cleanup_extract:
e061da
 					}
e061da
 
e061da
 					/* calculate column widths */
e061da
-					size_t column[4] = { 0, 0, 0, 0 };
e061da
+					size_t column[5] = { 0, 0, 0, 0, 0 };
e061da
 
e061da
 					/* fixed width columns */
e061da
 					column[0] = sizeof("000") - 1;
e061da
 					column[3] = sizeof("disabled") - 1;
e061da
+					column[4] = 64; /* SHA256_HASH_SIZE * 2 */
e061da
 
e061da
 					/* variable width columns */
e061da
 					const char *tmp = NULL;
e061da
@@ -610,7 +687,6 @@ cleanup_extract:
e061da
 
e061da
 					/* print out each module */
e061da
 					for (j = 0; j < modinfos_len; j++) {
e061da
-						uint16_t pri = 0;
e061da
 						const char *name = NULL;
e061da
 						int enabled = 0;
e061da
 						const char *lang_ext = NULL;
e061da
@@ -629,11 +705,20 @@ cleanup_extract:
e061da
 						result = semanage_module_info_get_lang_ext(sh, m, &lang_ext);
e061da
 						if (result != 0) goto cleanup_list;
e061da
 
e061da
-						printf("%0*u %-*s %-*s %-*s\n",
e061da
+						printf("%0*u %-*s %-*s %-*s",
e061da
 							(int)column[0], pri,
e061da
 							(int)column[1], name,
e061da
 							(int)column[2], lang_ext,
e061da
 							(int)column[3], enabled ? "" : "disabled");
e061da
+						if (checksum) {
e061da
+							module_checksum = hash_module_data(name, pri);
e061da
+							if (module_checksum) {
e061da
+								printf(" %-*s", (int)column[4], module_checksum);
e061da
+								free(module_checksum);
e061da
+							}
e061da
+						}
e061da
+						printf("\n");
e061da
+
e061da
 					}
e061da
 				}
e061da
 				else {
e061da
diff --git a/policycoreutils/semodule/sha256.c b/policycoreutils/semodule/sha256.c
e061da
new file mode 100644
e061da
index 000000000000..fe2aeef07f53
e061da
--- /dev/null
e061da
+++ b/policycoreutils/semodule/sha256.c
e061da
@@ -0,0 +1,294 @@
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  WjCryptLib_Sha256
e061da
+//
e061da
+//  Implementation of SHA256 hash function.
e061da
+//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
e061da
+//  Modified by WaterJuice retaining Public Domain license.
e061da
+//
e061da
+//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  IMPORTS
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+#include "sha256.h"
e061da
+#include <memory.h>
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  MACROS
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
e061da
+
e061da
+#define MIN(x, y) ( ((x)<(y))?(x):(y) )
e061da
+
e061da
+#define STORE32H(x, y)                                                                     \
e061da
+     { (y)[0] = (uint8_t)(((x)>>24)&255); (y)[1] = (uint8_t)(((x)>>16)&255);   \
e061da
+       (y)[2] = (uint8_t)(((x)>>8)&255); (y)[3] = (uint8_t)((x)&255); }
e061da
+
e061da
+#define LOAD32H(x, y)                            \
e061da
+     { x = ((uint32_t)((y)[0] & 255)<<24) | \
e061da
+           ((uint32_t)((y)[1] & 255)<<16) | \
e061da
+           ((uint32_t)((y)[2] & 255)<<8)  | \
e061da
+           ((uint32_t)((y)[3] & 255)); }
e061da
+
e061da
+#define STORE64H(x, y)                                                                     \
e061da
+   { (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255);     \
e061da
+     (y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255);     \
e061da
+     (y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255);     \
e061da
+     (y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); }
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  CONSTANTS
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+// The K array
e061da
+static const uint32_t K[64] = {
e061da
+    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
e061da
+    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
e061da
+    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
e061da
+    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
e061da
+    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
e061da
+    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
e061da
+    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
e061da
+    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
e061da
+    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
e061da
+    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
e061da
+    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
e061da
+    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
e061da
+    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
e061da
+};
e061da
+
e061da
+#define BLOCK_SIZE          64
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  INTERNAL FUNCTIONS
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+// Various logical functions
e061da
+#define Ch( x, y, z )     (z ^ (x & (y ^ z)))
e061da
+#define Maj( x, y, z )    (((x | y) & z) | (x & y))
e061da
+#define S( x, n )         ror((x),(n))
e061da
+#define R( x, n )         (((x)&0xFFFFFFFFUL)>>(n))
e061da
+#define Sigma0( x )       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
e061da
+#define Sigma1( x )       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
e061da
+#define Gamma0( x )       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
e061da
+#define Gamma1( x )       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
e061da
+
e061da
+#define Sha256Round( a, b, c, d, e, f, g, h, i )       \
e061da
+     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
e061da
+     t1 = Sigma0(a) + Maj(a, b, c);                    \
e061da
+     d += t0;                                          \
e061da
+     h  = t0 + t1;
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  TransformFunction
e061da
+//
e061da
+//  Compress 512-bits
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+static
e061da
+void
e061da
+    TransformFunction
e061da
+    (
e061da
+        Sha256Context*      Context,
e061da
+        uint8_t const*      Buffer
e061da
+    )
e061da
+{
e061da
+    uint32_t    S[8];
e061da
+    uint32_t    W[64];
e061da
+    uint32_t    t0;
e061da
+    uint32_t    t1;
e061da
+    uint32_t    t;
e061da
+    int         i;
e061da
+
e061da
+    // Copy state into S
e061da
+    for( i=0; i<8; i++ )
e061da
+    {
e061da
+        S[i] = Context->state[i];
e061da
+    }
e061da
+
e061da
+    // Copy the state into 512-bits into W[0..15]
e061da
+    for( i=0; i<16; i++ )
e061da
+    {
e061da
+        LOAD32H( W[i], Buffer + (4*i) );
e061da
+    }
e061da
+
e061da
+    // Fill W[16..63]
e061da
+    for( i=16; i<64; i++ )
e061da
+    {
e061da
+        W[i] = Gamma1( W[i-2]) + W[i-7] + Gamma0( W[i-15] ) + W[i-16];
e061da
+    }
e061da
+
e061da
+    // Compress
e061da
+    for( i=0; i<64; i++ )
e061da
+    {
e061da
+        Sha256Round( S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i );
e061da
+        t = S[7];
e061da
+        S[7] = S[6];
e061da
+        S[6] = S[5];
e061da
+        S[5] = S[4];
e061da
+        S[4] = S[3];
e061da
+        S[3] = S[2];
e061da
+        S[2] = S[1];
e061da
+        S[1] = S[0];
e061da
+        S[0] = t;
e061da
+    }
e061da
+
e061da
+    // Feedback
e061da
+    for( i=0; i<8; i++ )
e061da
+    {
e061da
+        Context->state[i] = Context->state[i] + S[i];
e061da
+    }
e061da
+}
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  PUBLIC FUNCTIONS
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  Sha256Initialise
e061da
+//
e061da
+//  Initialises a SHA256 Context. Use this to initialise/reset a context.
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+void
e061da
+    Sha256Initialise
e061da
+    (
e061da
+        Sha256Context*      Context         // [out]
e061da
+    )
e061da
+{
e061da
+    Context->curlen = 0;
e061da
+    Context->length = 0;
e061da
+    Context->state[0] = 0x6A09E667UL;
e061da
+    Context->state[1] = 0xBB67AE85UL;
e061da
+    Context->state[2] = 0x3C6EF372UL;
e061da
+    Context->state[3] = 0xA54FF53AUL;
e061da
+    Context->state[4] = 0x510E527FUL;
e061da
+    Context->state[5] = 0x9B05688CUL;
e061da
+    Context->state[6] = 0x1F83D9ABUL;
e061da
+    Context->state[7] = 0x5BE0CD19UL;
e061da
+}
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  Sha256Update
e061da
+//
e061da
+//  Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
e061da
+//  calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+void
e061da
+    Sha256Update
e061da
+    (
e061da
+        Sha256Context*      Context,        // [in out]
e061da
+        void const*         Buffer,         // [in]
e061da
+        uint32_t            BufferSize      // [in]
e061da
+    )
e061da
+{
e061da
+    uint32_t n;
e061da
+
e061da
+    if( Context->curlen > sizeof(Context->buf) )
e061da
+    {
e061da
+       return;
e061da
+    }
e061da
+
e061da
+    while( BufferSize > 0 )
e061da
+    {
e061da
+        if( Context->curlen == 0 && BufferSize >= BLOCK_SIZE )
e061da
+        {
e061da
+           TransformFunction( Context, (uint8_t*)Buffer );
e061da
+           Context->length += BLOCK_SIZE * 8;
e061da
+           Buffer = (uint8_t*)Buffer + BLOCK_SIZE;
e061da
+           BufferSize -= BLOCK_SIZE;
e061da
+        }
e061da
+        else
e061da
+        {
e061da
+           n = MIN( BufferSize, (BLOCK_SIZE - Context->curlen) );
e061da
+           memcpy( Context->buf + Context->curlen, Buffer, (size_t)n );
e061da
+           Context->curlen += n;
e061da
+           Buffer = (uint8_t*)Buffer + n;
e061da
+           BufferSize -= n;
e061da
+           if( Context->curlen == BLOCK_SIZE )
e061da
+           {
e061da
+              TransformFunction( Context, Context->buf );
e061da
+              Context->length += 8*BLOCK_SIZE;
e061da
+              Context->curlen = 0;
e061da
+           }
e061da
+       }
e061da
+    }
e061da
+}
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  Sha256Finalise
e061da
+//
e061da
+//  Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
e061da
+//  calling this, Sha256Initialised must be used to reuse the context.
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+void
e061da
+    Sha256Finalise
e061da
+    (
e061da
+        Sha256Context*      Context,        // [in out]
e061da
+        SHA256_HASH*        Digest          // [out]
e061da
+    )
e061da
+{
e061da
+    int i;
e061da
+
e061da
+    if( Context->curlen >= sizeof(Context->buf) )
e061da
+    {
e061da
+       return;
e061da
+    }
e061da
+
e061da
+    // Increase the length of the message
e061da
+    Context->length += Context->curlen * 8;
e061da
+
e061da
+    // Append the '1' bit
e061da
+    Context->buf[Context->curlen++] = (uint8_t)0x80;
e061da
+
e061da
+    // if the length is currently above 56 bytes we append zeros
e061da
+    // then compress.  Then we can fall back to padding zeros and length
e061da
+    // encoding like normal.
e061da
+    if( Context->curlen > 56 )
e061da
+    {
e061da
+        while( Context->curlen < 64 )
e061da
+        {
e061da
+            Context->buf[Context->curlen++] = (uint8_t)0;
e061da
+        }
e061da
+        TransformFunction(Context, Context->buf);
e061da
+        Context->curlen = 0;
e061da
+    }
e061da
+
e061da
+    // Pad up to 56 bytes of zeroes
e061da
+    while( Context->curlen < 56 )
e061da
+    {
e061da
+        Context->buf[Context->curlen++] = (uint8_t)0;
e061da
+    }
e061da
+
e061da
+    // Store length
e061da
+    STORE64H( Context->length, Context->buf+56 );
e061da
+    TransformFunction( Context, Context->buf );
e061da
+
e061da
+    // Copy output
e061da
+    for( i=0; i<8; i++ )
e061da
+    {
e061da
+        STORE32H( Context->state[i], Digest->bytes+(4*i) );
e061da
+    }
e061da
+}
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  Sha256Calculate
e061da
+//
e061da
+//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
e061da
+//  buffer.
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+void
e061da
+    Sha256Calculate
e061da
+    (
e061da
+        void  const*        Buffer,         // [in]
e061da
+        uint32_t            BufferSize,     // [in]
e061da
+        SHA256_HASH*        Digest          // [in]
e061da
+    )
e061da
+{
e061da
+    Sha256Context context;
e061da
+
e061da
+    Sha256Initialise( &context );
e061da
+    Sha256Update( &context, Buffer, BufferSize );
e061da
+    Sha256Finalise( &context, Digest );
e061da
+}
e061da
diff --git a/policycoreutils/semodule/sha256.h b/policycoreutils/semodule/sha256.h
e061da
new file mode 100644
e061da
index 000000000000..406ed869cd82
e061da
--- /dev/null
e061da
+++ b/policycoreutils/semodule/sha256.h
e061da
@@ -0,0 +1,89 @@
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  WjCryptLib_Sha256
e061da
+//
e061da
+//  Implementation of SHA256 hash function.
e061da
+//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
e061da
+//  Modified by WaterJuice retaining Public Domain license.
e061da
+//
e061da
+//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+#pragma once
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  IMPORTS
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+#include <stdint.h>
e061da
+#include <stdio.h>
e061da
+
e061da
+typedef struct
e061da
+{
e061da
+    uint64_t    length;
e061da
+    uint32_t    state[8];
e061da
+    uint32_t    curlen;
e061da
+    uint8_t     buf[64];
e061da
+} Sha256Context;
e061da
+
e061da
+#define SHA256_HASH_SIZE           ( 256 / 8 )
e061da
+
e061da
+typedef struct
e061da
+{
e061da
+    uint8_t      bytes [SHA256_HASH_SIZE];
e061da
+} SHA256_HASH;
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  PUBLIC FUNCTIONS
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  Sha256Initialise
e061da
+//
e061da
+//  Initialises a SHA256 Context. Use this to initialise/reset a context.
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+void
e061da
+    Sha256Initialise
e061da
+    (
e061da
+        Sha256Context*      Context         // [out]
e061da
+    );
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  Sha256Update
e061da
+//
e061da
+//  Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
e061da
+//  calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+void
e061da
+    Sha256Update
e061da
+    (
e061da
+        Sha256Context*      Context,        // [in out]
e061da
+        void const*         Buffer,         // [in]
e061da
+        uint32_t            BufferSize      // [in]
e061da
+    );
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  Sha256Finalise
e061da
+//
e061da
+//  Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
e061da
+//  calling this, Sha256Initialised must be used to reuse the context.
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+void
e061da
+    Sha256Finalise
e061da
+    (
e061da
+        Sha256Context*      Context,        // [in out]
e061da
+        SHA256_HASH*        Digest          // [out]
e061da
+    );
e061da
+
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+//  Sha256Calculate
e061da
+//
e061da
+//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
e061da
+//  buffer.
e061da
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
e061da
+void
e061da
+    Sha256Calculate
e061da
+    (
e061da
+        void  const*        Buffer,         // [in]
e061da
+        uint32_t            BufferSize,     // [in]
e061da
+        SHA256_HASH*        Digest          // [in]
e061da
+    );
e061da
-- 
e061da
2.33.1
e061da