Exemple #1
0
int _gnutls_fips_perform_self_checks1(void)
{
	int ret;

	_gnutls_switch_lib_state(LIB_STATE_SELFTEST);

	/* Tests the FIPS algorithms used by nettle internally.
	 * In our case we test AES-CBC since nettle's AES is used by
	 * the DRBG-AES.
	 */

	/* ciphers - one test per cipher */
	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_128_CBC);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	return 0;

error:
	_gnutls_switch_lib_state(LIB_STATE_ERROR);
	_gnutls_audit_log(NULL, "FIPS140-2 self testing part1 failed\n");

	return GNUTLS_E_SELF_TEST_ERROR;
}
Exemple #2
0
_CONSTRUCTOR static void lib_init(void)
{
int ret;

	ret = gnutls_global_init();
	if (ret < 0) {
		fprintf(stderr, "Error in GnuTLS initialization: %s\n", gnutls_strerror(ret));
		_gnutls_switch_lib_state(LIB_STATE_ERROR);
	}
}
Exemple #3
0
static void rnd_func(void *_ctx, unsigned length, uint8_t * data)
{
	if (_gnutls_rnd(GNUTLS_RND_RANDOM, data, length) < 0) {
#ifdef ENABLE_FIPS140
		_gnutls_switch_lib_state(LIB_STATE_ERROR);
#else
		abort();
#endif
	}
}
Exemple #4
0
static void lib_init(void)
{
int ret;
const char *e;

	if (_gnutls_global_init_skip() != 0)
		return;

	e = secure_getenv("GNUTLS_NO_EXPLICIT_INIT");
	if (e != NULL) {
		ret = atoi(e);
		if (ret == 1)
			return;
	}

	ret = _gnutls_global_init(1);
	if (ret < 0) {
		fprintf(stderr, "Error in GnuTLS initialization: %s\n", gnutls_strerror(ret));
		_gnutls_switch_lib_state(LIB_STATE_ERROR);
	}
}
Exemple #5
0
static int _gnutls_global_init(unsigned constructor)
{
	int ret = 0, res;
	int level;
	const char* e;

	if (!constructor) {
		GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex);
	}

	_gnutls_init++;
	if (_gnutls_init > 1) {
		if (_gnutls_init == 2 && _gnutls_init_ret == 0) {
			/* some applications may close the urandom fd 
			 * before calling gnutls_global_init(). in that
			 * case reopen it */
			ret = _gnutls_rnd_check();
			if (ret < 0) {
				gnutls_assert();
				goto out;
			}
		}
		ret = _gnutls_init_ret;
		goto out;
	}

	_gnutls_switch_lib_state(LIB_STATE_INIT);

	e = secure_getenv("GNUTLS_DEBUG_LEVEL");
	if (e != NULL) {
		level = atoi(e);
		gnutls_global_set_log_level(level);
		if (_gnutls_log_func == NULL)
			gnutls_global_set_log_function(default_log_func);
		_gnutls_debug_log("Enabled GnuTLS "VERSION" logging...\n");
	}

#ifdef HAVE_DCGETTEXT
	bindtextdomain(PACKAGE, LOCALEDIR);
#endif

	res = gnutls_crypto_init();
	if (res != 0) {
		gnutls_assert();
		ret = GNUTLS_E_CRYPTO_INIT_FAILED;
		goto out;
	}

	ret = _gnutls_system_key_init();
	if (ret != 0) {
		gnutls_assert();
	}

	/* initialize ASN.1 parser
	 */
	if (asn1_check_version(GNUTLS_MIN_LIBTASN1_VERSION) == NULL) {
		gnutls_assert();
		_gnutls_debug_log
		    ("Checking for libtasn1 failed: %s < %s\n",
		     asn1_check_version(NULL),
		     GNUTLS_MIN_LIBTASN1_VERSION);
		ret = GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY;
		goto out;
	}

	_gnutls_pkix1_asn = ASN1_TYPE_EMPTY;
	res = asn1_array2tree(pkix_asn1_tab, &_gnutls_pkix1_asn, NULL);
	if (res != ASN1_SUCCESS) {
		gnutls_assert();
		ret = _gnutls_asn2err(res);
		goto out;
	}

	res = asn1_array2tree(gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL);
	if (res != ASN1_SUCCESS) {
		gnutls_assert();
		ret = _gnutls_asn2err(res);
		goto out;
	}

	/* Initialize the random generator */
	ret = _gnutls_rnd_preinit();
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	/* Initialize the default TLS extensions */
	ret = _gnutls_ext_init();
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	ret = gnutls_mutex_init(&_gnutls_file_mutex);
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	ret = gnutls_mutex_init(&_gnutls_pkcs11_mutex);
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	ret = gnutls_system_global_init();
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

