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

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