summaryrefslogtreecommitdiff
path: root/lib/cert.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cert.c')
-rw-r--r--lib/cert.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/lib/cert.c b/lib/cert.c
index d93b2f6cba..9e42de1c51 100644
--- a/lib/cert.c
+++ b/lib/cert.c
@@ -245,6 +245,58 @@ gnutls_certificate_allocate_credentials(gnutls_certificate_credentials_t *
return 0;
}
+/* Returns 0 if it's ok to use the gnutls_kx_algorithm_t with this
+ * certificate (uses the KeyUsage field).
+ */
+static int
+check_key_usage(const gnutls_pcert_st * cert,
+ gnutls_kx_algorithm_t alg)
+{
+ unsigned int key_usage = 0;
+ int encipher_type;
+
+ if (cert == NULL || alg == GNUTLS_KX_UNKNOWN) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (_gnutls_map_kx_get_cred(alg, 1) == GNUTLS_CRD_CERTIFICATE ||
+ _gnutls_map_kx_get_cred(alg, 0) == GNUTLS_CRD_CERTIFICATE) {
+
+ gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
+
+ encipher_type = _gnutls_kx_encipher_type(alg);
+
+ if (key_usage != 0 && encipher_type != CIPHER_IGN) {
+ /* If key_usage has been set in the certificate
+ */
+
+ if (encipher_type == CIPHER_ENCRYPT) {
+ /* If the key exchange method requires an encipher
+ * type algorithm, and key's usage does not permit
+ * encipherment, then fail.
+ */
+ if (!(key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT)) {
+ gnutls_assert();
+ return
+ GNUTLS_E_KEY_USAGE_VIOLATION;
+ }
+ }
+
+ if (encipher_type == CIPHER_SIGN) {
+ /* The same as above, but for sign only keys
+ */
+ if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
+ gnutls_assert();
+ return
+ GNUTLS_E_KEY_USAGE_VIOLATION;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
/* returns the KX algorithms that are supported by a
* certificate. (Eg a certificate with RSA params, supports
@@ -275,7 +327,7 @@ _gnutls_selected_cert_supported_kx(gnutls_session_t session,
pk = _gnutls_map_kx_get_pk(kx);
if (pk == cert_pk) {
/* then check key usage */
- if (_gnutls_check_key_usage(cert, kx) == 0 ||
+ if (check_key_usage(cert, kx) == 0 ||
unlikely(session->internals.priorities.allow_server_key_usage_violation != 0)) {
alg[i] = kx;
i++;