Skip to content

Commit

Permalink
Use SHA-2 instead of SHA-1
Browse files Browse the repository at this point in the history
The use of SHA-1 in RHEL9 is deprecated
  • Loading branch information
bachradsusi committed Nov 10, 2023
1 parent 7bf4ac2 commit 9485916
Show file tree
Hide file tree
Showing 21 changed files with 491 additions and 413 deletions.
6 changes: 3 additions & 3 deletions libselinux/include/selinux/label.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
4 changes: 2 additions & 2 deletions libselinux/include/selinux/restorecon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
/*
Expand Down
4 changes: 2 additions & 2 deletions libselinux/man/man3/selabel_digest.3
Original file line number Diff line number Diff line change
Expand Up @@ -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 .
Expand Down
2 changes: 1 addition & 1 deletion libselinux/man/man3/selabel_open.3
Original file line number Diff line number Diff line change
Expand Up @@ -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)
.
Expand Down
18 changes: 9 additions & 9 deletions libselinux/man/man3/selinux_restorecon.3
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion libselinux/man/man3/selinux_restorecon_xattr.3
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion libselinux/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
40 changes: 20 additions & 20 deletions libselinux/src/label_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand All @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions libselinux/src/label_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
};

Expand Down
10 changes: 5 additions & 5 deletions libselinux/src/label_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,27 +114,27 @@ 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;

/* If SELABEL_OPT_DIGEST not set then just return */
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;
}
Expand Down
24 changes: 12 additions & 12 deletions libselinux/src/selinux_restorecon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -356,23 +356,23 @@ 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;

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;
}

Expand All @@ -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:
Expand Down Expand Up @@ -776,7 +776,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,

struct dir_hash_node {
char *path;
uint8_t digest[SHA1_HASH_SIZE];
uint8_t digest[SHA256_HASH_SIZE];
struct dir_hash_node *next;
};
/*
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 9485916

Please sign in to comment.