unsigned int flags)
{
int ret;
+ bool not_approved = false;
switch (algo) {
case GNUTLS_PK_DH: {
bigint_t k = NULL, primesub1 = NULL, r = NULL;
unsigned int bits;
- if (nonce != NULL)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (nonce != NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
f = pub->params[DH_Y];
x = priv->params[DH_X];
prime = priv->params[DH_P];
ret = _gnutls_mpi_init_multi(&k, &primesub1, &r, NULL);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
ret = _gnutls_mpi_sub_ui(primesub1, prime, 1);
if (ret < 0) {
} else if ((flags & PK_DERIVE_TLS13) &&
_gnutls_fips_mode_enabled()) {
/* Mandatory in FIPS mode for TLS 1.3 */
- ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
goto dh_cleanup;
}
goto dh_cleanup;
}
+ if (bits < 2048) {
+ not_approved = true;
+ }
ret = _gnutls_mpi_powm(k, f, x, prime);
if (ret < 0) {
if ((_gnutls_mpi_cmp_ui(k, 1) == 0)
|| (_gnutls_mpi_cmp_ui(k, 0) == 0)
|| (_gnutls_mpi_cmp(k, primesub1) == 0)) {
- gnutls_assert();
- ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
goto dh_cleanup;
}
out->data = NULL;
- if (nonce != NULL)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (nonce != NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
curve = get_supported_nist_curve(priv->curve);
- if (curve == NULL)
- return
- gnutls_assert_val
- (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (curve == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
+
+ /* P-192 is not supported in FIPS 140-3 */
+ if (priv->curve == GNUTLS_ECC_CURVE_SECP192R1) {
+ not_approved = true;
+ }
ret = _ecc_params_to_pubkey(pub, &ecc_pub, curve);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
ret =
_ecc_params_to_privkey(priv, &ecc_priv, curve);
if (ret < 0) {
ecc_point_clear(&ecc_pub);
- return gnutls_assert_val(ret);
+ gnutls_assert();
+ goto cleanup;
}
out->size = gnutls_ecc_curve_get_size(priv->curve);
{
unsigned size = gnutls_ecc_curve_get_size(priv->curve);
- if (nonce != NULL)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ /* Edwards curves are not approved */
+ not_approved = true;
+
+ if (nonce != NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
/* The point is in pub, while the private part (scalar) in priv. */
- if (size == 0 || priv->raw_priv.size != size)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (size == 0 || priv->raw_priv.size != size) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
out->data = gnutls_malloc(size);
if (out->data == NULL) {
struct ecc_point ecc_pub;
const struct ecc_curve *curve;
+ /* GOST curves are not approved */
+ not_approved = true;
+
out->data = NULL;
curve = get_supported_gost_curve(priv->curve);
- if (curve == NULL)
- return
- gnutls_assert_val
- (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (curve == NULL) {
+ gnutls_assert();
+ ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
+ goto cleanup;
+ }
- if (nonce == NULL)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (nonce == NULL) {
+ gnutls_assert();
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
ret = _gost_params_to_pubkey(pub, &ecc_pub, curve);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
ret = _gost_params_to_privkey(priv, &ecc_priv, curve);
if (ret < 0) {
ecc_point_clear(&ecc_pub);
- return gnutls_assert_val(ret);
+ gnutls_assert();
+ goto cleanup;
}
out->size = 2 * gnutls_ecc_curve_get_size(priv->curve);
ret = 0;
cleanup:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else if (not_approved) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+ }
return ret;
}
ret = 0;
cleanup:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ }
+
mpz_clear(p);
FAIL_IF_LIB_ERROR;
_rsa_params_to_privkey(pk_params, &priv);
ret = _rsa_params_to_pubkey(pk_params, &pub);
- if (ret < 0)
- return
- gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
- if (ciphertext->size != pub.size)
- return
- gnutls_assert_val
- (GNUTLS_E_DECRYPTION_FAILED);
+ if (ciphertext->size != pub.size) {
+ ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
+ goto cleanup;
+ }
if (_gnutls_mpi_init_scan_nz
(&c, ciphertext->data,
ret = 0;
cleanup:
- if (ret < 0)
+ if (ret < 0) {
gnutls_free(plaintext->data);
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ }
FAIL_IF_LIB_ERROR;
return ret;
FAIL_IF_LIB_ERROR;
if (algo != GNUTLS_PK_RSA || plaintext == NULL) {
- gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
+ ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ goto fail;
}
_rsa_params_to_privkey(pk_params, &priv);
ret = _rsa_params_to_pubkey(pk_params, &pub);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
- if (ciphertext->size != pub.size)
- return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
+ if (ciphertext->size != pub.size) {
+ ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
+ goto fail;
+ }
if (_gnutls_mpi_init_scan_nz(&c, ciphertext->data,
ciphertext->size) != 0) {
- return gnutls_assert_val (GNUTLS_E_MPI_SCAN_FAILED);
+ ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
+ goto fail;
}
if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST)
random_func = rnd_nonce_func;
ret = rsa_sec_decrypt(&pub, &priv, NULL, random_func,
plaintext_size, plaintext, TOMPZ(c));
+
+ /* The decrypt operation is infallible; treat the approved
+ * operation as complete at this point, regardless of any
+ * decryption failure detected below.
+ */
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+
/* after this point, any conditional on failure that cause differences
* in execution may create a timing or cache access pattern side
* channel that can be used as an oracle, so thread very carefully */
is_err |= CONSTCHECK_EQUAL(ret, 0);
/* then return GNUTLS_E_DECRYPTION_FAILED */
return (int)((is_err * UINT_MAX) & GNUTLS_E_DECRYPTION_FAILED);
+
+ fail:
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+
+ return ret;
}
#define CHECK_INVALID_RSA_PSS_PARAMS(dig_size, salt_size, pub_size, err) \
int ret;
unsigned int hash_len;
const mac_entry_st *me;
+ bool not_approved = false;
FAIL_IF_LIB_ERROR;
- if (IS_EC(algo)) {
- /* check if the curve relates to the algorithm used */
- if (gnutls_ecc_curve_get_pk(pk_params->curve) != algo)
- return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ /* check if the curve relates to the algorithm used */
+ if (IS_EC(algo) && gnutls_ecc_curve_get_pk(pk_params->curve) != algo) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
}
/* deterministic ECDSA/DSA is prohibited under FIPS except in
* the selftests */
- if (_gnutls_fips_mode_enabled() &&
- _gnutls_get_lib_state() != LIB_STATE_SELFTEST &&
- (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_ECDSA) &&
- (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE))
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if ((algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_ECDSA) &&
+ (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE) &&
+ _gnutls_fips_mode_enabled() &&
+ _gnutls_get_lib_state() != LIB_STATE_SELFTEST) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
switch (algo) {
case GNUTLS_PK_EDDSA_ED25519: /* we do EdDSA */
{
const gnutls_ecc_curve_entry_st *e;
- if (unlikely(get_eddsa_curve(algo) != pk_params->curve))
- return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ /* EdDSA is not approved yet */
+ not_approved = true;
+
+ if (unlikely(get_eddsa_curve(algo) != pk_params->curve)) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
e = _gnutls_ecc_curve_get_params(pk_params->curve);
- if (e == NULL)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (e == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
signature->data = gnutls_malloc(e->sig_size);
if (signature->data == NULL) {
struct dsa_signature sig;
const struct ecc_curve *curve;
+ /* GOSTDSA is not approved */
+ not_approved = true;
+
curve = get_supported_gost_curve(pk_params->curve);
- if (curve == NULL)
- return
- gnutls_assert_val
- (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (curve == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
ret =
_ecc_params_to_privkey(pk_params, &priv,
curve);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
/* This call will return a valid MAC entry and
* getters will check that is not null anyway. */
me = hash_to_entry(_gnutls_gost_digest(pk_params->algo));
if (_gnutls_mac_get_algo_len(me) != vdata->size) {
- gnutls_assert();
_gnutls_debug_log
("Security level of algorithm requires hash %s(%zd)\n",
_gnutls_mac_get_name(me),
_gnutls_mac_get_algo_len(me));
- return GNUTLS_E_INVALID_REQUEST;
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
}
dsa_signature_init(&sig);
nettle_random_func *random_func;
curve = get_supported_nist_curve(curve_id);
- if (curve == NULL)
- return
- gnutls_assert_val
- (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (curve == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
+
+ /* P-192 is not supported in FIPS 140-3 */
+ if (curve_id == GNUTLS_ECC_CURVE_SECP192R1) {
+ not_approved = true;
+ }
ret =
_ecc_params_to_privkey(pk_params, &priv,
curve);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
dsa_signature_init(&sig);
me = _gnutls_dsa_q_to_hash(pk_params,
&hash_len);
+ /* Only SHA-2 is allowed in FIPS 140-3 */
+ switch (me->id) {
+ case GNUTLS_MAC_SHA256:
+ case GNUTLS_MAC_SHA384:
+ case GNUTLS_MAC_SHA512:
+ case GNUTLS_MAC_SHA224:
+ break;
+ default:
+ not_approved = true;
+ }
+
if (hash_len > vdata->size) {
gnutls_assert();
_gnutls_debug_log
void *random_ctx;
nettle_random_func *random_func;
+ /* DSA is currently being defined as sunset with the
+ * current draft of FIPS 186-5 */
+ not_approved = true;
+
memset(&priv, 0, sizeof(priv));
memset(&pub, 0, sizeof(pub));
_dsa_params_get(pk_params, &pub);
mpz_t s;
_rsa_params_to_privkey(pk_params, &priv);
+
+ /* RSA key size should be 2048-bit or larger in FIPS
+ * 140-3. In addition to this, only SHA-2 is allowed
+ * for SigGen; it is checked in pk_prepare_hash lib/pk.c
+ */
+ if (unlikely(priv.size < 256)) {
+ not_approved = true;
+ }
+
ret = _rsa_params_to_pubkey(pk_params, &pub);
- if (ret < 0)
- return
- gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
mpz_init(s);
mpz_t s;
_rsa_params_to_privkey(pk_params, &priv);
+
+ /* RSA key size should be 2048-bit or larger in FIPS
+ * 140-3. In addition to this, only SHA-2 is allowed
+ * for SigGen; however, Nettle only support SHA256,
+ * SHA384, and SHA512 for RSA-PSS (see
+ * _rsa_pss_sign_digest_tr in this file for details).
+ */
+ if (unlikely(priv.size < 256)) {
+ not_approved = true;
+ }
+
ret = _rsa_params_to_pubkey(pk_params, &pub);
- if (ret < 0)
- return
- gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
mpz_init(s);
ret = 0;
cleanup:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else if (not_approved) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+ }
FAIL_IF_LIB_ERROR;
return ret;
int ret;
unsigned int hash_len;
bigint_t tmp[2] = { NULL, NULL };
+ bool not_approved = false;
FAIL_IF_LIB_ERROR;
- if (IS_EC(algo)) {
- /* check if the curve relates to the algorithm used */
- if (gnutls_ecc_curve_get_pk(pk_params->curve) != algo)
- return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ /* check if the curve relates to the algorithm used */
+ if (IS_EC(algo) && gnutls_ecc_curve_get_pk(pk_params->curve) != algo) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
}
switch (algo) {
{
const gnutls_ecc_curve_entry_st *e;
- if (unlikely(get_eddsa_curve(algo) != pk_params->curve))
- return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ /* EdDSA is not approved yet */
+ not_approved = true;
+
+ if (unlikely(get_eddsa_curve(algo) != pk_params->curve)) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
e = _gnutls_ecc_curve_get_params(pk_params->curve);
- if (e == NULL)
- return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (e == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
- if (signature->size != e->sig_size)
- return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ if (signature->size != e->sig_size) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ goto cleanup;
+ }
- if (pk_params->raw_pub.size != e->size)
- return gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED);
+ if (pk_params->raw_pub.size != e->size) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED);
+ goto cleanup;
+ }
ret = eddsa_verify(algo,
pk_params->raw_pub.data,
const struct ecc_curve *curve;
const mac_entry_st *me;
+ /* GOSTDSA is not approved */
+ not_approved = true;
+
curve = get_supported_gost_curve(pk_params->curve);
- if (curve == NULL)
- return
- gnutls_assert_val
- (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (curve == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
/* This call will return a valid MAC entry and
* getters will check that is not null anyway. */
me = hash_to_entry(_gnutls_gost_digest(pk_params->algo));
- if (_gnutls_mac_get_algo_len(me) != vdata->size)
- return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ if (_gnutls_mac_get_algo_len(me) != vdata->size) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ goto cleanup;
+ }
ret =
_gnutls_decode_gost_rs(signature, &tmp[0],
&tmp[1]);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
ret =
_gost_params_to_pubkey(pk_params, &pub, curve);
struct dsa_signature sig;
int curve_id = pk_params->curve;
const struct ecc_curve *curve;
+ const mac_entry_st *me;
curve = get_supported_nist_curve(curve_id);
- if (curve == NULL)
- return
- gnutls_assert_val
- (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (curve == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
ret =
_gnutls_decode_ber_rs(signature, &tmp[0],
&tmp[1]);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
ret =
_ecc_params_to_pubkey(pk_params, &pub, curve);
memcpy(sig.r, tmp[0], SIZEOF_MPZT);
memcpy(sig.s, tmp[1], SIZEOF_MPZT);
- _gnutls_dsa_q_to_hash(pk_params, &hash_len);
+ me = _gnutls_dsa_q_to_hash(pk_params, &hash_len);
+
+ /* SHA-1 is allowed for SigVer in FIPS 140-3 in legacy
+ * mode */
+ switch (me->id) {
+ case GNUTLS_MAC_SHA1:
+ case GNUTLS_MAC_SHA256:
+ case GNUTLS_MAC_SHA384:
+ case GNUTLS_MAC_SHA512:
+ case GNUTLS_MAC_SHA224:
+ break;
+ default:
+ not_approved = true;
+ }
if (hash_len > vdata->size)
hash_len = vdata->size;
struct dsa_signature sig;
bigint_t y;
+ /* DSA is currently being defined as sunset with the
+ * current draft of FIPS 186-5 */
+ not_approved = true;
+
ret =
_gnutls_decode_ber_rs(signature, &tmp[0],
&tmp[1]);
struct rsa_public_key pub;
ret = _rsa_params_to_pubkey(pk_params, &pub);
- if (ret < 0)
- return
- gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
- if (signature->size != pub.size)
- return
- gnutls_assert_val
- (GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ /* RSA key size should be 2048-bit or larger in FIPS
+ * 140-3. In addition to this, only SHA-1 and SHA-2 are
+ * allowed for SigVer; it is checked in
+ * _pkcs1_rsa_verify_sig in lib/pubkey.c
+ */
+ if (unlikely(pub.size < 256)) {
+ not_approved = true;
+ }
+
+ if (signature->size != pub.size) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ goto cleanup;
+ }
ret =
_gnutls_mpi_init_scan_nz(&tmp[0], signature->data,
if ((sign_params->flags &
GNUTLS_PK_FLAG_RSA_PSS_FIXED_SALT_LENGTH) &&
sign_params->salt_size != vdata->size) {
- return gnutls_assert_val
- (GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ goto cleanup;
}
ret = _rsa_params_to_pubkey(pk_params, &pub);
- if (ret < 0)
- return
- gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
- if (signature->size != pub.size)
- return
- gnutls_assert_val
- (GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ /* RSA key size should be 2048-bit or larger in FIPS
+ * 140-3. In addition to this, only SHA-1 and SHA-2 are
+ * allowed for SigVer, while Nettle only supports
+ * SHA256, SHA384, and SHA512 for RSA-PSS (see
+ * _rsa_pss_verify_digest in this file for the details).
+ */
+ if (unlikely(pub.size < 256)) {
+ not_approved = true;
+ }
+
+ if (signature->size != pub.size) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ goto cleanup;
+ }
ret =
_gnutls_mpi_init_scan_nz(&tmp[0], signature->data,
}
cleanup:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else if (not_approved) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+ }
_gnutls_mpi_release(&tmp[0]);
_gnutls_mpi_release(&tmp[1]);
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";
-const char const_data_sha256[32] = "onetwothreefourfivesixseveneight";
-const char const_data_sha384[48] = "onetwothreefourfivesixseveneightnineteneleventwe";
-const char const_data_sha512[64] = "onetwothreefourfivesixseveneightnineteneleventwelvethirteenfourt";
-gnutls_datum_t ddata, tmp = {NULL,0};
-char* gen_data = NULL;
-gnutls_x509_spki_st spki;
+ int ret;
+ gnutls_datum_t sig = {NULL, 0};
+ const char const_data[20] = "onetwothreefourfive";
+ const char const_data_sha256[32] = "onetwothreefourfivesixseveneight";
+ const char const_data_sha384[48] = "onetwothreefourfivesixseveneightnineteneleventwe";
+ const char const_data_sha512[64] = "onetwothreefourfivesixseveneightnineteneleventwelvethirteenfourt";
+ gnutls_datum_t ddata, tmp = {NULL,0};
+ char* gen_data = NULL;
+ gnutls_x509_spki_st spki;
+ gnutls_fips140_context_t context;
memcpy(&spki, ¶ms->spki, sizeof(spki));
switch (algo) {
case GNUTLS_PK_RSA:
- ret = _gnutls_pk_encrypt(algo, &sig, &ddata, params);
- if (ret < 0) {
+ /* Push a temporary FIPS context because _gnutls_pk_encrypt and
+ * _gnutls_pk_decrypt below will mark RSAES-PKCS1-v1_5 operation
+ * non-approved */
+ if (gnutls_fips140_context_init(&context) < 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) {
+ if (gnutls_fips140_push_context(context) < 0) {
ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
- gnutls_assert();
+ gnutls_fips140_context_deinit(context);
goto cleanup;
}
- ret = _gnutls_pk_decrypt(algo, &tmp, &sig, params);
+ ret = _gnutls_pk_encrypt(algo, &sig, &ddata, params);
if (ret < 0) {
ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
- gnutls_assert();
- goto cleanup;
+ }
+ if (ret == 0 &&
+ ddata.size == sig.size &&
+ memcmp(ddata.data, sig.data, sig.size) == 0) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
+ }
+ if (ret == 0 &&
+ _gnutls_pk_decrypt(algo, &tmp, &sig, params) < 0) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
+ }
+ if (ret == 0 &&
+ !(tmp.size == ddata.size &&
+ memcmp(tmp.data, ddata.data, tmp.size) == 0)) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
}
- if (tmp.size != ddata.size || memcmp(tmp.data, ddata.data, tmp.size) != 0) {
+ if (unlikely(gnutls_fips140_pop_context() < 0)) {
ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
- gnutls_assert();
+ }
+ gnutls_fips140_context_deinit(context);
+
+ if (ret < 0) {
goto cleanup;
}
unsigned int i;
unsigned rnd_level;
nettle_random_func *rnd_func;
+ bool not_approved = false;
FAIL_IF_LIB_ERROR;
- if (IS_EC(algo)) {
- /* check if the curve relates to the algorithm used */
- if (gnutls_ecc_curve_get_pk(level) != algo)
- return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ /* check if the curve relates to the algorithm used */
+ if (IS_EC(algo) && gnutls_ecc_curve_get_pk(level) != algo) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
}
if (ephemeral) {
struct dsa_params pub;
mpz_t x, y;
- if (params->params[DSA_Q] == NULL)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ /* DSA is currently being defined as sunset with the
+ * current draft of FIPS 186-5 */
+ not_approved = true;
+
+ if (params->params[DSA_Q] == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
_dsa_params_get(params, &pub);
mpz_clear(y);
if (ret < 0)
- goto fail;
+ goto cleanup;
break;
}
mpz_t primesub1;
mpz_t ypowq;
- if (algo != params->algo)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (algo != params->algo) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
_dsa_params_get(params, &pub);
have_q = 1;
/* This check is for the case !ENABLE_FIPS140 */
- if (algo == GNUTLS_PK_DSA && have_q == 0)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (algo == GNUTLS_PK_DSA && have_q == 0) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
mpz_init(r);
mpz_init(x);
mpz_clear(ypowq);
if (ret < 0)
- goto fail;
+ goto cleanup;
break;
}
} while (ret != 1 && ++retries < 3);
}
} else {
+ not_approved = true;
+
ret =
rsa_generate_keypair(&pub, &priv, NULL,
rnd_func, NULL, NULL,
params->params_nr++;
}
+ /* In FIPS 140-3, pub.n should be 2048-bit or larger; it
+ * is assured in rsa_generate_fips186_4_keypair in
+ * lib/nettle/int/rsa-keygen-fips186.c. */
+
mpz_set(TOMPZ(params->params[RSA_MODULUS]), pub.n);
mpz_set(TOMPZ(params->params[RSA_PUB]), pub.e);
mpz_set(TOMPZ(params->params[RSA_PRIV]), priv.d);
rsa_public_key_clear(&pub);
if (ret < 0)
- goto fail;
+ goto cleanup;
break;
}
{
unsigned size = gnutls_ecc_curve_get_size(level);
- if (params->pkflags & GNUTLS_PK_FLAG_PROVABLE)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ /* EdDSA is not approved yet */
+ not_approved = true;
+
+ if (params->pkflags & GNUTLS_PK_FLAG_PROVABLE) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
- if (unlikely(get_eddsa_curve(algo) != level))
- return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (unlikely(get_eddsa_curve(algo) != level)) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
- if (size == 0)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (size == 0) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
params->curve = level;
params->raw_priv.data = gnutls_malloc(size);
- if (params->raw_priv.data == NULL)
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ if (params->raw_priv.data == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ goto cleanup;
+ }
params->raw_pub.data = gnutls_malloc(size);
if (params->raw_pub.data == NULL) {
ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- goto fail;
+ goto cleanup;
}
ret = gnutls_rnd(rnd_level, params->raw_priv.data, size);
if (ret < 0) {
ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- goto fail;
+ goto cleanup;
}
params->raw_pub.size = size;
params->raw_priv.size = size;
params->raw_pub.data,
params->raw_priv.data);
if (ret < 0)
- goto fail;
+ goto cleanup;
break;
}
mpz_t x, y, xx, yy, nn, mm;
curve = get_supported_nist_curve(level);
- if (curve == NULL)
- return
- gnutls_assert_val
- (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (curve == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
+
+ /* P-192 is not supported in FIPS 140-3 */
+ if (level == GNUTLS_ECC_CURVE_SECP192R1) {
+ not_approved = true;
+ }
mpz_init(x);
mpz_init(y);
ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
goto ecc_fail;
}
+ } else {
+ not_approved = true;
}
#endif
ecc_scalar_clear(&m);
if (ret < 0)
- goto fail;
+ goto cleanup;
break;
}
const struct ecc_curve *curve;
const mac_entry_st *me;
+ /* GOST curves are not approved */
+ not_approved = true;
+
curve = get_supported_gost_curve(level);
- if (curve == NULL)
- return
- gnutls_assert_val
- (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ if (curve == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ goto cleanup;
+ }
me = hash_to_entry(_gnutls_gost_digest(algo));
- if (!me || me->output_size * 8 != ecc_bit_size(curve))
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (!me || me->output_size * 8 != ecc_bit_size(curve)) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
ecc_scalar_init(&key, curve);
ecc_point_init(&pub, curve);
ecc_scalar_clear(&key);
if (ret < 0)
- goto fail;
+ goto cleanup;
break;
}
{
unsigned size = gnutls_ecc_curve_get_size(level);
- if (size == 0)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ not_approved = true;
+
+ if (size == 0) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
params->curve = level;
params->raw_priv.data = gnutls_malloc(size);
- if (params->raw_priv.data == NULL)
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ if (params->raw_priv.data == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ goto cleanup;
+ }
params->raw_pub.data = gnutls_malloc(size);
if (params->raw_pub.data == NULL) {
ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- goto fail;
+ goto cleanup;
}
ret = gnutls_rnd(rnd_level, params->raw_priv.data, size);
if (ret < 0) {
ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- goto fail;
+ goto cleanup;
}
params->raw_pub.size = size;
params->raw_priv.size = size;
ret = edwards_curve_mul_g(algo, params->raw_pub.data, params->raw_priv.data);
if (ret < 0)
- goto fail;
+ goto cleanup;
break;
}
default:
ret = pct_test(algo, params);
if (ret < 0) {
gnutls_assert();
- goto fail;
+ goto cleanup;
}
#endif
- FAIL_IF_LIB_ERROR;
- return 0;
-
- fail:
-
- for (i = 0; i < params->params_nr; i++) {
- _gnutls_mpi_release(¶ms->params[i]);
+ cleanup:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ for (i = 0; i < params->params_nr; i++) {
+ _gnutls_mpi_release(¶ms->params[i]);
+ }
+ params->params_nr = 0;
+ gnutls_free(params->raw_priv.data);
+ gnutls_free(params->raw_pub.data);
+ } else if (not_approved) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
}
- params->params_nr = 0;
- gnutls_free(params->raw_priv.data);
- gnutls_free(params->raw_pub.data);
FAIL_IF_LIB_ERROR;
return ret;
static uint8_t key16[16];
static uint8_t iv16[16];
+static const gnutls_datum_t data = { .data = (unsigned char *)"foo", 3 };
+static const uint8_t rsa2342_sha1_sig_data[] = {
+ 0x9b, 0x3e, 0x15, 0x36, 0xec, 0x9d, 0x51, 0xd7, 0xa2, 0xb1, 0x3a, 0x15,
+ 0x1a, 0xfe, 0x4e, 0x12, 0x43, 0x3c, 0xa8, 0x58, 0x4c, 0x2a, 0x82, 0xc1,
+ 0x02, 0x3f, 0xc0, 0x6f, 0xa2, 0x23, 0xba, 0x58, 0x9f, 0xc0, 0xfc, 0x87,
+ 0x5e, 0xfd, 0x13, 0x32, 0xa6, 0xd9, 0x72, 0x63, 0x04, 0x68, 0xb9, 0x0f,
+ 0x46, 0x21, 0x3f, 0x7f, 0xe1, 0xa2, 0xb0, 0xfa, 0x66, 0x84, 0xd9, 0x64,
+ 0x87, 0x40, 0x31, 0x27, 0xec, 0xb3, 0xbb, 0x53, 0xb5, 0x8f, 0xf9, 0x3c,
+ 0x45, 0x1c, 0xcc, 0x30, 0xf5, 0xab, 0x9e, 0x1b, 0x86, 0x92, 0x6a, 0x58,
+ 0xeb, 0xa1, 0x87, 0x71, 0x40, 0xfb, 0x9d, 0x8f, 0x2c, 0x82, 0x32, 0xe1,
+ 0x7f, 0xfc, 0xe9, 0xd1, 0x76, 0xa3, 0x56, 0xdf, 0x38, 0xdb, 0xe2, 0x8a,
+ 0xd3, 0x7e, 0xb4, 0xe2, 0xc9, 0x6a, 0xb2, 0x02, 0xe8, 0xf6, 0x34, 0xde,
+ 0x51, 0x36, 0xd7, 0x3a, 0xba, 0x0f, 0x51, 0x3d, 0xb0, 0xe8, 0x8e, 0x58,
+ 0x72, 0x1c, 0x89, 0xac, 0x68, 0xa5, 0x03, 0xb1, 0xd6, 0x5d, 0x32, 0x2f,
+ 0x3c, 0x71, 0xcc, 0xc2, 0xd7, 0xf9, 0x51, 0xb1, 0xc8, 0x07, 0x07, 0x63,
+ 0xe7, 0xa9, 0x9b, 0x9f, 0xdb, 0xc5, 0xb5, 0x68, 0xfd, 0xed, 0x11, 0x0c,
+ 0xa7, 0xfa, 0x08, 0x59, 0xa8, 0x84, 0xcd, 0x36, 0x6b, 0xa5, 0xfe, 0xf9,
+ 0xd3, 0xe1, 0x36, 0xaf, 0x71, 0x47, 0x39, 0x1e, 0xb7, 0xbc, 0x06, 0x66,
+ 0xb8, 0xd7, 0x6d, 0x37, 0x6d, 0x52, 0x85, 0x34, 0x2b, 0x05, 0x62, 0x2e,
+ 0xbe, 0x6d, 0xa3, 0x76, 0xcd, 0xe0, 0xd6, 0x3e, 0x9d, 0xcf, 0x74, 0xf9,
+ 0xb4, 0x6b, 0xc0, 0x20, 0xe9, 0xd7, 0x19, 0x2d, 0xe6, 0x8a, 0xfd, 0xa2,
+ 0xa4, 0x4a, 0xea, 0x01, 0x91, 0xf5, 0xb5, 0x29, 0x7a, 0xda, 0x68, 0xc6,
+ 0x6c, 0xa0, 0x99, 0x5b, 0x79, 0x18, 0x96, 0xb1, 0xbe, 0x38, 0x74, 0x66,
+ 0x4b, 0x47, 0x46, 0x89, 0xea, 0x25, 0x2a, 0x9e, 0x3a, 0xdc, 0x49, 0x6b,
+ 0xba, 0xcb, 0xe4, 0x7a, 0x8f, 0x60, 0x35, 0xf3, 0x9f, 0x9d, 0xeb, 0x9d,
+ 0xfa, 0x0c, 0xaf, 0x6e, 0x47, 0x65, 0xaf, 0x17, 0x18, 0x56, 0x16, 0xe8,
+ 0x01, 0xd5, 0x55, 0xdf, 0xca, 0x41, 0x63, 0xd0, 0x48, 0x9b, 0x08, 0xdb,
+ 0xdd, 0x73, 0x4a, 0xa5,
+};
+
+static const gnutls_datum_t rsa2342_sha1_sig = {
+ .data = (unsigned char *)rsa2342_sha1_sig_data,
+ .size = sizeof(rsa2342_sha1_sig_data),
+};
+
+static void
+rsa_import_keypair(gnutls_privkey_t *privkey, gnutls_pubkey_t *pubkey,
+ const char *filename)
+{
+ const char *srcdir;
+ char path[256];
+ gnutls_datum_t tmp;
+ gnutls_x509_privkey_t xprivkey;
+ int ret;
+
+ ret = gnutls_x509_privkey_init(&xprivkey);
+ if (ret < 0) {
+ fail("gnutls_x509_privkey_init failed\n");
+ }
+ srcdir = getenv("srcdir");
+ if (!srcdir) {
+ srcdir = ".";
+ }
+ snprintf(path, sizeof(path), "%s/certs/%s", srcdir, filename);
+ ret = gnutls_load_file(path, &tmp);
+ if (ret < 0) {
+ fail("gnutls_load_file failed\n");
+ }
+ ret = gnutls_x509_privkey_import(xprivkey, &tmp, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fail("gnutls_x509_privkey_import failed\n");
+ }
+ gnutls_free(tmp.data);
+
+ ret = gnutls_privkey_init(privkey);
+ if (ret < 0) {
+ fail("gnutls_privkey_init failed\n");
+ }
+ ret = gnutls_privkey_import_x509(*privkey, xprivkey,
+ GNUTLS_PRIVKEY_IMPORT_COPY);
+ if (ret < 0) {
+ fail("gnutls_privkey_import_x509 failed\n");
+ }
+ gnutls_x509_privkey_deinit(xprivkey);
+
+ ret = gnutls_pubkey_init(pubkey);
+ if (ret < 0) {
+ fail("gnutls_pubkey_init failed\n");
+ }
+ ret = gnutls_pubkey_import_privkey(*pubkey, *privkey,
+ GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
+ if (ret < 0) {
+ fail("gnutls_pubkey_import_privkey failed\n");
+ }
+
+}
+
void doit(void)
{
int ret;
gnutls_privkey_t privkey;
gnutls_datum_t key = { key16, sizeof(key16) };
gnutls_datum_t iv = { iv16, sizeof(iv16) };
+ gnutls_fips140_context_t fips_context;
+ gnutls_fips140_operation_state_t fips_state;
+ gnutls_datum_t signature;
+ unsigned int bits;
fprintf(stderr,
"Please note that if in FIPS140 mode, you need to assure the library's integrity prior to running this test\n");
fail("Cannot initialize library\n");
}
+ ret = gnutls_fips140_context_init(&fips_context);
+ if (ret < 0) {
+ fail("Cannot initialize FIPS context\n");
+ }
+ fips_state = gnutls_fips140_get_operation_state(fips_context);
+ if (fips_state != GNUTLS_FIPS140_OP_INITIAL) {
+ fail("operation state is not initial\n");
+ }
+ ret = gnutls_fips140_pop_context();
+ if (ret != GNUTLS_E_INVALID_REQUEST) {
+ fail("gnutls_fips140_pop_context succeeded while not pushed\n");
+ }
+
+#define FIPS_PUSH_CONTEXT() do { \
+ ret = gnutls_fips140_push_context(fips_context); \
+ if (ret < 0) { \
+ fail("gnutls_fips140_push_context failed\n"); \
+ } \
+} while (0)
+
+#define FIPS_POP_CONTEXT(state) do { \
+ ret = gnutls_fips140_pop_context(); \
+ if (ret < 0) { \
+ fail("gnutls_fips140_context_pop failed\n"); \
+ } \
+ fips_state = gnutls_fips140_get_operation_state(fips_context); \
+ if (fips_state != GNUTLS_FIPS140_OP_ ## state) { \
+ fail("operation state is not " # state " (%d)\n", \
+ fips_state); \
+ } \
+} while (0)
+
/* Try crypto.h functionality */
ret =
gnutls_cipher_init(&ch, GNUTLS_CIPHER_AES_128_CBC, &key, &iv);
}
gnutls_deinit(session);
+ /* Generate 2048-bit RSA key */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_x509_privkey_init(&xprivkey);
+ if (ret < 0) {
+ fail("gnutls_privkey_init failed\n");
+ }
+ bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_RSA, GNUTLS_SEC_PARAM_MEDIUM);
+ ret = gnutls_x509_privkey_generate(xprivkey, GNUTLS_PK_RSA, bits, 0);
+ if (ret < 0) {
+ fail("gnutls_x509_privkey_generate failed (%d) for %u-bit key\n",
+ ret, bits);
+ }
+ gnutls_x509_privkey_deinit(xprivkey);
+ FIPS_POP_CONTEXT(APPROVED);
+
+ /* Generate 512-bit RSA key */
+ FIPS_PUSH_CONTEXT();
ret = gnutls_x509_privkey_init(&xprivkey);
if (ret < 0) {
fail("gnutls_privkey_init failed\n");
fail("gnutls_x509_privkey_generate succeeded (%d) for 512-bit key\n", ret);
}
gnutls_x509_privkey_deinit(xprivkey);
+ FIPS_POP_CONTEXT(ERROR);
+
+ /* Import 2432-bit RSA key; not a security function */
+ FIPS_PUSH_CONTEXT();
+ rsa_import_keypair(&privkey, &pubkey, "rsa-2432.pem");
+ FIPS_POP_CONTEXT(INITIAL);
+
+ /* Create a signature with SHA256; approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
+ &data, &signature);
+ if (ret < 0) {
+ fail("gnutls_privkey_sign_data failed\n");
+ }
+ gnutls_free(signature.data);
+ FIPS_POP_CONTEXT(APPROVED);
+
+ /* Create a signature with SHA-1; not approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0,
+ &data, &signature);
+ if (ret < 0) {
+ fail("gnutls_privkey_sign_data failed\n");
+ }
+ gnutls_free(signature.data);
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+
+ /* Verify a signature created with SHA-1; approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &data,
+ &rsa2342_sha1_sig);
+ if (ret < 0) {
+ fail("gnutls_pubkey_verify_data2 failed\n");
+ }
+ FIPS_POP_CONTEXT(APPROVED);
+ gnutls_pubkey_deinit(pubkey);
+ gnutls_privkey_deinit(privkey);
+
+ /* Import 512-bit RSA key; not a security function */
+ FIPS_PUSH_CONTEXT();
+ rsa_import_keypair(&privkey, &pubkey, "rsa-512.pem");
+ FIPS_POP_CONTEXT(INITIAL);
+
+ /* Create a signature; not approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
+ &data, &signature);
+ if (ret < 0) {
+ fail("gnutls_privkey_sign_data failed\n");
+ }
+ gnutls_free(signature.data);
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+ gnutls_pubkey_deinit(pubkey);
+ gnutls_privkey_deinit(privkey);
/* Test when FIPS140 is set to error state */
_gnutls_lib_simulate_error();
fail("gnutls_init succeeded when in FIPS140 error state\n");
}
+ gnutls_fips140_context_deinit(fips_context);
gnutls_global_deinit();
return;
}