#ifndef _WIN32
	ret = _gnutls_register_fork_handler();
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}
#endif

#ifdef ENABLE_FIPS140
	res = _gnutls_fips_mode_enabled();
	/* res == 1 -> fips140-2 mode enabled
	 * res == 2 -> only self checks performed - but no failure
	 * res == not in fips140 mode
	 */
	if (res != 0) {
		_gnutls_debug_log("FIPS140-2 mode: %d\n", res);
		_gnutls_priority_update_fips();

		/* first round of self checks, these are done on the
		 * nettle algorithms which are used internally */
		ret = _gnutls_fips_perform_self_checks1();
		if (res != 2) {
			if (ret < 0) {
				gnutls_assert();
				goto out;
			}
		}
	}
#endif

	_gnutls_register_accel_crypto();
	_gnutls_cryptodev_init();
	_gnutls_load_system_priorities();

#ifdef ENABLE_FIPS140
	/* These self tests are performed on the overriden algorithms
	 * (e.g., AESNI overriden AES). They are after _gnutls_register_accel_crypto()
	 * intentionally */
	if (res != 0) {
		ret = _gnutls_fips_perform_self_checks2();
		if (res != 2) {
			if (ret < 0) {
				gnutls_assert();
				goto out;
			}
		}
		_gnutls_fips_mode_reset_zombie();
	}
#endif
	_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
	ret = 0;

      out:
	_gnutls_init_ret = ret;
	if (!constructor) {
		GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex);
	}
	return ret;
}
Exemple #6
0
/**
 * gnutls_global_init:
 *
 * This function performs any required precalculations, detects
 * the supported CPU capabilities and initializes the underlying
 * cryptographic backend. In order to free any resources 
 * taken by this call you should gnutls_global_deinit() 
 * when gnutls usage is no longer needed.
 *
 * This function increments a global counter, so that
 * gnutls_global_deinit() only releases resources when it has been
 * called as many times as gnutls_global_init().  This is useful when
 * GnuTLS is used by more than one library in an application.  This
 * function can be called many times, but will only do something the
 * first time.
 *
 * Since GnuTLS 3.3.0 this function is only required in systems that
 * do not support library constructors and static linking. This
 * function also became thread safe.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int gnutls_global_init(void)
{
	int ret = 0, res;
	int level;
	const char* e;
	
	GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex);

	_gnutls_init++;
	if (_gnutls_init > 1) {
		ret = 0;
		goto out;
	}

	_gnutls_switch_lib_state(LIB_STATE_INIT);

	e = getenv("GNUTLS_DEBUG_LEVEL");
	if (e != NULL) {
		level = atoi(e);
		gnutls_global_set_log_level(level);
		if (_gnutls_log_func == NULL)
			gnutls_global_set_log_function(default_log_func);
		_gnutls_debug_log("Enabled GnuTLS logging...\n");
	}

	bindtextdomain(PACKAGE, LOCALEDIR);

	res = gnutls_crypto_init();
	if (res != 0) {
		gnutls_assert();
		ret = GNUTLS_E_CRYPTO_INIT_FAILED;
		goto out;
	}

	/* initialize ASN.1 parser
	 */
	if (asn1_check_version(GNUTLS_MIN_LIBTASN1_VERSION) == NULL) {
		gnutls_assert();
		_gnutls_debug_log
		    ("Checking for libtasn1 failed: %s < %s\n",
		     asn1_check_version(NULL),
		     GNUTLS_MIN_LIBTASN1_VERSION);
		ret = GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY;
		goto out;
	}

	res = asn1_array2tree(pkix_asn1_tab, &_gnutls_pkix1_asn, NULL);
	if (res != ASN1_SUCCESS) {
		ret = _gnutls_asn2err(res);
		goto out;
	}

	res = asn1_array2tree(gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL);
	if (res != ASN1_SUCCESS) {
		ret = _gnutls_asn2err(res);
		goto out;
	}

	/* Initialize the random generator */
	ret = _gnutls_rnd_init();
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	/* Initialize the default TLS extensions */
	ret = _gnutls_ext_init();
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	ret = gnutls_mutex_init(&_gnutls_file_mutex);
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	ret = gnutls_mutex_init(&_gnutls_pkcs11_mutex);
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	ret = gnutls_system_global_init();
	if (ret < 0) {
		gnutls_assert();
		goto out;
	}

	_gnutls_register_accel_crypto();
	_gnutls_cryptodev_init();

#ifdef ENABLE_FIPS140
	/* Perform FIPS140 checks last, so that all modules
	 * have been loaded */
	res = _gnutls_fips_mode_enabled();
	/* res == 1 -> fips140-2 mode enabled
	 * res == 2 -> only self checks performed - but no failure
	 * res == not in fips140 mode
	 */
	if (res != 0) {
		_gnutls_priority_update_fips();

		ret = _gnutls_fips_perform_self_checks();
		if (res != 2) {
			if (ret < 0) {
				gnutls_assert();
				goto out;
			}
		}
	}
