Adapt check_key_usage to new weird bits
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 9f4160f..6227460 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -335,19 +335,25 @@
  * \brief          Check usage of certificate against keyUsage extension.
  *
  * \param crt      Leaf certificate used.
- * \param usage    Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT before using the
- *                 certificate to perform an RSA key exchange).
+ * \param usage    Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT
+ *                 before using the certificate to perform an RSA key
+ *                 exchange).
+ *
+ * \note           Except for decipherOnly and encipherOnly, a bit set in the
+ *                 usage argument means this bit MUST be set in the
+ *                 certificate. For decipherOnly and encipherOnly, it means
+ *                 that bit MAY be set.
  *
  * \return         0 is these uses of the certificate are allowed,
  *                 MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension
- *                 is present but does not contain all the bits set in the
- *                 usage argument.
+ *                 is present but does not match the usage argument.
  *
  * \note           You should only call this function on leaf certificates, on
  *                 (intermediate) CAs the keyUsage extension is automatically
  *                 checked by \c mbedtls_x509_crt_verify().
  */
-int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, unsigned int usage );
+int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
+                                      unsigned int usage );
 #endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */
 
 #if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 2285e1d..051b61a 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1519,10 +1519,24 @@
 }
 
 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, unsigned int usage )
+int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
+                                      unsigned int usage )
 {
-    if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) != 0 &&
-        ( crt->key_usage & usage ) != usage )
+    unsigned int usage_must, usage_may;
+    unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
+                          | MBEDTLS_X509_KU_DECIPHER_ONLY;
+
+    if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
+        return( 0 );
+
+    usage_must = usage & ~may_mask;
+
+    if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
+        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+
+    usage_may = usage & may_mask;
+
+    if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
 
     return( 0 );
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 0be6c71..6ab4b21 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1128,6 +1128,15 @@
 X509 crt keyUsage #8 (extension present, combined KU one absent)
 x509_check_key_usage:"data_files/server1.key_usage.crt":MBEDTLS_X509_KU_KEY_ENCIPHERMENT|MBEDTLS_X509_KU_KEY_AGREEMENT:MBEDTLS_ERR_X509_BAD_INPUT_DATA
 
+X509 crt keyUsage #9 (extension present, decOnly allowed absent)
+x509_check_key_usage:"data_files/server1.key_usage.crt":MBEDTLS_X509_KU_DIGITAL_SIGNATURE|MBEDTLS_X509_KU_KEY_ENCIPHERMENT|MBEDTLS_X509_KU_DECIPHER_ONLY:0
+
+X509 crt keyUsage #10 (extension present, decOnly non-allowed present)
+x509_check_key_usage:"data_files/keyUsage.decipherOnly.crt":MBEDTLS_X509_KU_DIGITAL_SIGNATURE|MBEDTLS_X509_KU_KEY_ENCIPHERMENT:MBEDTLS_ERR_X509_BAD_INPUT_DATA
+
+X509 crt keyUsage #11 (extension present, decOnly allowed present)
+x509_check_key_usage:"data_files/keyUsage.decipherOnly.crt":MBEDTLS_X509_KU_DIGITAL_SIGNATURE|MBEDTLS_X509_KU_KEY_ENCIPHERMENT|MBEDTLS_X509_KU_DECIPHER_ONLY:0
+
 X509 crt extendedKeyUsage #1 (no extension, serverAuth)
 depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 x509_check_extended_key_usage:"data_files/server5.crt":"2B06010505070301":0