Blob Blame History Raw
From 94859162dbf9d2ccd4ffb923720c654a4cb9150a Mon Sep 17 00:00:00 2001
From: Petr Lautrbach <plautrba@redhat.com>
Date: Fri, 30 Jul 2021 14:14:37 +0200
Subject: [PATCH] Use SHA-2 instead of SHA-1
Content-type: text/plain

The use of SHA-1 in RHEL9 is deprecated
---
 libselinux/include/selinux/label.h            |   6 +-
 libselinux/include/selinux/restorecon.h       |   4 +-
 libselinux/man/man3/selabel_digest.3          |   4 +-
 libselinux/man/man3/selabel_open.3            |   2 +-
 libselinux/man/man3/selinux_restorecon.3      |  18 +-
 .../man/man3/selinux_restorecon_xattr.3       |   2 +-
 libselinux/src/Makefile                       |   2 +-
 libselinux/src/label_file.c                   |  40 +--
 libselinux/src/label_internal.h               |  10 +-
 libselinux/src/label_support.c                |  10 +-
 libselinux/src/selinux_restorecon.c           |  24 +-
 libselinux/src/sha1.c                         | 220 -------------
 libselinux/src/sha1.h                         |  85 -----
 libselinux/src/sha256.c                       | 294 ++++++++++++++++++
 libselinux/src/sha256.h                       |  89 ++++++
 libselinux/utils/selabel_digest.c             |  26 +-
 .../selabel_get_digests_all_partial_matches.c |  28 +-
 17 files changed, 471 insertions(+), 393 deletions(-)
 delete mode 100644 libselinux/src/sha1.c
 delete mode 100644 libselinux/src/sha1.h
 create mode 100644 libselinux/src/sha256.c
 create mode 100644 libselinux/src/sha256.h