#endif
	_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
	ret = 0;

      out:
	GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex);
	return ret;
}
Exemple #7
0
/* we don't use additional input */
int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
			unsigned add_size, const uint8_t *add)
{
	uint8_t tmp[AES_BLOCK_SIZE];
	uint8_t seed[DRBG_AES_SEED_SIZE];
	unsigned left;

	if (ctx->seeded == 0)
		return 0;

	if (add_size > 0) {
		if (add_size > DRBG_AES_SEED_SIZE)
			return 0;
		memcpy(seed, add, add_size);
		if (add_size != DRBG_AES_SEED_SIZE)
			memset(&seed[add_size], 0, DRBG_AES_SEED_SIZE - add_size);

		drbg_aes_update(ctx, seed);
	} else {
		memset(seed, 0, DRBG_AES_SEED_SIZE);
	}

	/* Throw the first block generated. FIPS 140-2 requirement (see 
	 * the continuous random number generator test in 4.9.2)
	 */
	if (ctx->prev_block_present == 0) {
		INCREMENT(sizeof(ctx->v), ctx->v);
		aes_encrypt(&ctx->key, AES_BLOCK_SIZE, ctx->prev_block, ctx->v);

		ctx->prev_block_present = 1;
	}

	/* Perform the actual encryption */
	for (left = length; left >= AES_BLOCK_SIZE;
	     left -= AES_BLOCK_SIZE, dst += AES_BLOCK_SIZE) {

		INCREMENT(sizeof(ctx->v), ctx->v);
		aes_encrypt(&ctx->key, AES_BLOCK_SIZE, dst, ctx->v);

		/* if detected loop */
		if (memcmp(dst, ctx->prev_block, AES_BLOCK_SIZE) == 0) {
			_gnutls_switch_lib_state(LIB_STATE_ERROR);
			return 0;
		}

		memcpy(ctx->prev_block, dst, AES_BLOCK_SIZE);
	}

	if (left > 0) {		/* partial fill */

		INCREMENT(sizeof(ctx->v), ctx->v);
		aes_encrypt(&ctx->key, AES_BLOCK_SIZE, tmp, ctx->v);

		/* if detected loop */
		if (memcmp(tmp, ctx->prev_block, AES_BLOCK_SIZE) == 0) {
			_gnutls_switch_lib_state(LIB_STATE_ERROR);
			return 0;
		}

		memcpy(ctx->prev_block, tmp, AES_BLOCK_SIZE);
		memcpy(dst, tmp, left);
	}

	if (ctx->reseed_counter > DRBG_AES_RESEED_TIME)
		return 0;
	ctx->reseed_counter++;

	drbg_aes_update(ctx, seed);

	return 1;
}
Exemple #8
0
void _gnutls_lib_simulate_error(void)
{
	_gnutls_switch_lib_state(LIB_STATE_ERROR);
}
Exemple #9
0
int _gnutls_fips_perform_self_checks2(void)
{
	int ret;

	_gnutls_switch_lib_state(LIB_STATE_SELFTEST);

	/* Tests the FIPS algorithms */

	/* ciphers - one test per cipher */
	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_3DES_CBC);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_GCM);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	/* MAC (includes message digest test) */
	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA1);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA224);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA256);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA384);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA512);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	/* PK */
	ret = gnutls_pk_self_test(0, GNUTLS_PK_RSA);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = gnutls_pk_self_test(0, GNUTLS_PK_DSA);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = gnutls_pk_self_test(0, GNUTLS_PK_EC);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = gnutls_pk_self_test(0, GNUTLS_PK_DH);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	if (_gnutls_rnd_ops.self_test == NULL) {
		gnutls_assert();
		goto error;
	}
        
	ret = _gnutls_rnd_ops.self_test();
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	if (_skip_integrity_checks == 0) {
		ret = check_binary_integrity(GNUTLS_LIBRARY_NAME, "gnutls_global_init");
		if (ret == 0) {
			gnutls_assert();
			goto error;
		}

		ret = check_binary_integrity(NETTLE_LIBRARY_NAME, "nettle_aes_set_encrypt_key");
		if (ret == 0) {
			gnutls_assert();
			goto error;
		}

		ret = check_binary_integrity(HOGWEED_LIBRARY_NAME, "nettle_mpz_sizeinbase_256_u");
		if (ret == 0) {
			gnutls_assert();
			goto error;
		}

		ret = check_binary_integrity(GMP_LIBRARY_NAME, "__gmpz_init");
		if (ret == 0) {
			gnutls_assert();
			goto error;
		}
	}
	
	return 0;

