static int dcrypt_gnutls_generate_keypair(struct dcrypt_keypair *pair_r, enum dcrypt_key_type kind, unsigned int bits, const char *curve, const char **error_r) { gnutls_pk_algorithm_t pk_algo; gnutls_ecc_curve_t pk_curve; if (kind == DCRYPT_KEY_EC) { pk_curve = gnutls_ecc_curve_get_id(curve); if (pk_curve == GNUTLS_ECC_CURVE_INVALID) { *error_r = "Invalid curve"; return -1; } bits = GNUTLS_CURVE_TO_BITS(pk_curve); #if GNUTLS_VERSION_NUMBER >= 0x030500 pk_algo = gnutls_curve_get_pk(pk_curve); #else pk_algo = GNUTLS_PK_EC; #endif } else if (kind == DCRYPT_KEY_RSA) { pk_algo = gnutls_pk_get_id("RSA"); } else { *error_r = "Unsupported key type"; return -1; } int ec; gnutls_privkey_t priv; if ((ec = gnutls_privkey_init(&priv)) != GNUTLS_E_SUCCESS) return dcrypt_gnutls_error(ec, error_r); #if GNUTLS_VERSION_NUMBER >= 0x030500 gnutls_privkey_set_flags(priv, GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT); #endif ec = gnutls_privkey_generate(priv, pk_algo, bits, 0); if (ec != GNUTLS_E_SUCCESS) { gnutls_privkey_deinit(priv); return dcrypt_gnutls_error(ec, error_r); } pair_r->priv = (struct dcrypt_private_key*)priv; return dcrypt_gnutls_private_to_public_key(pair_r->priv, &pair_r->pub, error_r); }
static void test_sig(gnutls_pk_algorithm_t pk, unsigned hash, unsigned bits) { gnutls_pubkey_t pubkey; gnutls_privkey_t privkey; gnutls_sign_algorithm_t sign_algo; gnutls_datum_t signature; const gnutls_datum_t *hash_data; int ret; unsigned j; if (hash == GNUTLS_DIG_SHA1) hash_data = &sha1_data; else if (hash == GNUTLS_DIG_SHA256) hash_data = &sha256_data; else abort(); sign_algo = gnutls_pk_to_sign(pk, hash); for (j = 0; j < 100; j++) { ret = gnutls_pubkey_init(&pubkey); if (ret < 0) ERR(__LINE__); ret = gnutls_privkey_init(&privkey); if (ret < 0) ERR(__LINE__); ret = gnutls_privkey_generate(privkey, pk, bits, 0); if (ret < 0) ERR(__LINE__); ret = gnutls_privkey_sign_hash(privkey, hash, 0, hash_data, &signature); if (ret < 0) ERR(__LINE__); ret = gnutls_pubkey_import_privkey(pubkey, privkey, GNUTLS_KEY_DIGITAL_SIGNATURE, 0); if (ret < 0) ERR(__LINE__); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, hash_data, &signature); if (ret < 0) ERR(__LINE__); /* should fail */ ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, &invalid_hash_data, &signature); if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) ERR(__LINE__); sign_algo = gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm (pubkey, NULL), hash); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, hash_data, &signature); if (ret < 0) ERR(__LINE__); /* should fail */ ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, &invalid_hash_data, &signature); if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) ERR(__LINE__); /* test the raw interface */ gnutls_free(signature.data); signature.data = NULL; if (pk == GNUTLS_PK_RSA) { ret = gnutls_privkey_sign_hash(privkey, hash, GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, hash_data, &signature); if (ret < 0) ERR(__LINE__); sign_algo = gnutls_pk_to_sign (gnutls_pubkey_get_pk_algorithm (pubkey, NULL), hash); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA, hash_data, &signature); if (ret < 0) ERR(__LINE__); } gnutls_free(signature.data); gnutls_privkey_deinit(privkey); gnutls_pubkey_deinit(pubkey); } }