static int _wrap_nettle_pk_encrypt(gnutls_pk_algorithm_t algo, gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, const gnutls_pk_params_st * pk_params) { int ret; mpz_t p; mpz_init(p); switch (algo) { case GNUTLS_PK_RSA: { struct rsa_public_key pub; _rsa_params_to_pubkey(pk_params, &pub); ret = rsa_encrypt(&pub, NULL, rnd_func, plaintext->size, plaintext->data, p); if (ret == 0) { ret = gnutls_assert_val (GNUTLS_E_ENCRYPTION_FAILED); goto cleanup; } ret = _gnutls_mpi_dprint_size(p, ciphertext, pub.size); if (ret < 0) { gnutls_assert(); goto cleanup; } break; } default: gnutls_assert(); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: mpz_clear(p); FAIL_IF_LIB_ERROR; return ret; }
static int _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo, const gnutls_datum_t * vdata, const gnutls_datum_t * signature, const gnutls_pk_params_st * pk_params) { int ret; unsigned int hash_len; bigint_t tmp[2] = { NULL, NULL }; switch (algo) { case GNUTLS_PK_EC: /* ECDSA */ { ecc_key pub; struct dsa_signature sig; int stat; int curve_id = pk_params->flags; if (is_supported_curve(curve_id) == 0) return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } _ecc_params_to_pubkey(pk_params, &pub); memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) hash_len = vdata->size; ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub, curve_id); if (ret != 0 || stat != 1) { gnutls_assert(); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; } else ret = 0; _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); _ecc_params_clear( &pub); break; } case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_signature sig; ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } memset(&pub, 0, sizeof(pub)); _dsa_params_to_pubkey (pk_params, &pub); memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) hash_len = vdata->size; ret = _dsa_verify (&pub, hash_len, vdata->data, &sig); if (ret == 0) { gnutls_assert(); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; } else ret = 0; _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); break; } case GNUTLS_PK_RSA: { struct rsa_public_key pub; _rsa_params_to_pubkey (pk_params, &pub); ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = rsa_pkcs1_verify (&pub, vdata->size, vdata->data, TOMPZ(tmp[0])); if (ret == 0) ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); else ret = 0; _gnutls_mpi_release (&tmp[0]); break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } cleanup: return ret; }
/* in case of DSA puts into data, r,s */ static int _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo, gnutls_datum_t * signature, const gnutls_datum_t * vdata, const gnutls_pk_params_st * pk_params) { int ret; unsigned int hash; unsigned int hash_len; switch (algo) { case GNUTLS_PK_EC: /* we do ECDSA */ { ecc_key priv; struct dsa_signature sig; int curve_id = pk_params->flags; if (is_supported_curve(curve_id) == 0) return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); _ecc_params_to_privkey(pk_params, &priv); dsa_signature_init (&sig); hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) { gnutls_assert (); _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len); hash_len = vdata->size; } ret = ecc_sign_hash(vdata->data, hash_len, &sig, NULL, rnd_func, &priv, curve_id); if (ret != 0) { gnutls_assert (); ret = GNUTLS_E_PK_SIGN_FAILED; goto ecdsa_fail; } ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s); ecdsa_fail: dsa_signature_clear (&sig); _ecc_params_clear( &priv); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_private_key priv; struct dsa_signature sig; memset(&priv, 0, sizeof(priv)); memset(&pub, 0, sizeof(pub)); _dsa_params_to_pubkey (pk_params, &pub); _dsa_params_to_privkey (pk_params, &priv); dsa_signature_init (&sig); hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) { gnutls_assert (); _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len); hash_len = vdata->size; } ret = _dsa_sign (&pub, &priv, NULL, rnd_func, hash_len, vdata->data, &sig); if (ret == 0) { gnutls_assert (); ret = GNUTLS_E_PK_SIGN_FAILED; goto dsa_fail; } ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s); dsa_fail: dsa_signature_clear (&sig); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } case GNUTLS_PK_RSA: { struct rsa_private_key priv; struct rsa_public_key pub; mpz_t s; _rsa_params_to_privkey (pk_params, &priv); _rsa_params_to_pubkey (pk_params, &pub); mpz_init(s); ret = rsa_pkcs1_sign_tr(&pub, &priv, NULL, rnd_func, vdata->size, vdata->data, s); if (ret == 0) { gnutls_assert(); ret = GNUTLS_E_PK_SIGN_FAILED; goto rsa_fail; } ret = _gnutls_mpi_dprint (s, signature); rsa_fail: mpz_clear(s); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: return ret; }
static int _wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * plaintext, const gnutls_datum_t * ciphertext, const gnutls_pk_params_st * pk_params) { int ret; plaintext->data = NULL; /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_RSA: { struct rsa_private_key priv; struct rsa_public_key pub; unsigned length; bigint_t c; _rsa_params_to_privkey (pk_params, &priv); _rsa_params_to_pubkey (pk_params, &pub); if (_gnutls_mpi_scan_nz (&c, ciphertext->data, ciphertext->size) != 0) { ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); goto cleanup; } length = pub.size; plaintext->data = gnutls_malloc(length); if (plaintext->data == NULL) { ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto cleanup; } ret = rsa_decrypt_tr(&pub, &priv, NULL, rnd_func, &length, plaintext->data, TOMPZ(c)); _gnutls_mpi_release (&c); plaintext->size = length; if (ret == 0) { ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); goto cleanup; } break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: if (ret < 0) gnutls_free(plaintext->data); return ret; }
/* Given a signature and parameters, it should return * the hash algorithm used in the signature. This is a kludge * but until we deprecate gnutls_pubkey_get_verify_algorithm() * we depend on it. */ static int wrap_nettle_hash_algorithm (gnutls_pk_algorithm_t pk, const gnutls_datum_t * sig, gnutls_pk_params_st * issuer_params, gnutls_digest_algorithm_t* hash_algo) { uint8_t digest[MAX_HASH_SIZE]; uint8_t digest_info[MAX_HASH_SIZE*3]; gnutls_datum_t di; unsigned digest_size; mpz_t s; struct rsa_public_key pub; int ret; mpz_init(s); switch (pk) { case GNUTLS_PK_DSA: case GNUTLS_PK_EC: if (hash_algo) *hash_algo = _gnutls_dsa_q_to_hash (pk, issuer_params, NULL); ret = 0; break; case GNUTLS_PK_RSA: if (sig == NULL) { /* return a sensible algorithm */ if (hash_algo) *hash_algo = GNUTLS_DIG_SHA256; return 0; } _rsa_params_to_pubkey (issuer_params, &pub); digest_size = sizeof(digest); nettle_mpz_set_str_256_u(s, sig->size, sig->data); digest_size = sizeof (digest_info); ret = extract_digest_info( &pub, &digest_size, digest_info, s); if (ret == 0) { ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; gnutls_assert (); goto cleanup; } di.data = digest_info; di.size = digest_size; digest_size = sizeof(digest); if ((ret = decode_ber_digest_info (&di, hash_algo, digest, &digest_size)) < 0) { gnutls_assert (); goto cleanup; } if (digest_size != _gnutls_hash_get_algo_len (*hash_algo)) { gnutls_assert (); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; goto cleanup; } ret = 0; break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; } cleanup: mpz_clear(s); return ret; }