diff --git a/libselinux/include/selinux/label.h b/libselinux/include/selinux/label.h
index ce189a3ae2fe..ce77d32dfed1 100644
--- a/libselinux/include/selinux/label.h
+++ b/libselinux/include/selinux/label.h
@@ -120,13 +120,13 @@ extern int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con,
 					 const char *key, const char **aliases, int type);
 
 /**
- * selabel_digest - Retrieve the SHA1 digest and the list of specfiles used to
+ * selabel_digest - Retrieve the SHA256 digest and the list of specfiles used to
  *		    generate the digest. The SELABEL_OPT_DIGEST option must
  *		    be set in selabel_open() to initiate the digest generation.
  * @handle: specifies backend instance to query
- * @digest: returns a pointer to the SHA1 digest.
+ * @digest: returns a pointer to the SHA256 digest.
  * @digest_len: returns length of digest in bytes.
- * @specfiles: a list of specfiles used in the SHA1 digest generation.
+ * @specfiles: a list of specfiles used in the SHA256 digest generation.
  *	       The list is NULL terminated and will hold @num_specfiles entries.
  * @num_specfiles: number of specfiles in the list.
  *
diff --git a/libselinux/include/selinux/restorecon.h b/libselinux/include/selinux/restorecon.h
index b10fe684eff9..8df4744505b3 100644
--- a/libselinux/include/selinux/restorecon.h
+++ b/libselinux/include/selinux/restorecon.h
@@ -41,8 +41,8 @@ extern int selinux_restorecon_parallel(const char *pathname,
  * restorecon_flags options
  */
 /*
- * Force the checking of labels even if the stored SHA1 digest
- * matches the specfiles SHA1 digest (requires CAP_SYS_ADMIN).
+ * Force the checking of labels even if the stored SHA256 digest
+ * matches the specfiles SHA256 digest (requires CAP_SYS_ADMIN).
  */
 #define SELINUX_RESTORECON_IGNORE_DIGEST		0x00001
 /*
diff --git a/libselinux/man/man3/selabel_digest.3 b/libselinux/man/man3/selabel_digest.3
index 56a008f00df0..5f7c42533d0e 100644
--- a/libselinux/man/man3/selabel_digest.3
+++ b/libselinux/man/man3/selabel_digest.3
@@ -20,11 +20,11 @@ selabel_digest \- Return digest of specfiles and list of files used
 .BR selabel_digest ()
 performs an operation on the handle
 .IR hnd ,
-returning the results of the SHA1 digest pointed to by
+returning the results of the SHA256 digest pointed to by
 .IR digest ,
 whose length will be
 .IR digest_len .
-The list of specfiles used in the SHA1 digest calculation is returned in
+The list of specfiles used in the SHA256 digest calculation is returned in
 .I specfiles
 with the number of entries in
 .IR num_specfiles .
diff --git a/libselinux/man/man3/selabel_open.3 b/libselinux/man/man3/selabel_open.3
index 0e03e1be111e..14ab888d2e03 100644
--- a/libselinux/man/man3/selabel_open.3
+++ b/libselinux/man/man3/selabel_open.3
@@ -69,7 +69,7 @@ is used; a custom validation function can be provided via
 Note that an invalid context may not be treated as an error unless it is actually encountered during a lookup operation.
 .TP
 .B SELABEL_OPT_DIGEST
-A non-null value for this option enables the generation of an SHA1 digest of
+A non-null value for this option enables the generation of an SHA256 digest of
 the spec files loaded as described in
 .BR selabel_digest (3)
 .
diff --git a/libselinux/man/man3/selinux_restorecon.3 b/libselinux/man/man3/selinux_restorecon.3
index 218aaf6d2ae5..5f6d4b386429 100644
--- a/libselinux/man/man3/selinux_restorecon.3
+++ b/libselinux/man/man3/selinux_restorecon.3
@@ -36,7 +36,7 @@ If this is a directory and the
 .B SELINUX_RESTORECON_RECURSE
 has been set (for descending through directories), then
 .BR selinux_restorecon ()
-will write an SHA1 digest of specfile entries calculated by
+will write an SHA256 digest of specfile entries calculated by
 .BR selabel_get_digests_all_partial_matches (3)
 to an extended attribute of
 .IR security.sehash
@@ -55,7 +55,7 @@ will take place.
 .br
 The
 .IR restorecon_flags
-that can be used to manage the usage of the SHA1 digest are:
+that can be used to manage the usage of the SHA256 digest are:
 .RS
 .B SELINUX_RESTORECON_SKIP_DIGEST
 .br
@@ -73,8 +73,8 @@ Do not check or update any extended attribute
 entries.
 .sp
 .B SELINUX_RESTORECON_IGNORE_DIGEST
-force the checking of labels even if the stored SHA1 digest matches the
-specfile entries SHA1 digest. The specfile entries digest will be written to the
+force the checking of labels even if the stored SHA256 digest matches the
+specfile entries SHA256 digest. The specfile entries digest will be written to the
 .IR security.sehash
 extended attribute once relabeling has been completed successfully provided the
 .B SELINUX_RESTORECON_NOCHANGE
@@ -95,7 +95,7 @@ default specfile context.
 .sp
 .B SELINUX_RESTORECON_RECURSE
 change file and directory labels recursively (descend directories)
-and if successful write an SHA1 digest of the specfile entries to an
+and if successful write an SHA256 digest of the specfile entries to an
 extended attribute as described in the
 .B NOTES
 section.
@@ -179,12 +179,12 @@ for fetching the ignored (skipped) error count after
 or
 .BR selinux_restorecon_parallel (3)
 completes with success. In case any errors were skipped during the file tree
-walk, the specfile entries SHA1 digest will not have been written to the
+walk, the specfile entries SHA256 digest will not have been written to the
 .IR security.sehash
 extended attribute.
 .RE
 .sp
-The behavior regarding the checking and updating of the SHA1 digest described
+The behavior regarding the checking and updating of the SHA256 digest described
 above is the default behavior. It is possible to change this by first calling
 .BR selabel_open (3)
 and not enabling the
@@ -247,7 +247,7 @@ To improve performance when relabeling file systems recursively (e.g. the
 .B SELINUX_RESTORECON_RECURSE
 flag is set)
 .BR selinux_restorecon ()
-will write a calculated SHA1 digest of the specfile entries returned by
+will write a calculated SHA256 digest of the specfile entries returned by
 .BR selabel_get_digests_all_partial_matches (3)
 to an extended attribute named
 .IR security.sehash
@@ -269,7 +269,7 @@ Should any of the specfile entries have changed, then when
 .BR selinux_restorecon ()
 is run again with the
 .B SELINUX_RESTORECON_RECURSE
-flag set, new SHA1 digests will be calculated and all files automatically
+flag set, new SHA256 digests will be calculated and all files automatically
 relabeled depending on the settings of the
 .B SELINUX_RESTORECON_SET_SPECFILE_CTX
 flag (provided
diff --git a/libselinux/man/man3/selinux_restorecon_xattr.3 b/libselinux/man/man3/selinux_restorecon_xattr.3
index c56326814b94..098c840fc59b 100644
--- a/libselinux/man/man3/selinux_restorecon_xattr.3
+++ b/libselinux/man/man3/selinux_restorecon_xattr.3
@@ -119,7 +119,7 @@ By default
 .BR selinux_restorecon_xattr (3)
 will use the default set of specfiles described in
 .BR files_contexts (5)
-to calculate the SHA1 digests to be used for comparison.
+to calculate the SHA256 digests to be used for comparison.
 To change this default behavior
 .BR selabel_open (3)
 must be called specifying the required
diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index 7aadb822afb0..d906c8811017 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -130,7 +130,7 @@ DISABLE_FLAGS+= -DNO_MEDIA_BACKEND -DNO_DB_BACKEND -DNO_X_BACKEND \
 	-DBUILD_HOST
 SRCS= callbacks.c freecon.c label.c label_file.c \
 	label_backends_android.c regex.c label_support.c \
-	matchpathcon.c setrans_client.c sha1.c booleans.c
+	matchpathcon.c setrans_client.c sha256.c booleans.c
 LABEL_BACKEND_ANDROID=y
 endif
 
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 4778f8f8cd4a..b902ff06a502 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -1093,7 +1093,7 @@ static struct spec *lookup_common(struct selabel_handle *rec,
 
 /*
  * Returns true if the digest of all partial matched contexts is the same as
- * the one saved by setxattr, otherwise returns false. The length of the SHA1
+ * the one saved by setxattr, otherwise returns false. The length of the SHA256
  * digest will always be returned. The caller must free any returned digests.
  */
 static bool get_digests_all_partial_matches(struct selabel_handle *rec,
@@ -1102,39 +1102,39 @@ static bool get_digests_all_partial_matches(struct selabel_handle *rec,
 					    uint8_t **xattr_digest,
 					    size_t *digest_len)
 {
-	uint8_t read_digest[SHA1_HASH_SIZE];
+	uint8_t read_digest[SHA256_HASH_SIZE];
 	ssize_t read_size = getxattr(pathname, RESTORECON_PARTIAL_MATCH_DIGEST,
-				     read_digest, SHA1_HASH_SIZE
+				     read_digest, SHA256_HASH_SIZE
 #ifdef __APPLE__
 				     , 0, 0
 #endif /* __APPLE __ */
 				    );
-	uint8_t hash_digest[SHA1_HASH_SIZE];
+	uint8_t hash_digest[SHA256_HASH_SIZE];
 	bool status = selabel_hash_all_partial_matches(rec, pathname,
 						       hash_digest);
 
 	*xattr_digest = NULL;
 	*calculated_digest = NULL;
-	*digest_len = SHA1_HASH_SIZE;
+	*digest_len = SHA256_HASH_SIZE;
 
-	if (read_size == SHA1_HASH_SIZE) {
-		*xattr_digest = calloc(1, SHA1_HASH_SIZE + 1);
+	if (read_size == SHA256_HASH_SIZE) {
+		*xattr_digest = calloc(1, SHA256_HASH_SIZE + 1);
 		if (!*xattr_digest)
 			goto oom;
 
-		memcpy(*xattr_digest, read_digest, SHA1_HASH_SIZE);
+		memcpy(*xattr_digest, read_digest, SHA256_HASH_SIZE);
 	}
 
 	if (status) {
-		*calculated_digest = calloc(1, SHA1_HASH_SIZE + 1);
+		*calculated_digest = calloc(1, SHA256_HASH_SIZE + 1);
 		if (!*calculated_digest)
 			goto oom;
 
-		memcpy(*calculated_digest, hash_digest, SHA1_HASH_SIZE);
+		memcpy(*calculated_digest, hash_digest, SHA256_HASH_SIZE);
 	}
 
-	if (status && read_size == SHA1_HASH_SIZE &&
-	    memcmp(read_digest, hash_digest, SHA1_HASH_SIZE) == 0)
+	if (status && read_size == SHA256_HASH_SIZE &&
+	    memcmp(read_digest, hash_digest, SHA256_HASH_SIZE) == 0)
 		return true;
 
 	return false;
@@ -1154,22 +1154,22 @@ static bool hash_all_partial_matches(struct selabel_handle *rec, const char *key
 		return false;
 	}
 
-	Sha1Context context;
-	Sha1Initialise(&context);
+	Sha256Context context;
+	Sha256Initialise(&context);
 	size_t i;
 	for (i = 0; i < total_matches; i++) {
 		char* regex_str = matches[i]->regex_str;
 		mode_t mode = matches[i]->mode;
 		char* ctx_raw = matches[i]->lr.ctx_raw;
 
-		Sha1Update(&context, regex_str, strlen(regex_str) + 1);
-		Sha1Update(&context, &mode, sizeof(mode_t));
-		Sha1Update(&context, ctx_raw, strlen(ctx_raw) + 1);
+		Sha256Update(&context, regex_str, strlen(regex_str) + 1);
+		Sha256Update(&context, &mode, sizeof(mode_t));
+		Sha256Update(&context, ctx_raw, strlen(ctx_raw) + 1);
 	}
 
-	SHA1_HASH sha1_hash;
-	Sha1Finalise(&context, &sha1_hash);
-	memcpy(digest, sha1_hash.bytes, SHA1_HASH_SIZE);
+	SHA256_HASH sha256_hash;
+	Sha256Finalise(&context, &sha256_hash);
+	memcpy(digest, sha256_hash.bytes, SHA256_HASH_SIZE);
 
 	free(matches);
 	return true;
diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h
index ea60cd9a058f..77ac8173c7a9 100644
--- a/libselinux/src/label_internal.h
+++ b/libselinux/src/label_internal.h
@@ -13,7 +13,7 @@
 #include <stdio.h>
 #include <selinux/selinux.h>
 #include <selinux/label.h>
-#include "sha1.h"
+#include "sha256.h"
 
 #if defined(ANDROID) || defined(__APPLE__)
 // Android and Mac do not have fgets_unlocked()
@@ -47,15 +47,15 @@ int selabel_service_init(struct selabel_handle *rec,
  */
 
 /*
- * Calculate an SHA1 hash of all the files used to build the specs.
+ * Calculate an SHA256 hash of all the files used to build the specs.
  * The hash value is held in rec->digest if SELABEL_OPT_DIGEST set. To
  * calculate the hash the hashbuf will hold a concatenation of all the files
  * used. This is released once the value has been calculated.
  */
-#define DIGEST_SPECFILE_SIZE SHA1_HASH_SIZE
+#define DIGEST_SPECFILE_SIZE SHA256_HASH_SIZE
 #define DIGEST_FILES_MAX 8
 struct selabel_digest {
-	unsigned char *digest;	/* SHA1 digest of specfiles */
+	unsigned char *digest;	/* SHA256 digest of specfiles */
 	unsigned char *hashbuf;	/* buffer to hold specfiles */
 	size_t hashbuf_size;	/* buffer size */
 	size_t specfile_cnt;	/* how many specfiles processed */
@@ -110,7 +110,7 @@ struct selabel_handle {
 	 */
 	char *spec_file;
 
-	/* ptr to SHA1 hash information if SELABEL_OPT_DIGEST set */
+	/* ptr to SHA256 hash information if SELABEL_OPT_DIGEST set */
 	struct selabel_digest *digest;
 };
 
diff --git a/libselinux/src/label_support.c b/libselinux/src/label_support.c
index f7ab9292562e..1c3c1728f6ba 100644
--- a/libselinux/src/label_support.c
+++ b/libselinux/src/label_support.c
@@ -114,7 +114,7 @@ int  read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
 /* Once all the specfiles are in the hash_buf, generate the hash. */
 void  digest_gen_hash(struct selabel_digest *digest)
 {
-	Sha1Context context;
+	Sha256Context context;
 	size_t remaining_size;
 	const unsigned char *ptr;
 
@@ -122,19 +122,19 @@ void  digest_gen_hash(struct selabel_digest *digest)
 	if (!digest)
 		return;
 
-	Sha1Initialise(&context);
+	Sha256Initialise(&context);
 
 	/* Process in blocks of UINT32_MAX bytes */
 	remaining_size = digest->hashbuf_size;
 	ptr = digest->hashbuf;
 	while (remaining_size > UINT32_MAX) {
-		Sha1Update(&context, ptr, UINT32_MAX);
+		Sha256Update(&context, ptr, UINT32_MAX);
 		remaining_size -= UINT32_MAX;
 		ptr += UINT32_MAX;
 	}
-	Sha1Update(&context, ptr, remaining_size);
+	Sha256Update(&context, ptr, remaining_size);
 
-	Sha1Finalise(&context, (SHA1_HASH *)digest->digest);
+	Sha256Finalise(&context, (SHA256_HASH *)digest->digest);
 	free(digest->hashbuf);
 	digest->hashbuf = NULL;
 }
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 38f10f1c7edd..111b89aa8dc9 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -37,7 +37,7 @@
 #include "callbacks.h"
 #include "selinux_internal.h"
 #include "label_file.h"
-#include "sha1.h"
+#include "sha256.h"
 
 #define STAR_COUNT 1024
 
@@ -304,7 +304,7 @@ static uint64_t exclude_non_seclabel_mounts(void)
 static int add_xattr_entry(const char *directory, bool delete_nonmatch,
 			   bool delete_all)
 {
-	char *sha1_buf = NULL;
+	char *sha256_buf = NULL;
 	size_t i, digest_len = 0;
 	int rc;
 	enum digest_result digest_result;
@@ -328,15 +328,15 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
 	}
 
 	/* Convert entry to a hex encoded string. */
-	sha1_buf = malloc(digest_len * 2 + 1);
-	if (!sha1_buf) {
+	sha256_buf = malloc(digest_len * 2 + 1);
+	if (!sha256_buf) {
 		free(xattr_digest);
 		free(calculated_digest);
 		goto oom;
 	}
 
 	for (i = 0; i < digest_len; i++)
-		sprintf((&sha1_buf[i * 2]), "%02x", xattr_digest[i]);
+		sprintf((&sha256_buf[i * 2]), "%02x", xattr_digest[i]);
 
 	digest_result = match ? MATCH : NOMATCH;
 
@@ -356,7 +356,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
 	/* Now add entries to link list. */
 	new_entry = malloc(sizeof(struct dir_xattr));
 	if (!new_entry) {
-		free(sha1_buf);
+		free(sha256_buf);
 		goto oom;
 	}
 	new_entry->next = NULL;
@@ -364,15 +364,15 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
 	new_entry->directory = strdup(directory);
 	if (!new_entry->directory) {
 		free(new_entry);
-		free(sha1_buf);
+		free(sha256_buf);
 		goto oom;
 	}
 
-	new_entry->digest = strdup(sha1_buf);
+	new_entry->digest = strdup(sha256_buf);
 	if (!new_entry->digest) {
 		free(new_entry->directory);
 		free(new_entry);
-		free(sha1_buf);
+		free(sha256_buf);
 		goto oom;
 	}
 
@@ -386,7 +386,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
 		dir_xattr_last = new_entry;
 	}
 
-	free(sha1_buf);
+	free(sha256_buf);
 	return 0;
 
 oom:
@@ -776,7 +776,7 @@ err:
 
 struct dir_hash_node {
 	char *path;
-	uint8_t digest[SHA1_HASH_SIZE];
+	uint8_t digest[SHA256_HASH_SIZE];
 	struct dir_hash_node *next;
 };
 /*
@@ -1282,7 +1282,7 @@ static int selinux_restorecon_common(const char *pathname_orig,
 			if (setxattr(current->path,
 			    RESTORECON_PARTIAL_MATCH_DIGEST,
 			    current->digest,
-			    SHA1_HASH_SIZE, 0) < 0) {
+			    SHA256_HASH_SIZE, 0) < 0) {
 				selinux_log(SELINUX_ERROR,
 					    "setxattr failed: %s: %m\n",
 					    current->path);
diff --git a/libselinux/src/sha1.c b/libselinux/src/sha1.c
deleted file mode 100644
index 9d51e04ac331..000000000000
--- a/libselinux/src/sha1.c
+++ /dev/null
@@ -1,220 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  LibSha1
-//
-//  Implementation of SHA1 hash function.
-//  Original author:  Steve Reid <sreid@sea-to-sky.net>
-//  Contributions by: James H. Brown <jbrown@burgoyne.com>, Saul Kravitz <Saul.Kravitz@celera.com>,
-//  and Ralph Giles <giles@ghostscript.com>
-//  Modified by WaterJuice retaining Public Domain license.
-//
-//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
-//  Modified to:
-//    - stop symbols being exported for libselinux shared library - October 2015
-//								       Richard Haines <richard_c_haines@btinternet.com>
-//    - Not cast the workspace from a byte array to a CHAR64LONG16 due to alignment issues.
-//      Fixes:
-//        sha1.c:73:33: error: cast from 'uint8_t *' (aka 'unsigned char *') to 'CHAR64LONG16 *' increases required alignment from 1 to 4 [-Werror,-Wcast-align]
-//             CHAR64LONG16*       block = (CHAR64LONG16*) workspace;
-//                                                                     William Roberts <william.c.roberts@intel.com>
-//    - Silence clang's -Wextra-semi-stmt warning - July 2021, Nicolas Iooss <nicolas.iooss@m4x.org>
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  IMPORTS
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "sha1.h"
-#include <memory.h>
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  TYPES
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-typedef union
-{
-    uint8_t     c [64];
-    uint32_t    l [16];
-} CHAR64LONG16;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  INTERNAL FUNCTIONS
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-// blk0() and blk() perform the initial expand.
-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
-    |(rol(block->l[i],8)&0x00FF00FF))
-
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-    ^block->l[(i+2)&15]^block->l[i&15],1))
-
-// (R0+R1), R2, R3, R4 are the different operations used in SHA1
-#define R0(v,w,x,y,z,i)  do { z += ((w&(x^y))^y)     + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30); } while (0)
-#define R1(v,w,x,y,z,i)  do { z += ((w&(x^y))^y)     + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30); } while (0)
-#define R2(v,w,x,y,z,i)  do { z += (w^x^y)           + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30); } while (0)
-#define R3(v,w,x,y,z,i)  do { z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30); } while (0)
-#define R4(v,w,x,y,z,i)  do { z += (w^x^y)           + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30); } while (0)
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  TransformFunction
-//
-//  Hash a single 512-bit block. This is the core of the algorithm
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-static
-void
-    TransformFunction
-    (
-        uint32_t            state[5],
-        const uint8_t       buffer[64]
-    )
-{
-    uint32_t            a;
-    uint32_t            b;
-    uint32_t            c;
-    uint32_t            d;
-    uint32_t            e;
-    CHAR64LONG16        workspace;
-    CHAR64LONG16*       block = &workspace;
-
-    memcpy(block, buffer, 64);
-
-    // Copy context->state[] to working vars
-    a = state[0];
-    b = state[1];
-    c = state[2];
-    d = state[3];
-    e = state[4];
-
-    // 4 rounds of 20 operations each. Loop unrolled.
-    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-
-    // Add the working vars back into context.state[]
-    state[0] += a;
-    state[1] += b;
-    state[2] += c;
-    state[3] += d;
-    state[4] += e;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  PUBLIC FUNCTIONS
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  Sha1Initialise
-//
-//  Initialises an SHA1 Context. Use this to initialise/reset a context.
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void 
-    Sha1Initialise
-    (
-        Sha1Context*                Context
-    )
-{
-    // SHA1 initialization constants
-    Context->State[0] = 0x67452301;
-    Context->State[1] = 0xEFCDAB89;
-    Context->State[2] = 0x98BADCFE;
-    Context->State[3] = 0x10325476;
-    Context->State[4] = 0xC3D2E1F0;
-    Context->Count[0] = 0;
-    Context->Count[1] = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  Sha1Update
-//
-//  Adds data to the SHA1 context. This will process the data and update the internal state of the context. Keep on
-//  calling this function until all the data has been added. Then call Sha1Finalise to calculate the hash.
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void 
-    Sha1Update
-    (
-        Sha1Context*        Context,
-        const void*         Buffer,
-        uint32_t            BufferSize
-    )
-{
-    uint32_t    i;
-    uint32_t    j;
-
-    j = (Context->Count[0] >> 3) & 63;
-    if ((Context->Count[0] += BufferSize << 3) < (BufferSize << 3))
-    {
-        Context->Count[1]++;
-    }
-
-    Context->Count[1] += (BufferSize >> 29);
-    if ((j + BufferSize) > 63)
-    {
-        i = 64 - j;
-        memcpy(&Context->Buffer[j], Buffer, i);
-        TransformFunction(Context->State, Context->Buffer);
-        for (; i + 63 < BufferSize; i += 64)
-        {
-            TransformFunction(Context->State, (const uint8_t*)Buffer + i);
-        }
-        j = 0;
-    }
-    else
-    {
-        i = 0;
-    }
-
-    memcpy(&Context->Buffer[j], &((const uint8_t*)Buffer)[i], BufferSize - i);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  Sha1Finalise
-//
-//  Performs the final calculation of the hash and returns the digest (20 byte buffer containing 160bit hash). After
-//  calling this, Sha1Initialised must be used to reuse the context.
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void 
-    Sha1Finalise
-    (
-        Sha1Context*                Context,
-        SHA1_HASH*                  Digest
-    )
-{
-    uint32_t    i;
-    uint8_t     finalcount[8];
-
-    for (i = 0; i < 8; i++)
-    {
-        finalcount[i] = (unsigned char)((Context->Count[(i >= 4 ? 0 : 1)]
-         >> ((3-(i & 3)) * 8) ) & 255);  // Endian independent
-    }
-    Sha1Update(Context, (const uint8_t*)"\x80", 1);
-    while ((Context->Count[0] & 504) != 448)
-    {
-        Sha1Update(Context, (const uint8_t*)"\0", 1);
-    }
-
-    Sha1Update(Context, finalcount, 8);  // Should cause a Sha1TransformFunction()
-    for (i = 0; i < SHA1_HASH_SIZE; i++)
-    {
-        Digest->bytes[i] = (uint8_t)((Context->State[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-    }
-}
diff --git a/libselinux/src/sha1.h b/libselinux/src/sha1.h
deleted file mode 100644
index f83a6e7ed7ba..000000000000
--- a/libselinux/src/sha1.h
+++ /dev/null
@@ -1,85 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  LibSha1
-//
-//  Implementation of SHA1 hash function.
-//  Original author:  Steve Reid <sreid@sea-to-sky.net>
-//  Contributions by: James H. Brown <jbrown@burgoyne.com>, Saul Kravitz <Saul.Kravitz@celera.com>,
-//  and Ralph Giles <giles@ghostscript.com>
-//  Modified by WaterJuice retaining Public Domain license.
-//
-//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifndef _sha1_h_
-#define _sha1_h_
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  IMPORTS
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include <stdint.h>
-#include <stdio.h>
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  TYPES
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Sha1Context - This must be initialised using Sha1Initialised. Do not modify the contents of this structure directly.
-typedef struct
-{
-    uint32_t        State[5];
-    uint32_t        Count[2];
-    uint8_t         Buffer[64];
-} Sha1Context;
-
-#define SHA1_HASH_SIZE           ( 160 / 8 )
-
-typedef struct
-{
-    uint8_t      bytes [SHA1_HASH_SIZE];
-} SHA1_HASH;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  PUBLIC FUNCTIONS
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  Sha1Initialise
-//
-//  Initialises an SHA1 Context. Use this to initialise/reset a context.
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void
-    Sha1Initialise
-    (
-        Sha1Context*                Context
-    );
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  Sha1Update
-//
-//  Adds data to the SHA1 context. This will process the data and update the internal state of the context. Keep on
-//  calling this function until all the data has been added. Then call Sha1Finalise to calculate the hash.
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void
-    Sha1Update
-    (
-        Sha1Context*        Context,
-        const void*         Buffer,
-        uint32_t            BufferSize
-    );
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//  Sha1Finalise
-//
-//  Performs the final calculation of the hash and returns the digest (20 byte buffer containing 160bit hash). After
-//  calling this, Sha1Initialised must be used to reuse the context.
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void
-    Sha1Finalise
-    (
-        Sha1Context*                Context,
-        SHA1_HASH*                  Digest
-    );
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#endif //_sha1_h_
diff --git a/libselinux/src/sha256.c b/libselinux/src/sha256.c
new file mode 100644
index 000000000000..fe2aeef07f53
--- /dev/null
+++ b/libselinux/src/sha256.c
@@ -0,0 +1,294 @@
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  WjCryptLib_Sha256
+//
+//  Implementation of SHA256 hash function.
+//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+//  Modified by WaterJuice retaining Public Domain license.
+//
+//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  IMPORTS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "sha256.h"
+#include <memory.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  MACROS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
+
+#define MIN(x, y) ( ((x)<(y))?(x):(y) )
+
+#define STORE32H(x, y)                                                                     \
+     { (y)[0] = (uint8_t)(((x)>>24)&255); (y)[1] = (uint8_t)(((x)>>16)&255);   \
+       (y)[2] = (uint8_t)(((x)>>8)&255); (y)[3] = (uint8_t)((x)&255); }
+
+#define LOAD32H(x, y)                            \
+     { x = ((uint32_t)((y)[0] & 255)<<24) | \
+           ((uint32_t)((y)[1] & 255)<<16) | \
+           ((uint32_t)((y)[2] & 255)<<8)  | \
+           ((uint32_t)((y)[3] & 255)); }
+
+#define STORE64H(x, y)                                                                     \
+   { (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255);     \
+     (y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255);     \
+     (y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255);     \
+     (y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  CONSTANTS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// The K array
+static const uint32_t K[64] = {
+    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+#define BLOCK_SIZE          64
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  INTERNAL FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Various logical functions
+#define Ch( x, y, z )     (z ^ (x & (y ^ z)))
+#define Maj( x, y, z )    (((x | y) & z) | (x & y))
+#define S( x, n )         ror((x),(n))
+#define R( x, n )         (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0( x )       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1( x )       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0( x )       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1( x )       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+#define Sha256Round( a, b, c, d, e, f, g, h, i )       \
+     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
+     t1 = Sigma0(a) + Maj(a, b, c);                    \
+     d += t0;                                          \
+     h  = t0 + t1;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  TransformFunction
+//
+//  Compress 512-bits
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+static
+void
+    TransformFunction
+    (
+        Sha256Context*      Context,
+        uint8_t const*      Buffer
+    )
+{
+    uint32_t    S[8];
+    uint32_t    W[64];
+    uint32_t    t0;
+    uint32_t    t1;
+    uint32_t    t;
+    int         i;
+
+    // Copy state into S
+    for( i=0; i<8; i++ )
+    {
+        S[i] = Context->state[i];
+    }
+
+    // Copy the state into 512-bits into W[0..15]
+    for( i=0; i<16; i++ )
+    {
+        LOAD32H( W[i], Buffer + (4*i) );
+    }
+
+    // Fill W[16..63]
+    for( i=16; i<64; i++ )
+    {
+        W[i] = Gamma1( W[i-2]) + W[i-7] + Gamma0( W[i-15] ) + W[i-16];
+    }
+
+    // Compress
+    for( i=0; i<64; i++ )
+    {
+        Sha256Round( S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i );
+        t = S[7];
+        S[7] = S[6];
+        S[6] = S[5];
+        S[5] = S[4];
+        S[4] = S[3];
+        S[3] = S[2];
+        S[2] = S[1];
+        S[1] = S[0];
+        S[0] = t;
+    }
+
+    // Feedback
+    for( i=0; i<8; i++ )
+    {
+        Context->state[i] = Context->state[i] + S[i];
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  PUBLIC FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  Sha256Initialise
+//
+//  Initialises a SHA256 Context. Use this to initialise/reset a context.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+    Sha256Initialise
+    (
+        Sha256Context*      Context         // [out]
+    )
+{
+    Context->curlen = 0;
+    Context->length = 0;
+    Context->state[0] = 0x6A09E667UL;
+    Context->state[1] = 0xBB67AE85UL;
+    Context->state[2] = 0x3C6EF372UL;
+    Context->state[3] = 0xA54FF53AUL;
+    Context->state[4] = 0x510E527FUL;
+    Context->state[5] = 0x9B05688CUL;
+    Context->state[6] = 0x1F83D9ABUL;
+    Context->state[7] = 0x5BE0CD19UL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  Sha256Update
+//
+//  Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
+//  calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+    Sha256Update
+    (
+        Sha256Context*      Context,        // [in out]
+        void const*         Buffer,         // [in]
+        uint32_t            BufferSize      // [in]
+    )
+{
+    uint32_t n;
+
+    if( Context->curlen > sizeof(Context->buf) )
+    {
+       return;
+    }
+
+    while( BufferSize > 0 )
+    {
+        if( Context->curlen == 0 && BufferSize >= BLOCK_SIZE )
+        {
+           TransformFunction( Context, (uint8_t*)Buffer );
+           Context->length += BLOCK_SIZE * 8;
+           Buffer = (uint8_t*)Buffer + BLOCK_SIZE;
+           BufferSize -= BLOCK_SIZE;
+        }
+        else
+        {
+           n = MIN( BufferSize, (BLOCK_SIZE - Context->curlen) );
+           memcpy( Context->buf + Context->curlen, Buffer, (size_t)n );
+           Context->curlen += n;
+           Buffer = (uint8_t*)Buffer + n;
+           BufferSize -= n;
+           if( Context->curlen == BLOCK_SIZE )
+           {
+              TransformFunction( Context, Context->buf );
+              Context->length += 8*BLOCK_SIZE;
+              Context->curlen = 0;
+           }
+       }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  Sha256Finalise
+//
+//  Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
+//  calling this, Sha256Initialised must be used to reuse the context.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+    Sha256Finalise
+    (
+        Sha256Context*      Context,        // [in out]
+        SHA256_HASH*        Digest          // [out]
+    )
+{
+    int i;
+
+    if( Context->curlen >= sizeof(Context->buf) )
+    {
+       return;
+    }
+
+    // Increase the length of the message
+    Context->length += Context->curlen * 8;
+
+    // Append the '1' bit
+    Context->buf[Context->curlen++] = (uint8_t)0x80;
+
+    // if the length is currently above 56 bytes we append zeros
+    // then compress.  Then we can fall back to padding zeros and length
+    // encoding like normal.
+    if( Context->curlen > 56 )
+    {
+        while( Context->curlen < 64 )
+        {
+            Context->buf[Context->curlen++] = (uint8_t)0;
+        }
+        TransformFunction(Context, Context->buf);
+        Context->curlen = 0;
+    }
+
+    // Pad up to 56 bytes of zeroes
+    while( Context->curlen < 56 )
+    {
+        Context->buf[Context->curlen++] = (uint8_t)0;
+    }
+
+    // Store length
+    STORE64H( Context->length, Context->buf+56 );
+    TransformFunction( Context, Context->buf );
+
+    // Copy output
+    for( i=0; i<8; i++ )
+    {
+        STORE32H( Context->state[i], Digest->bytes+(4*i) );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  Sha256Calculate
+//
+//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
+//  buffer.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+    Sha256Calculate
+    (
+        void  const*        Buffer,         // [in]
+        uint32_t            BufferSize,     // [in]
+        SHA256_HASH*        Digest          // [in]
+    )
+{
+    Sha256Context context;
+
+    Sha256Initialise( &context );
+    Sha256Update( &context, Buffer, BufferSize );
+    Sha256Finalise( &context, Digest );
+}
diff --git a/libselinux/src/sha256.h b/libselinux/src/sha256.h
new file mode 100644
index 000000000000..406ed869cd82
--- /dev/null
+++ b/libselinux/src/sha256.h
@@ -0,0 +1,89 @@
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  WjCryptLib_Sha256
+//
+//  Implementation of SHA256 hash function.
+//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+//  Modified by WaterJuice retaining Public Domain license.
+//
+//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  IMPORTS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include <stdint.h>
+#include <stdio.h>
+
+typedef struct
+{
+    uint64_t    length;
+    uint32_t    state[8];
+    uint32_t    curlen;
+    uint8_t     buf[64];
+} Sha256Context;
+
+#define SHA256_HASH_SIZE           ( 256 / 8 )
+
+typedef struct
+{
+    uint8_t      bytes [SHA256_HASH_SIZE];
+} SHA256_HASH;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  PUBLIC FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  Sha256Initialise
+//
+//  Initialises a SHA256 Context. Use this to initialise/reset a context.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+    Sha256Initialise
+    (
+        Sha256Context*      Context         // [out]
+    );
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  Sha256Update
+//
+//  Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
+//  calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+    Sha256Update
+    (
+        Sha256Context*      Context,        // [in out]
+        void const*         Buffer,         // [in]
+        uint32_t            BufferSize      // [in]
+    );
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  Sha256Finalise
+//
+//  Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
+//  calling this, Sha256Initialised must be used to reuse the context.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+    Sha256Finalise
+    (
+        Sha256Context*      Context,        // [in out]
+        SHA256_HASH*        Digest          // [out]
+    );
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//  Sha256Calculate
+//
+//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
+//  buffer.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+    Sha256Calculate
+    (
+        void  const*        Buffer,         // [in]
+        uint32_t            BufferSize,     // [in]
+        SHA256_HASH*        Digest          // [in]
+    );
diff --git a/libselinux/utils/selabel_digest.c b/libselinux/utils/selabel_digest.c
index bf22b472856c..b992d4230eb3 100644
--- a/libselinux/utils/selabel_digest.c
+++ b/libselinux/utils/selabel_digest.c
@@ -15,8 +15,8 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname)
 		"Where:\n\t"
 		"-b  The backend - \"file\", \"media\", \"x\", \"db\" or "
 			"\"prop\"\n\t"
-		"-v  Run \"cat <specfile_list> | openssl dgst -sha1 -hex\"\n\t"
-		"    on the list of specfiles to compare the SHA1 digests.\n\t"
+		"-v  Run \"cat <specfile_list> | openssl dgst -sha256 -hex\"\n\t"
+		"    on the list of specfiles to compare the SHA256 digests.\n\t"
 		"-B  Use base specfiles only (valid for \"-b file\" only).\n\t"
 		"-i  Do not request a digest.\n\t"
 		"-f  Optional file containing the specs (defaults to\n\t"
@@ -63,12 +63,12 @@ int main(int argc, char **argv)
 	int rc, opt, validate = 0;
 	char *baseonly = NULL, *file = NULL, *digest = (char *)1;
 	char **specfiles = NULL;
-	unsigned char *sha1_digest = NULL;
+	unsigned char *sha256_digest = NULL;
 	size_t i, num_specfiles;
 
 	char cmd_buf[4096];
 	char *cmd_ptr;
-	char *sha1_buf;
+	char *sha256_buf;
 
 	struct selabel_handle *hnd;
 	struct selinux_opt selabel_option[] = {
@@ -138,7 +138,7 @@ int main(int argc, char **argv)
 		return -1;
 	}
 
-	rc = selabel_digest(hnd, &sha1_digest, &digest_len, &specfiles,
+	rc = selabel_digest(hnd, &sha256_digest, &digest_len, &specfiles,
 							    &num_specfiles);
 
 	if (rc) {
@@ -153,19 +153,19 @@ int main(int argc, char **argv)
 		goto err;
 	}
 
-	sha1_buf = malloc(digest_len * 2 + 1);
-	if (!sha1_buf) {
+	sha256_buf = malloc(digest_len * 2 + 1);
+	if (!sha256_buf) {
 		fprintf(stderr, "Could not malloc buffer ERROR: %s\n",
 						    strerror(errno));
 		rc = -1;
 		goto err;
 	}
 
-	printf("SHA1 digest: ");
+	printf("SHA256 digest: ");
 	for (i = 0; i < digest_len; i++)
-		sprintf(&(sha1_buf[i * 2]), "%02x", sha1_digest[i]);
+		sprintf(&(sha256_buf[i * 2]), "%02x", sha256_digest[i]);
 
-	printf("%s\n", sha1_buf);
+	printf("%s\n", sha256_buf);
 	printf("calculated using the following specfile(s):\n");
 
 	if (specfiles) {
@@ -178,13 +178,13 @@ int main(int argc, char **argv)
 			cmd_ptr += strlen(specfiles[i]) + 1;
 			printf("%s\n", specfiles[i]);
 		}
-		sprintf(cmd_ptr, "| /usr/bin/openssl dgst -sha1 -hex");
+		sprintf(cmd_ptr, "| /usr/bin/openssl dgst -sha256 -hex");
 
 		if (validate)
-			rc = run_check_digest(cmd_buf, sha1_buf);
+			rc = run_check_digest(cmd_buf, sha256_buf);
 	}
 
-	free(sha1_buf);
+	free(sha256_buf);
 err:
 	selabel_close(hnd);
 	return rc;
diff --git a/libselinux/utils/selabel_get_digests_all_partial_matches.c b/libselinux/utils/selabel_get_digests_all_partial_matches.c
index e2733b4195ff..98e533dc2692 100644
--- a/libselinux/utils/selabel_get_digests_all_partial_matches.c
+++ b/libselinux/utils/selabel_get_digests_all_partial_matches.c
@@ -16,8 +16,8 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname)
 		"-v  Validate file_contxts entries against loaded policy.\n\t"
 		"-r  Recursively descend directories.\n\t"
 		"-f  Optional file_contexts file (defaults to current policy).\n\t"
-		"path  Path to check current SHA1 digest against file_contexts entries.\n\n"
-		"This will check the directory selinux.sehash SHA1 digest for "
+		"path  Path to check current SHA256 digest against file_contexts entries.\n\n"
+		"This will check the directory selinux.sehash SHA256 digest for "
 		"<path> against\na newly generated digest based on the "
 		"file_context entries for that node\n(using the regx, mode "
 		"and path entries).\n", progname);
@@ -35,7 +35,7 @@ int main(int argc, char **argv)
 	char *paths[2] = { NULL, NULL };
 	uint8_t *xattr_digest = NULL;
 	uint8_t *calculated_digest = NULL;
-	char *sha1_buf = NULL;
+	char *sha256_buf = NULL;
 
 	struct selabel_handle *hnd;
 	struct selinux_opt selabel_option[] = {
@@ -104,27 +104,27 @@ int main(int argc, char **argv)
 							 &xattr_digest,
 							 &digest_len);
 
-			sha1_buf = calloc(1, digest_len * 2 + 1);
-			if (!sha1_buf) {
+			sha256_buf = calloc(1, digest_len * 2 + 1);
+			if (!sha256_buf) {
 				fprintf(stderr, "Could not calloc buffer ERROR: %s\n",
 					    strerror(errno));
 				return -1;
 			}
 
 			if (status) { /* They match */
-				printf("xattr and file_contexts SHA1 digests match for: %s\n",
+				printf("xattr and file_contexts SHA256 digests match for: %s\n",
 				       ftsent->fts_path);
 
 				if (calculated_digest) {
 					for (i = 0; i < digest_len; i++)
-						sprintf((&sha1_buf[i * 2]),
+						sprintf((&sha256_buf[i * 2]),
 							"%02x",
 							calculated_digest[i]);
-					printf("SHA1 digest: %s\n", sha1_buf);
+					printf("SHA256 digest: %s\n", sha256_buf);
 				}
 			} else {
 				if (!calculated_digest) {
-					printf("No SHA1 digest available for: %s\n",
+					printf("No SHA256 digest available for: %s\n",
 					       ftsent->fts_path);
 					printf("as file_context entry is \"<<none>>\"\n");
 					goto cleanup;
@@ -134,25 +134,25 @@ int main(int argc, char **argv)
 				       ftsent->fts_path);
 
 				for (i = 0; i < digest_len; i++)
-					sprintf((&sha1_buf[i * 2]), "%02x",
+					sprintf((&sha256_buf[i * 2]), "%02x",
 						calculated_digest[i]);
-				printf("generated SHA1 digest: %s\n", sha1_buf);
+				printf("generated SHA256 digest: %s\n", sha256_buf);
 
 				if (!xattr_digest) {
 					printf("however there is no selinux.sehash xattr entry.\n");
 				} else {
 					printf("however it does NOT match the current entry of:\n");
 					for (i = 0; i < digest_len; i++)
-						sprintf((&sha1_buf[i * 2]),
+						sprintf((&sha256_buf[i * 2]),
 							"%02x",
 							xattr_digest[i]);
-					printf("%s\n", sha1_buf);
+					printf("%s\n", sha256_buf);
 				}
 			}
 			cleanup:
 			free(xattr_digest);
 			free(calculated_digest);
-			free(sha1_buf);
+			free(sha256_buf);
 			break;
 		}
 		default:
-- 
2.41.0