/** * gnutls_privkey_decrypt_data: * @key: Holds the key * @flags: zero for now * @ciphertext: holds the data to be decrypted * @plaintext: will contain the decrypted data, allocated with gnutls_malloc() * * This function will decrypt the given data using the algorithm * supported by the private key. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_privkey_decrypt_data (gnutls_privkey_t key, unsigned int flags, const gnutls_datum_t * ciphertext, gnutls_datum_t * plaintext) { if (key->pk_algorithm != GNUTLS_PK_RSA) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } switch (key->type) { #ifdef ENABLE_OPENPGP case GNUTLS_PRIVKEY_OPENPGP: return _gnutls_openpgp_privkey_decrypt_data (key->key.openpgp, flags, ciphertext, plaintext); #endif case GNUTLS_PRIVKEY_X509: return _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext, key->key.x509->params, key->key.x509->params_size, 2); case GNUTLS_PRIVKEY_PKCS11: return _gnutls_pkcs11_privkey_decrypt_data (key->key.pkcs11, flags, ciphertext, plaintext); default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } }
int _gnutls_rsa_verify (const gnutls_datum_t * vdata, const gnutls_datum_t * ciphertext, gnutls_pk_params_st * params, int btype) { gnutls_datum_t plain; int ret; /* decrypt signature */ if ((ret = _gnutls_pkcs1_rsa_decrypt (&plain, ciphertext, params, btype)) < 0) { gnutls_assert (); return ret; } if (plain.size != vdata->size) { gnutls_assert (); _gnutls_free_datum (&plain); return GNUTLS_E_PK_SIG_VERIFY_FAILED; } if (memcmp (plain.data, vdata->data, plain.size) != 0) { gnutls_assert (); _gnutls_free_datum (&plain); return GNUTLS_E_PK_SIG_VERIFY_FAILED; } _gnutls_free_datum (&plain); return 0; /* ok */ }
int proc_rsa_export_client_kx (gnutls_session_t session, opaque * data, size_t _data_size) { gnutls_datum_t plaintext; gnutls_datum_t ciphertext; int ret, dsize; bigint_t *params; int params_len; int randomize_key = 0; ssize_t data_size = _data_size; if (gnutls_protocol_get_version (session) == GNUTLS_SSL3) { /* SSL 3.0 */ ciphertext.data = data; ciphertext.size = data_size; } else { /* TLS 1.0 */ DECR_LEN (data_size, 2); ciphertext.data = &data[2]; dsize = _gnutls_read_uint16 (data); if (dsize != data_size) { gnutls_assert (); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } ciphertext.size = dsize; } ret = _gnutls_get_private_rsa_params (session, ¶ms, ¶ms_len); if (ret < 0) { gnutls_assert (); return ret; } ret = _gnutls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, params_len, 2); /* btype==2 */ if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE) { /* In case decryption fails then don't inform * the peer. Just use a random key. (in order to avoid * attack against pkcs-1 formating). */ gnutls_assert (); _gnutls_audit_log ("auth_rsa: Possible PKCS #1 format attack\n"); randomize_key = 1; } else { /* If the secret was properly formatted, then * check the version number. */ if (_gnutls_get_adv_version_major (session) != plaintext.data[0] || _gnutls_get_adv_version_minor (session) != plaintext.data[1]) { /* No error is returned here, if the version number check * fails. We proceed normally. * That is to defend against the attack described in the paper * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima, * Ondej Pokorny and Tomas Rosa. */ gnutls_assert (); _gnutls_audit_log ("auth_rsa: Possible PKCS #1 version check format attack\n"); } } if (randomize_key != 0) { session->key->key.size = GNUTLS_MASTER_SIZE; session->key->key.data = gnutls_malloc (session->key->key.size); if (session->key->key.data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* we do not need strong random numbers here. */ ret = _gnutls_rnd (GNUTLS_RND_NONCE, session->key->key.data, session->key->key.size); if (ret < 0) { gnutls_assert (); return ret; } } else { session->key->key.data = plaintext.data; session->key->key.size = plaintext.size; } /* This is here to avoid the version check attack * discussed above. */ session->key->key.data[0] = _gnutls_get_adv_version_major (session); session->key->key.data[1] = _gnutls_get_adv_version_minor (session); return 0; }
/* This will return the appropriate hash to verify the given signature. * If signature is NULL it will return an (or the) appropriate hash for * the given parameters. */ int _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash, const gnutls_datum_t * signature, gnutls_pk_algorithm pk, bigint_t * issuer_params, unsigned int issuer_params_size) { opaque digest[MAX_HASH_SIZE]; gnutls_datum_t decrypted; int digest_size; int ret; switch (pk) { case GNUTLS_PK_DSA: if (hash) *hash = _gnutls_dsa_q_to_hash (issuer_params[1], NULL); ret = 0; break; case GNUTLS_PK_RSA: if (signature == NULL) { /* return a sensible algorithm */ if (hash) *hash = GNUTLS_DIG_SHA256; return 0; } ret = _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, issuer_params, issuer_params_size, 1); if (ret < 0) { gnutls_assert (); goto cleanup; } digest_size = sizeof (digest); if ((ret = decode_ber_digest_info (&decrypted, hash, digest, &digest_size)) != 0) { gnutls_assert (); _gnutls_free_datum (&decrypted); goto cleanup; } _gnutls_free_datum (&decrypted); if (digest_size != _gnutls_hash_get_algo_len (*hash)) { gnutls_assert (); ret = GNUTLS_E_ASN1_GENERIC_ERROR; goto cleanup; } ret = 0; break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; } cleanup: return ret; }
/* if hash==MD5 then we do RSA-MD5 * if hash==SHA then we do RSA-SHA * params[0] is modulus * params[1] is public key */ static int _pkcs1_rsa_verify_sig (const gnutls_datum_t * text, const gnutls_datum_t * prehash, const gnutls_datum_t * signature, bigint_t * params, int params_len) { gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN; int ret; opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp; int digest_size; digest_hd_st hd; gnutls_datum_t decrypted; ret = _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, params_len, 1); if (ret < 0) { gnutls_assert (); return ret; } /* decrypted is a BER encoded data of type DigestInfo */ digest_size = sizeof (digest); if ((ret = decode_ber_digest_info (&decrypted, &hash, digest, &digest_size)) != 0) { gnutls_assert (); _gnutls_free_datum (&decrypted); return ret; } _gnutls_free_datum (&decrypted); if (digest_size != _gnutls_hash_get_algo_len (hash)) { gnutls_assert (); return GNUTLS_E_ASN1_GENERIC_ERROR; } if (prehash && prehash->data && prehash->size == digest_size) { cmp = prehash->data; } else { if (!text) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_hash_init (&hd, hash); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&hd, text->data, text->size); _gnutls_hash_deinit (&hd, md); cmp = md; } if (memcmp (cmp, digest, digest_size) != 0) { gnutls_assert (); return GNUTLS_E_PK_SIG_VERIFY_FAILED; } return 0; }
/*- * _gnutls_openpgp_privkey_decrypt_data: * @key: Holds the key * @flags: zero for now * @ciphertext: holds the data to be decrypted * @plaintext: will contain newly allocated plaintext * * This function will sign the given hash using the private key. You * should use gnutls_openpgp_privkey_set_preferred_key_id() before * calling this function to set the subkey to use. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. -*/ int _gnutls_openpgp_privkey_decrypt_data (gnutls_openpgp_privkey_t key, unsigned int flags, const gnutls_datum_t * ciphertext, gnutls_datum_t * plaintext) { int result, i; bigint_t params[MAX_PRIV_PARAMS_SIZE]; int params_size = MAX_PRIV_PARAMS_SIZE; int pk_algorithm; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } result = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid); if (result == 0) { uint32_t kid[2]; KEYID_IMPORT (kid, keyid); result = _gnutls_openpgp_privkey_get_mpis (key, kid, params, ¶ms_size); i = gnutls_openpgp_privkey_get_subkey_idx (key, keyid); pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, i, NULL); } else { pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL); result = _gnutls_openpgp_privkey_get_mpis (key, NULL, params, ¶ms_size); } if (result < 0) { gnutls_assert (); return result; } if (pk_algorithm != GNUTLS_PK_RSA) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } result = _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext, params, params_size, 2); for (i = 0; i < params_size; i++) _gnutls_mpi_release (¶ms[i]); if (result < 0) { gnutls_assert (); return result; } return 0; }
int _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash, const gnutls_datum_t * signature, const gnutls_x509_crt_t issuer) { bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE]; opaque digest[MAX_HASH_SIZE]; gnutls_datum_t decrypted; int issuer_params_size; int digest_size; int ret, i; issuer_params_size = MAX_PUBLIC_PARAMS_SIZE; ret = _gnutls_x509_crt_get_mpis (issuer, issuer_params, &issuer_params_size); if (ret < 0) { gnutls_assert (); return ret; } switch (gnutls_x509_crt_get_pk_algorithm (issuer, NULL)) { case GNUTLS_PK_DSA: if (hash) *hash = _gnutls_dsa_q_to_hash (issuer_params[1]); ret = 0; break; case GNUTLS_PK_RSA: ret = _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, issuer_params, issuer_params_size, 1); if (ret < 0) { gnutls_assert (); goto cleanup; } digest_size = sizeof (digest); if ((ret = decode_ber_digest_info (&decrypted, hash, digest, &digest_size)) != 0) { gnutls_assert (); _gnutls_free_datum (&decrypted); goto cleanup; } _gnutls_free_datum (&decrypted); if (digest_size != _gnutls_hash_get_algo_len (*hash)) { gnutls_assert (); ret = GNUTLS_E_ASN1_GENERIC_ERROR; goto cleanup; } ret = 0; break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; } cleanup: /* release allocated mpis */ for (i = 0; i < issuer_params_size; i++) { _gnutls_mpi_release (&issuer_params[i]); } return ret; }