forked from aws/aws-lc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Integrate Snapsafe /dev/sysgenid into rand
- Loading branch information
Showing
5 changed files
with
267 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#include <openssl/crypto.h> | ||
|
||
#include "../delocate.h" | ||
#include "snapsafe_detect.h" | ||
|
||
/* Test mode state */ | ||
#define SNAPSAFE_TEST_MODE_DISABLED 0x00 | ||
#define SNAPSAFE_TEST_MODE_ENABLED 0x01 | ||
DEFINE_STATIC_MUTEX(test_mode_mutex); | ||
static volatile int test_mode_enabled = 0; | ||
static volatile uint32_t test_mode_sgn = 0; | ||
static volatile int test_mode_status = 1; | ||
|
||
#if defined(OPENSSL_LINUX) | ||
#include <fcntl.h> | ||
#include <stdlib.h> | ||
#include <sys/ioctl.h> | ||
#include <sys/mman.h> | ||
#include <sys/random.h> | ||
#include <unistd.h> | ||
|
||
/* Snapsafety state */ | ||
#define SNAPSAFETY_STATE_FAILED_INITIALISE 0x00 | ||
#define SNAPSAFETY_STATE_SUCCESS_INITIALISE 0x01 | ||
#define SNAPSAFETY_STATE_NOT_SUPPORTED 0x02 | ||
|
||
/* Sysgenid state */ | ||
/* These values can be found here: https://lkml.org/lkml/2021/3/8/677 */ | ||
#define SYSGENID_IOCTL 0xE4 | ||
#define SYSGENID_TRIGGER_GEN_UPDATE _IO(SYSGENID_IOCTL, 3) | ||
|
||
static const char *sgc_file_path = "/dev/sysgenid"; | ||
static volatile uint32_t *sgc_addr = NULL; | ||
DEFINE_STATIC_ONCE(aws_snapsafe_init) | ||
|
||
static int snapsafety_state = SNAPSAFETY_STATE_FAILED_INITIALISE; | ||
|
||
/* aws_snapsafe_check_kernel_support returns 1 if the special sysgenid device | ||
* file exists and 0 otherwise. */ | ||
static int aws_snapsafe_check_kernel_support(void) { | ||
/* This file-exist method is generally brittle. But for our purpose, this | ||
* should be more than fine. */ | ||
if (access(sgc_file_path, F_OK) != 0) { | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
|
||
static void do_aws_snapsafe_init(void) { | ||
if (aws_snapsafe_check_kernel_support() != 1) { | ||
snapsafety_state = SNAPSAFETY_STATE_NOT_SUPPORTED; | ||
return; | ||
} | ||
|
||
/* While not totally obvious from man pages, mmap actually only allocates | ||
* memory on page size boundaries. So just give it that hint. */ | ||
long page_size = sysconf(_SC_PAGESIZE); | ||
if (page_size <= 0) { | ||
snapsafety_state = SNAPSAFETY_STATE_FAILED_INITIALISE; | ||
return; | ||
} | ||
|
||
if (sgc_addr == NULL) { | ||
int fd_sgc = open(sgc_file_path, O_RDONLY); | ||
if (fd_sgc == -1) { | ||
snapsafety_state = SNAPSAFETY_STATE_FAILED_INITIALISE; | ||
return; | ||
} | ||
|
||
void *addr = | ||
mmap(NULL, (size_t)page_size, PROT_READ, MAP_SHARED, fd_sgc, 0); | ||
|
||
/* Can close file descriptor now per | ||
* https://man7.org/linux/man-pages/man2/mmap.2.html: "After the mmap() call | ||
* has returned, the file descriptor, fd, can be closed immediately without | ||
* invalidating the mapping.". We have initialised snapsafety without errors | ||
* and this function is only executed once. Therefore, try to close file | ||
* descriptor but don't error if it fails. */ | ||
close(fd_sgc); | ||
|
||
if (addr == MAP_FAILED) { | ||
snapsafety_state = SNAPSAFETY_STATE_FAILED_INITIALISE; | ||
return; | ||
} | ||
|
||
/* sgc_addr will now point at the mapped memory and any 4-byte read from | ||
* this pointer will correspond to the sgn manager by the VMM. */ | ||
sgc_addr = addr; | ||
|
||
snapsafety_state = SNAPSAFETY_STATE_SUCCESS_INITIALISE; | ||
} | ||
} | ||
|
||
static uint32_t aws_snapsafe_read_sgn(void) { | ||
if (snapsafety_state == SNAPSAFETY_STATE_SUCCESS_INITIALISE) { | ||
return *sgc_addr; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
|
||
int CRYPTO_get_snapsafe_generation(uint32_t *snapsafe_generation_number) { | ||
CRYPTO_once(aws_snapsafe_init_bss_get(), do_aws_snapsafe_init); | ||
|
||
CRYPTO_STATIC_MUTEX_lock_read(test_mode_mutex_bss_get()); | ||
if (test_mode_enabled == SNAPSAFE_TEST_MODE_ENABLED) { | ||
*snapsafe_generation_number = test_mode_sgn; | ||
return test_mode_status; | ||
} | ||
CRYPTO_STATIC_MUTEX_unlock_read(test_mode_mutex_bss_get()); | ||
|
||
if (snapsafety_state == SNAPSAFETY_STATE_FAILED_INITIALISE) { | ||
*snapsafe_generation_number = 0; | ||
return 0; | ||
} | ||
|
||
if (snapsafety_state != SNAPSAFETY_STATE_SUCCESS_INITIALISE) { | ||
// Use 0 to indicate snapsafe is not active. | ||
*snapsafe_generation_number = 0; | ||
} else { | ||
// Retrieve value from OS | ||
*snapsafe_generation_number = aws_snapsafe_read_sgn(); | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
#else // !defined(OPENSSL_LINUX) | ||
|
||
int CRYPTO_get_snapsafe_generation(uint32_t *snapsafe_generation_number) { | ||
CRYPTO_STATIC_MUTEX_lock_read(test_mode_mutex_bss_get()); | ||
if (test_mode_enabled == SNAPSAFE_TEST_MODE_ENABLED) { | ||
*snapsafe_generation_number = test_mode_sgn; | ||
return test_mode_status; | ||
} | ||
CRYPTO_STATIC_MUTEX_unlock_read(test_mode_mutex_bss_get()); | ||
|
||
*snapsafe_generation_number = 0; | ||
return 1; | ||
} | ||
|
||
#endif // defined(OPENSSL_LINUX) && !defined(FIPS) | ||
|
||
OPENSSL_EXPORT void HAZMAT_snapsafe_testing_status(int status) { | ||
CRYPTO_STATIC_MUTEX_lock_write(test_mode_mutex_bss_get()); | ||
test_mode_status = status; | ||
CRYPTO_STATIC_MUTEX_unlock_write(test_mode_mutex_bss_get()); | ||
} | ||
|
||
OPENSSL_EXPORT void HAZMAT_snapsafe_testing(int enable) { | ||
CRYPTO_STATIC_MUTEX_lock_write(test_mode_mutex_bss_get()); | ||
if (enable == 0) { | ||
test_mode_enabled = SNAPSAFE_TEST_MODE_DISABLED; | ||
} else { | ||
test_mode_enabled = SNAPSAFE_TEST_MODE_ENABLED; | ||
} | ||
CRYPTO_STATIC_MUTEX_unlock_write(test_mode_mutex_bss_get()); | ||
} | ||
|
||
OPENSSL_EXPORT void HAZMAT_snapsafe_testing_value(uint32_t val) { | ||
CRYPTO_STATIC_MUTEX_lock_write(test_mode_mutex_bss_get()); | ||
test_mode_sgn = val; | ||
CRYPTO_STATIC_MUTEX_unlock_write(test_mode_mutex_bss_get()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#ifndef HEADER_SNAPSAFE_DETECT | ||
#define HEADER_SNAPSAFE_DETECT | ||
|
||
#include <openssl/base.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#if defined(AWSLC_SYSGENID_PATH) | ||
#define AWSLC_SYSGENID_FILE_PATH AWSLC_SYSGENID_PATH | ||
#else | ||
// If no user-specified path is provided at compile-time, use a default | ||
// path. Path taken from https://lkml.org/lkml/2021/3/8/677. This path | ||
// might change in the future, becasue the SysGenID interface is not yet | ||
// stable. | ||
#define AWSLC_SYSGENID_FILE_PATH "/dev/sysgenid" | ||
#endif | ||
|
||
// Snapsafe-type uniqueness breaking event (ube detection. | ||
// | ||
// CRYPTO_get_snapsafe_generation provides the snapsafe generation number for the | ||
// current process. The snapsafe generation number is a non-zero, strictly-monotonic | ||
// counter with the property that, if queried in an address space and then again in | ||
// a subsequently resumed snapshot/VM, the resumed address space will observe a greater value. | ||
// | ||
// We use SysGenID to detect resumed snapshot/VM events. See | ||
// https://lkml.org/lkml/2021/3/8/677 for details about how SysGenID works. | ||
// We make light use of the SysGenId capabilities and only use the following | ||
// supported functions on the device: |open| and |mmap|. | ||
// | ||
// |CRYPTO_get_snapsafe_generation| returns 0 only when the filesystem | ||
// presents SysGenID interface (typically `/dev/sysgenid`) but the library | ||
// is unable to initialize its use. In all other cases, it returns 1. | ||
OPENSSL_EXPORT int CRYPTO_get_snapsafe_generation( | ||
uint32_t *snapsafe_generation_number); | ||
|
||
// Below functions are strictly for testing only! | ||
|
||
// HAZMAT_snapsafe_testing is an internal function used for testing snapsafe. | ||
// Call |HAZMAT_sysgenid_testing| with a non-zero value to enable testing, otherwise | ||
// testing will be disabled. | ||
// Returns 1 if succesfull and 0 otherwise. | ||
OPENSSL_EXPORT void HAZMAT_snapsafe_testing(int enable); | ||
|
||
// HAZMAT_snapsafe_testing_status is an internal function used for testing snapsafe. | ||
// The value |val| passed to this function will be used as the snapsafe status | ||
// returned by |CRYPTO_get_snapsafe_generation| when testing has been enabled. | ||
OPENSSL_EXPORT void HAZMAT_snapsafe_testing_status(int status); | ||
|
||
// HAZMAT_snapsafe_testing_value is an internal function used for testing snapsafe. | ||
// The value |val| passed to this function will be used as the snapsafe generation | ||
// number when testing has been enabled. | ||
OPENSSL_EXPORT void HAZMAT_snapsafe_testing_value(uint32_t val); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* HEADER_SNAPSAFE_DETECT */ |