summaryrefslogtreecommitdiff
path: root/lib/algorithms/sign.c
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2021-05-06 12:41:40 +0200
committerDaiki Ueno <ueno@gnu.org>2021-11-29 13:21:53 +0100
commit0ecce7191dfd78387f2994253d37ed1df50d563d (patch)
treefb1d66e9329cdad3ef617c02b96c77aca1c8dd3e /lib/algorithms/sign.c
parentee3af8d6e863bd958cbe7468f9cbe09d803f4e92 (diff)
downloadgnutls-0ecce7191dfd78387f2994253d37ed1df50d563d.tar.gz
priority: support allowlisting in configuration file
This adds a new mode of interpreting the [overrides] section. If "override-mode" is set to "allowlisting" in the [global] section, all the algorithms (hashes, signature algorithms, curves, and versions) are initially marked as insecure/disabled. Then the user can enable them by specifying allowlisting keywords such as "secure-hash" in the [overrides] section. Signed-off-by: Daiki Ueno <ueno@gnu.org> Co-authored-by: Alexander Sosedkin <asosedkin@redhat.com>
Diffstat (limited to 'lib/algorithms/sign.c')
-rw-r--r--lib/algorithms/sign.c120
1 files changed, 114 insertions, 6 deletions
diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c
index 4c5619454f..543bd19bb5 100644
--- a/lib/algorithms/sign.c
+++ b/lib/algorithms/sign.c
@@ -453,15 +453,22 @@ unsigned gnutls_sign_is_secure(gnutls_sign_algorithm_t algorithm)
bool _gnutls_sign_is_secure2(const gnutls_sign_entry_st *se, unsigned int flags)
{
- if (se->hash != GNUTLS_DIG_UNKNOWN && _gnutls_digest_is_insecure(se->hash))
- return gnutls_assert_val(0);
+ if (se->hash != GNUTLS_DIG_UNKNOWN &&
+ _gnutls_digest_is_insecure2(se->hash,
+ flags & GNUTLS_SIGN_FLAG_ALLOW_INSECURE_REVERTIBLE ?
+ GNUTLS_MAC_FLAG_ALLOW_INSECURE_REVERTIBLE :
+ 0)) {
+ return gnutls_assert_val(false);
+ }
- if (flags & GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS)
- return (se->slevel==_SECURE)?1:0;
- else
- return (se->slevel==_SECURE || se->slevel == _INSECURE_FOR_CERTS)?1:0;
+ return (flags & GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS ?
+ se->slevel == _SECURE :
+ (se->slevel == _SECURE || se->slevel == _INSECURE_FOR_CERTS)) ||
+ (flags & GNUTLS_SIGN_FLAG_ALLOW_INSECURE_REVERTIBLE &&
+ se->flags & GNUTLS_SIGN_FLAG_INSECURE_REVERTIBLE);
}
+/* This is only called by cfg_apply in priority.c, in blocklisting mode. */
int _gnutls_sign_mark_insecure(gnutls_sign_algorithm_t sign, hash_security_level_t level)
{
#ifndef DISABLE_SYSTEM_CONFIG
@@ -472,6 +479,7 @@ int _gnutls_sign_mark_insecure(gnutls_sign_algorithm_t sign, hash_security_level
for(p = sign_algorithms; p->name != NULL; p++) {
if (p->id && p->id == sign) {
+ if (p->slevel < level)
p->slevel = level;
return 0;
}
@@ -480,6 +488,106 @@ int _gnutls_sign_mark_insecure(gnutls_sign_algorithm_t sign, hash_security_level
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
}
+/* This is only called by cfg_apply in priority.c, in allowlisting mode. */
+void _gnutls_sign_mark_insecure_all(hash_security_level_t level)
+{
+#ifndef DISABLE_SYSTEM_CONFIG
+ gnutls_sign_entry_st *p;
+
+ for(p = sign_algorithms; p->name != NULL; p++) {
+ if (p->slevel < level)
+ p->slevel = level;
+ p->flags |= GNUTLS_SIGN_FLAG_INSECURE_REVERTIBLE;
+ }
+#endif
+}
+
+/**
+ * gnutls_sign_set_secure:
+ * @sign: the sign algorithm
+ * @secure: whether to mark the sign algorithm secure
+ *
+ * Modify the previous system wide setting that marked @sign as secure
+ * or insecure. This only has effect when the algorithm is marked as
+ * secure through the allowlisting mode in the configuration file, or
+ * when the setting is modified with a prior call to this function.
+ *
+ * Even when @secure is true, @sign is not marked as secure for the
+ * use in certificates. Use gnutls_sign_set_secure_for_certs() to
+ * mark it secure as well for certificates.
+ *
+ * Since: 3.7.3
+ */
+int
+gnutls_sign_set_secure(gnutls_sign_algorithm_t sign,
+ unsigned int secure)
+{
+#ifndef DISABLE_SYSTEM_CONFIG
+ gnutls_sign_entry_st *p;
+
+ for(p = sign_algorithms; p->name != NULL; p++) {
+ if (p->id && p->id == sign) {
+ if (!(p->flags & GNUTLS_SIGN_FLAG_INSECURE_REVERTIBLE)) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ if (secure) {
+ if (p->slevel > _INSECURE_FOR_CERTS) {
+ p->slevel = _INSECURE_FOR_CERTS;
+ }
+ } else {
+ p->slevel = _INSECURE;
+ }
+ return 0;
+ }
+ }
+#endif
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+}
+
+/**
+ * gnutls_sign_set_secure_for_certs:
+ * @sign: the sign algorithm
+ * @secure: whether to mark the sign algorithm secure for certificates
+ *
+ * Modify the previous system wide setting that marked @sign as secure
+ * or insecure for the use in certificates. This only has effect when
+ * the algorithm is marked as secure through the allowlisting mode in
+ * the configuration file, or when the setting is modified with a
+ * prior call to this function.
+ *
+ * When @secure is true, @sign is marked as secure for any use unlike
+ * gnutls_sign_set_secure(). Otherwise, it is marked as insecure only
+ * for the use in certificates. Use gnutls_sign_set_secure() to mark
+ * it insecure for any uses.
+ *
+ * Since: 3.7.3
+ */
+int
+gnutls_sign_set_secure_for_certs(gnutls_sign_algorithm_t sign,
+ unsigned int secure)
+{
+#ifndef DISABLE_SYSTEM_CONFIG
+ gnutls_sign_entry_st *p;
+
+ for(p = sign_algorithms; p->name != NULL; p++) {
+ if (p->id && p->id == sign) {
+ if (!(p->flags & GNUTLS_SIGN_FLAG_INSECURE_REVERTIBLE)) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ if (secure) {
+ p->slevel = _SECURE;
+ } else {
+ if (p->slevel < _INSECURE_FOR_CERTS) {
+ p->slevel = _INSECURE_FOR_CERTS;
+ }
+ }
+ return 0;
+ }
+ }
+#endif
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+}
+
/**
* gnutls_sign_is_secure2:
* @algorithm: is a sign algorithm