error:
	_gnutls_switch_lib_state(LIB_STATE_ERROR);
	_gnutls_audit_log(NULL, "FIPS140-2 self testing part 2 failed\n");

	return GNUTLS_E_SELF_TEST_ERROR;
}
Exemple #10
0
/* Run an HMAC using the key above on the library binary data. 
 * Returns true on success and false on error.
 */
static unsigned check_binary_integrity(const char* libname, const char* symbol)
{
	int ret;
	unsigned prev;
	char mac_file[GNUTLS_PATH_MAX];
	char file[GNUTLS_PATH_MAX];
	uint8_t hmac[HMAC_SIZE];
	uint8_t new_hmac[HMAC_SIZE];
	size_t hmac_size;
	gnutls_datum_t data;

	ret = get_library_path(libname, symbol, file, sizeof(file));
	if (ret < 0) {
		_gnutls_debug_log("Could not get path for library %s\n", libname);
		return 0;
	}

	_gnutls_debug_log("Loading: %s\n", file);
	ret = gnutls_load_file(file, &data);
	if (ret < 0) {
		_gnutls_debug_log("Could not load: %s\n", file);
		return gnutls_assert_val(0);
	}

	prev = _gnutls_get_lib_state();
	_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
	ret = gnutls_hmac_fast(HMAC_ALGO, FIPS_KEY, sizeof(FIPS_KEY)-1,
		data.data, data.size, new_hmac);
	_gnutls_switch_lib_state(prev);
	
	gnutls_free(data.data);

	if (ret < 0)
		return gnutls_assert_val(0);

	/* now open the .hmac file and compare */
	get_hmac_file(mac_file, sizeof(mac_file), file);

	ret = gnutls_load_file(mac_file, &data);
	if (ret < 0) {
		get_hmac_file2(mac_file, sizeof(mac_file), file);
		ret = gnutls_load_file(mac_file, &data);
		if (ret < 0) {
			_gnutls_debug_log("Could not open %s for MAC testing: %s\n", mac_file, gnutls_strerror(ret));
			return gnutls_assert_val(0);
		}
	}

	hmac_size = hex_data_size(data.size);
	ret = gnutls_hex_decode(&data, hmac, &hmac_size);
	gnutls_free(data.data);

	if (ret < 0) {
		_gnutls_debug_log("Could not convert hex data to binary for MAC testing for %s.\n", libname);
		return gnutls_assert_val(0);
	}

	if (hmac_size != sizeof(hmac) ||
			memcmp(hmac, new_hmac, sizeof(hmac)) != 0) {
		_gnutls_debug_log("Calculated MAC for %s does not match\n", libname);
		return gnutls_assert_val(0);
	}
	_gnutls_debug_log("Successfully verified MAC for %s (%s)\n", mac_file, libname);
	
	return 1;
}
Exemple #11
0
static int pct_test(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params)
{
int ret;
gnutls_datum_t sig = {NULL, 0};
const char const_data[20] = "onetwothreefourfive";
gnutls_datum_t ddata, tmp = {NULL,0};
char* gen_data = NULL;

	if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_EC) {
		unsigned hash_len;

		_gnutls_dsa_q_to_hash(algo, params, &hash_len);
		gen_data = gnutls_malloc(hash_len);
		gnutls_rnd(GNUTLS_RND_NONCE, gen_data, hash_len);

		ddata.data = (void*)gen_data;
		ddata.size = hash_len;
	} else {
		ddata.data = (void*)const_data;
		ddata.size = sizeof(const_data);
	}

	switch (algo) {
	case GNUTLS_PK_RSA:
		ret = _gnutls_pk_encrypt(algo, &sig, &ddata, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			goto cleanup;
		}

		if (ddata.size == sig.size && memcmp(ddata.data, sig.data, sig.size) == 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		ret = _gnutls_pk_decrypt(algo, &tmp, &sig, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		if (tmp.size != ddata.size || memcmp(tmp.data, ddata.data, tmp.size) != 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		free(sig.data);
		sig.data = NULL;

		/* Here we don't know the purpose of the key. Check both
		 * signing and encryption.
		 */
	case GNUTLS_PK_EC: /* we only do keys for ECDSA */
	case GNUTLS_PK_DSA:
		ret = _gnutls_pk_sign(algo, &sig, &ddata, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			goto cleanup;
		}

		ret = _gnutls_pk_verify(algo, &ddata, &sig, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}
		break;

	default:
		ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
		goto cleanup;
	}

	ret = 0;
cleanup:
	if (ret == GNUTLS_E_PK_GENERATION_ERROR) {
		_gnutls_switch_lib_state(LIB_STATE_ERROR);
	}
	gnutls_free(gen_data);
	gnutls_free(sig.data);
	gnutls_free(tmp.data);
	return ret;
}