|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2013 Red Hat
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include <gnutls/gnutls.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/crypto.h>
|
|
Packit Service |
4684c1 |
#include <unistd.h>
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include <fips.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/self-test.h>
|
|
Packit Service |
4684c1 |
#include <stdio.h>
|
|
Packit Service |
4684c1 |
#include <extras/hex.h>
|
|
Packit Service |
4684c1 |
#include <random.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gthreads.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
unsigned int _gnutls_lib_state = LIB_STATE_POWERON;
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_FIPS140
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <dlfcn.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define FIPS_KERNEL_FILE "/proc/sys/crypto/fips_enabled"
|
|
Packit Service |
4684c1 |
#define FIPS_SYSTEM_FILE "/etc/system-fips"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* We provide a per-thread FIPS-mode so that an application
|
|
Packit Service |
4684c1 |
* can use gnutls_fips140_set_mode() to override a specific
|
|
Packit Service |
4684c1 |
* operation on a thread */
|
|
Packit Service |
4684c1 |
static gnutls_fips_mode_t _global_fips_mode = -1;
|
|
Packit Service |
4684c1 |
static _Thread_local gnutls_fips_mode_t _tfips_mode = -1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int _skip_integrity_checks = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Returns:
|
|
Packit Service |
4684c1 |
* a gnutls_fips_mode_t value
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
unsigned _gnutls_fips_mode_enabled(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned f1p = 0, f2p;
|
|
Packit Service |
4684c1 |
FILE* fd;
|
|
Packit Service |
4684c1 |
const char *p;
|
|
Packit Service |
4684c1 |
unsigned ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* We initialize this threads' mode, and
|
|
Packit Service |
4684c1 |
* the global mode if not already initialized.
|
|
Packit Service |
4684c1 |
* When the global mode is initialized, then
|
|
Packit Service |
4684c1 |
* the thread mode is copied from it. As this
|
|
Packit Service |
4684c1 |
* is called on library initialization, the
|
|
Packit Service |
4684c1 |
* _global_fips_mode is always set during app run.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (_tfips_mode != (gnutls_fips_mode_t)-1)
|
|
Packit Service |
4684c1 |
return _tfips_mode;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (_global_fips_mode != (gnutls_fips_mode_t)-1) {
|
|
Packit Service |
4684c1 |
return _global_fips_mode;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p = secure_getenv("GNUTLS_SKIP_FIPS_INTEGRITY_CHECKS");
|
|
Packit Service |
4684c1 |
if (p && p[0] == '1') {
|
|
Packit Service |
4684c1 |
_skip_integrity_checks = 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p = secure_getenv("GNUTLS_FORCE_FIPS_MODE");
|
|
Packit Service |
4684c1 |
if (p) {
|
|
Packit Service |
4684c1 |
if (p[0] == '1')
|
|
Packit Service |
4684c1 |
ret = 1;
|
|
Packit Service |
4684c1 |
else if (p[0] == '2')
|
|
Packit Service |
4684c1 |
ret = GNUTLS_FIPS140_SELFTESTS;
|
|
Packit Service |
4684c1 |
else if (p[0] == '3')
|
|
Packit Service |
4684c1 |
ret = GNUTLS_FIPS140_LAX;
|
|
Packit Service |
4684c1 |
else if (p[0] == '4')
|
|
Packit Service |
4684c1 |
ret = GNUTLS_FIPS140_LOG;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
ret = GNUTLS_FIPS140_DISABLED;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
goto exit;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fd = fopen(FIPS_KERNEL_FILE, "re");
|
|
Packit Service |
4684c1 |
if (fd != NULL) {
|
|
Packit Service |
4684c1 |
f1p = fgetc(fd);
|
|
Packit Service |
4684c1 |
fclose(fd);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (f1p == '1') f1p = 1;
|
|
Packit Service |
4684c1 |
else f1p = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (f1p != 0) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("FIPS140-2 mode enabled\n");
|
|
Packit Service |
4684c1 |
ret = GNUTLS_FIPS140_STRICT;
|
|
Packit Service |
4684c1 |
goto exit;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
f2p = !access(FIPS_SYSTEM_FILE, F_OK);
|
|
Packit Service |
4684c1 |
if (f2p != 0) {
|
|
Packit Service |
4684c1 |
/* a funny state where self tests are performed
|
|
Packit Service |
4684c1 |
* and ignored */
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("FIPS140-2 ZOMBIE mode enabled\n");
|
|
Packit Service |
4684c1 |
ret = GNUTLS_FIPS140_SELFTESTS;
|
|
Packit Service |
4684c1 |
goto exit;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = GNUTLS_FIPS140_DISABLED;
|
|
Packit Service |
4684c1 |
goto exit;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
exit:
|
|
Packit Service |
4684c1 |
_global_fips_mode = ret;
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* This _fips_mode == 2 is a strange mode where checks are being
|
|
Packit Service |
4684c1 |
* performed, but its output is ignored. */
|
|
Packit Service |
4684c1 |
void _gnutls_fips_mode_reset_zombie(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (_global_fips_mode == GNUTLS_FIPS140_SELFTESTS) {
|
|
Packit Service |
4684c1 |
_global_fips_mode = GNUTLS_FIPS140_DISABLED;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* These only works with the platform where SONAME is part of the ABI.
|
|
Packit Service |
4684c1 |
* For example, *_SONAME will be set to "none" on Windows platforms. */
|
|
Packit Service |
4684c1 |
#define GNUTLS_LIBRARY_NAME GNUTLS_LIBRARY_SONAME
|
|
Packit Service |
4684c1 |
#define NETTLE_LIBRARY_NAME NETTLE_LIBRARY_SONAME
|
|
Packit Service |
4684c1 |
#define HOGWEED_LIBRARY_NAME HOGWEED_LIBRARY_SONAME
|
|
Packit Service |
4684c1 |
#define GMP_LIBRARY_NAME GMP_LIBRARY_SONAME
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define HMAC_SUFFIX ".hmac"
|
|
Packit Service |
4684c1 |
#define HMAC_SIZE 32
|
|
Packit Service |
4684c1 |
#define HMAC_ALGO GNUTLS_MAC_SHA256
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int get_library_path(const char* lib, const char* symbol, char* path, size_t path_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
Dl_info info;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
void *dl, *sym;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
dl = dlopen(lib, RTLD_LAZY);
|
|
Packit Service |
4684c1 |
if (dl == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
sym = dlsym(dl, symbol);
|
|
Packit Service |
4684c1 |
if (sym == NULL) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = dladdr(sym, &info;;
|
|
Packit Service |
4684c1 |
if (ret == 0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
snprintf(path, path_size, "%s", info.dli_fname);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
dlclose(dl);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void get_hmac_file(char *mac_file, size_t mac_file_size, const char* orig)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
char* p;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p = strrchr(orig, '/');
|
|
Packit Service |
4684c1 |
if (p==NULL) {
|
|
Packit Service |
4684c1 |
snprintf(mac_file, mac_file_size, ".%s"HMAC_SUFFIX, orig);
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
snprintf(mac_file, mac_file_size, "%.*s/.%s"HMAC_SUFFIX, (int)(p-orig), orig, p+1);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void get_hmac_file2(char *mac_file, size_t mac_file_size, const char* orig)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
char* p;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p = strrchr(orig, '/');
|
|
Packit Service |
4684c1 |
if (p==NULL) {
|
|
Packit Service |
4684c1 |
snprintf(mac_file, mac_file_size, "fipscheck/%s"HMAC_SUFFIX, orig);
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
snprintf(mac_file, mac_file_size, "%.*s/fipscheck/%s"HMAC_SUFFIX, (int)(p-orig), orig, p+1);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Run an HMAC using the key above on the library binary data.
|
|
Packit Service |
4684c1 |
* Returns true on success and false on error.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static unsigned check_binary_integrity(const char* libname, const char* symbol)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
unsigned prev;
|
|
Packit Service |
4684c1 |
char mac_file[GNUTLS_PATH_MAX];
|
|
Packit Service |
4684c1 |
char file[GNUTLS_PATH_MAX];
|
|
Packit Service |
4684c1 |
uint8_t hmac[HMAC_SIZE];
|
|
Packit Service |
4684c1 |
uint8_t new_hmac[HMAC_SIZE];
|
|
Packit Service |
4684c1 |
size_t hmac_size;
|
|
Packit Service |
4684c1 |
gnutls_datum_t data;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = get_library_path(libname, symbol, file, sizeof(file));
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Could not get path for library %s\n", libname);
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Loading: %s\n", file);
|
|
Packit Service |
4684c1 |
ret = gnutls_load_file(file, &data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Could not load: %s\n", file);
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
prev = _gnutls_get_lib_state();
|
|
Packit Service |
4684c1 |
_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
|
|
Packit Service |
4684c1 |
ret = gnutls_hmac_fast(HMAC_ALGO, FIPS_KEY, sizeof(FIPS_KEY)-1,
|
|
Packit Service |
4684c1 |
data.data, data.size, new_hmac);
|
|
Packit Service |
4684c1 |
_gnutls_switch_lib_state(prev);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(data.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* now open the .hmac file and compare */
|
|
Packit Service |
4684c1 |
get_hmac_file(mac_file, sizeof(mac_file), file);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_load_file(mac_file, &data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
get_hmac_file2(mac_file, sizeof(mac_file), file);
|
|
Packit Service |
4684c1 |
ret = gnutls_load_file(mac_file, &data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Could not open %s for MAC testing: %s\n", mac_file, gnutls_strerror(ret));
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
hmac_size = hex_data_size(data.size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* trim eventual newlines from the end of the data read from file */
|
|
Packit Service |
4684c1 |
while ((data.size > 0) && (data.data[data.size - 1] == '\n')) {
|
|
Packit Service |
4684c1 |
data.data[data.size - 1] = 0;
|
|
Packit Service |
4684c1 |
data.size--;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_hex_decode(&data, hmac, &hmac_size);
|
|
Packit Service |
4684c1 |
gnutls_free(data.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Could not convert hex data to binary for MAC testing for %s.\n", libname);
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (hmac_size != sizeof(hmac) ||
|
|
Packit Service |
4684c1 |
memcmp(hmac, new_hmac, sizeof(hmac)) != 0) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Calculated MAC for %s does not match\n", libname);
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Successfully verified MAC for %s (%s)\n", mac_file, libname);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_fips_perform_self_checks1(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Tests the FIPS algorithms used by nettle internally.
|
|
Packit Service |
4684c1 |
* In our case we test AES-CBC since nettle's AES is used by
|
|
Packit Service |
4684c1 |
* the DRBG-AES.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* ciphers - one test per cipher */
|
|
Packit Service |
4684c1 |
ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_128_CBC);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
error:
|
|
Packit Service |
4684c1 |
_gnutls_switch_lib_state(LIB_STATE_ERROR);
|
|
Packit Service |
4684c1 |
_gnutls_audit_log(NULL, "FIPS140-2 self testing part1 failed\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return GNUTLS_E_SELF_TEST_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_fips_perform_self_checks2(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Tests the FIPS algorithms */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* ciphers - one test per cipher */
|
|
Packit Service |
4684c1 |
ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_3DES_CBC);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CBC);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_GCM);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_XTS);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CFB8);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Digest tests */
|
|
Packit Service |
4684c1 |
ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_224);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_256);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_384);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_512);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* MAC (includes message digest test) */
|
|
Packit Service |
4684c1 |
ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA1);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA224);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA256);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA384);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA512);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4e863c |
ret = gnutls_mac_self_test(0, GNUTLS_MAC_AES_CMAC_256);
|
|
Packit Service |
4e863c |
if (ret < 0) {
|
|
Packit Service |
4e863c |
gnutls_assert();
|
|
Packit Service |
4e863c |
goto error;
|
|
Packit Service |
4e863c |
}
|
|
Packit Service |
4e863c |
|
|
Packit Service |
4684c1 |
/* PK */
|
|
Packit Service |
4684c1 |
ret = gnutls_pk_self_test(0, GNUTLS_PK_RSA);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pk_self_test(0, GNUTLS_PK_DSA);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pk_self_test(0, GNUTLS_PK_EC);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pk_self_test(0, GNUTLS_PK_DH);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4e863c |
/* HKDF */
|
|
Packit Service |
4e863c |
ret = gnutls_hkdf_self_test(0, GNUTLS_MAC_SHA256);
|
|
Packit Service |
4e863c |
if (ret < 0) {
|
|
Packit Service |
4e863c |
gnutls_assert();
|
|
Packit Service |
4e863c |
goto error;
|
|
Packit Service |
4e863c |
}
|
|
Packit Service |
4e863c |
|
|
Packit Service |
4e863c |
/* PBKDF2 */
|
|
Packit Service |
4e863c |
ret = gnutls_pbkdf2_self_test(0, GNUTLS_MAC_SHA256);
|
|
Packit Service |
4e863c |
if (ret < 0) {
|
|
Packit Service |
4e863c |
gnutls_assert();
|
|
Packit Service |
4e863c |
goto error;
|
|
Packit Service |
4e863c |
}
|
|
Packit Service |
4e863c |
|
|
Packit Service |
4e863c |
/* TLS-PRF */
|
|
Packit Service |
4e863c |
ret = gnutls_tlsprf_self_test(0, GNUTLS_MAC_SHA256);
|
|
Packit Service |
4e863c |
if (ret < 0) {
|
|
Packit Service |
4e863c |
gnutls_assert();
|
|
Packit Service |
4e863c |
goto error;
|
|
Packit Service |
4e863c |
}
|
|
Packit Service |
4e863c |
|
|
Packit Service |
4684c1 |
if (_gnutls_rnd_ops.self_test == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* this does not require rng initialization */
|
|
Packit Service |
4684c1 |
ret = _gnutls_rnd_ops.self_test();
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (_skip_integrity_checks == 0) {
|
|
Packit Service |
4684c1 |
ret = check_binary_integrity(GNUTLS_LIBRARY_NAME, "gnutls_global_init");
|
|
Packit Service |
4684c1 |
if (ret == 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = check_binary_integrity(NETTLE_LIBRARY_NAME, "nettle_aes_set_encrypt_key");
|
|
Packit Service |
4684c1 |
if (ret == 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = check_binary_integrity(HOGWEED_LIBRARY_NAME, "nettle_mpz_sizeinbase_256_u");
|
|
Packit Service |
4684c1 |
if (ret == 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = check_binary_integrity(GMP_LIBRARY_NAME, "__gmpz_init");
|
|
Packit Service |
4684c1 |
if (ret == 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
error:
|
|
Packit Service |
4684c1 |
_gnutls_switch_lib_state(LIB_STATE_ERROR);
|
|
Packit Service |
4684c1 |
_gnutls_audit_log(NULL, "FIPS140-2 self testing part 2 failed\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return GNUTLS_E_SELF_TEST_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_fips140_mode_enabled:
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Checks whether this library is in FIPS140 mode. The returned
|
|
Packit Service |
4684c1 |
* value corresponds to the library mode as set with
|
|
Packit Service |
4684c1 |
* gnutls_fips140_set_mode().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* If gnutls_fips140_set_mode() was called with %GNUTLS_FIPS140_SET_MODE_THREAD
|
|
Packit Service |
4684c1 |
* then this function will return the current thread's FIPS140 mode, otherwise
|
|
Packit Service |
4684c1 |
* the global value is returned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: return non-zero if true or zero if false.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.3.0
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
unsigned gnutls_fips140_mode_enabled(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_FIPS140
|
|
Packit Service |
4684c1 |
unsigned ret = _gnutls_fips_mode_enabled();
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
b97e56 |
if (ret > GNUTLS_FIPS140_DISABLED) {
|
|
Packit Service |
b97e56 |
/* If the previous run of selftests has failed, return as if
|
|
Packit Service |
b97e56 |
* the FIPS mode is disabled. We could use HAVE_LIB_ERROR, if
|
|
Packit Service |
b97e56 |
* we can assume that all the selftests run atomically from
|
|
Packit Service |
b97e56 |
* the ELF constructor.
|
|
Packit Service |
b97e56 |
*/
|
|
Packit Service |
b97e56 |
if (_gnutls_get_lib_state() == LIB_STATE_ERROR)
|
|
Packit Service |
b97e56 |
return 0;
|
|
Packit Service |
b97e56 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
b97e56 |
}
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_fips140_set_mode:
|
|
Packit Service |
4684c1 |
* @mode: the FIPS140-2 mode to switch to
|
|
Packit Service |
4684c1 |
* @flags: should be zero or %GNUTLS_FIPS140_SET_MODE_THREAD
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* That function is not thread-safe when changing the mode with no flags
|
|
Packit Service |
4684c1 |
* (globally), and should be called prior to creating any threads. Its
|
|
Packit Service |
4684c1 |
* behavior with no flags after threads are created is undefined.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* When the flag %GNUTLS_FIPS140_SET_MODE_THREAD is specified
|
|
Packit Service |
4684c1 |
* then this call will change the FIPS140-2 mode for this particular
|
|
Packit Service |
4684c1 |
* thread and not for the whole process. That way an application
|
|
Packit Service |
4684c1 |
* can utilize this function to set and reset mode for specific
|
|
Packit Service |
4684c1 |
* operations.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function never fails but will be a no-op if used when
|
|
Packit Service |
4684c1 |
* the library is not in FIPS140-2 mode. When asked to switch to unknown
|
|
Packit Service |
4684c1 |
* values for @mode or to %GNUTLS_FIPS140_SELFTESTS mode, the library
|
|
Packit Service |
4684c1 |
* switches to %GNUTLS_FIPS140_STRICT mode.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.6.2
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
void gnutls_fips140_set_mode(gnutls_fips_mode_t mode, unsigned flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_FIPS140
|
|
Packit Service |
4684c1 |
gnutls_fips_mode_t prev = _gnutls_fips_mode_enabled();
|
|
Packit Service |
4684c1 |
if (prev == GNUTLS_FIPS140_DISABLED || prev == GNUTLS_FIPS140_SELFTESTS) {
|
|
Packit Service |
4684c1 |
/* we need to run self-tests first to be in FIPS140-2 mode */
|
|
Packit Service |
4684c1 |
_gnutls_audit_log(NULL, "The library should be initialized in FIPS140-2 mode to do that operation\n");
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch (mode) {
|
|
Packit Service |
4684c1 |
case GNUTLS_FIPS140_STRICT:
|
|
Packit Service |
4684c1 |
case GNUTLS_FIPS140_LAX:
|
|
Packit Service |
4684c1 |
case GNUTLS_FIPS140_LOG:
|
|
Packit Service |
4684c1 |
case GNUTLS_FIPS140_DISABLED:
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
case GNUTLS_FIPS140_SELFTESTS:
|
|
Packit Service |
4684c1 |
_gnutls_audit_log(NULL, "Cannot switch library to FIPS140-2 self-tests mode; defaulting to strict\n");
|
|
Packit Service |
4684c1 |
mode = GNUTLS_FIPS140_STRICT;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
_gnutls_audit_log(NULL, "Cannot switch library to mode %u; defaulting to strict\n", (unsigned)mode);
|
|
Packit Service |
4684c1 |
mode = GNUTLS_FIPS140_STRICT;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (flags & GNUTLS_FIPS140_SET_MODE_THREAD)
|
|
Packit Service |
4684c1 |
_tfips_mode = mode;
|
|
Packit Service |
4684c1 |
else {
|
|
Packit Service |
4684c1 |
_global_fips_mode = mode;
|
|
Packit Service |
4684c1 |
_tfips_mode = -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void _gnutls_lib_simulate_error(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
_gnutls_switch_lib_state(LIB_STATE_ERROR);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void _gnutls_lib_force_operational(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
|
|
Packit Service |
4684c1 |
}
|