diff options
Diffstat (limited to 'lib/algorithms')
-rw-r--r-- | lib/algorithms/ecc.c | 47 | ||||
-rw-r--r-- | lib/algorithms/groups.c | 18 | ||||
-rw-r--r-- | lib/algorithms/mac.c | 67 | ||||
-rw-r--r-- | lib/algorithms/protocols.c | 69 | ||||
-rw-r--r-- | lib/algorithms/sign.c | 120 |
5 files changed, 313 insertions, 8 deletions
diff --git a/lib/algorithms/ecc.c b/lib/algorithms/ecc.c index f5fb8ac76f..d2c0b3585b 100644 --- a/lib/algorithms/ecc.c +++ b/lib/algorithms/ecc.c @@ -353,13 +353,58 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get_id(const char *name) return ret; } +/* This is only called by cfg_apply in priority.c, in blocklisting mode. */ int _gnutls_ecc_curve_mark_disabled(gnutls_ecc_curve_t curve) { gnutls_ecc_curve_entry_st *p; for(p = ecc_curves; p->name != NULL; p++) { if (p->id == curve) { - p->supported = 0; + p->supported = false; + return 0; + } + } + + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); +} + +/* This is only called by cfg_apply in priority.c, in allowlisting mode. */ +void _gnutls_ecc_curve_mark_disabled_all(void) +{ + gnutls_ecc_curve_entry_st *p; + + for(p = ecc_curves; p->name != NULL; p++) { + p->supported = false; + p->supported_revertible = true; + } +} + +/** + * gnutls_ecc_curve_set_enabled: + * @curve: is an ECC curve + * @enabled: whether to enable the curve + * + * Modify the previous system wide setting that marked @curve as + * enabled or disabled. This only has effect when the curve is + * enabled through the allowlisting mode in the configuration file, or + * when the setting is modified with a prior call to this function. + * + * Returns: 0 on success or negative error code otherwise. + * + * Since: 3.7.3 + */ +int +gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, + unsigned int enabled) +{ + gnutls_ecc_curve_entry_st *p; + + for(p = ecc_curves; p->name != NULL; p++) { + if (p->id == curve) { + if (!p->supported_revertible) { + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + p->supported = enabled; return 0; } } diff --git a/lib/algorithms/groups.c b/lib/algorithms/groups.c index d4b77beb2a..d8bf95824f 100644 --- a/lib/algorithms/groups.c +++ b/lib/algorithms/groups.c @@ -276,6 +276,24 @@ gnutls_group_t gnutls_group_get_id(const char *name) return ret; } + +/* Similar to gnutls_group_get_id, except that it does not check if + * the curve is supported. + */ +gnutls_group_t _gnutls_group_get_id(const char *name) +{ + gnutls_group_t ret = GNUTLS_GROUP_INVALID; + + GNUTLS_GROUP_LOOP( + if (c_strcasecmp(p->name, name) == 0) { + ret = p->id; + break; + } + ); + + return ret; +} + /** * gnutls_group_get_name: * @group: is an element from %gnutls_group_t diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c index 57dfca95de..a2c66e76bb 100644 --- a/lib/algorithms/mac.c +++ b/lib/algorithms/mac.c @@ -291,6 +291,7 @@ gnutls_digest_algorithm_t gnutls_digest_get_id(const char *name) return ret; } +/* This is only called by cfg_apply in priority.c, in blocklisting mode. */ int _gnutls_digest_mark_insecure(gnutls_digest_algorithm_t dig) { #ifndef DISABLE_SYSTEM_CONFIG @@ -307,6 +308,57 @@ int _gnutls_digest_mark_insecure(gnutls_digest_algorithm_t dig) return GNUTLS_E_INVALID_REQUEST; } +/* This is only called by cfg_apply in priority.c, in allowlisting mode. */ +void _gnutls_digest_mark_insecure_all(void) +{ +#ifndef DISABLE_SYSTEM_CONFIG + mac_entry_st *p; + + for(p = hash_algorithms; p->name != NULL; p++) { + p->flags |= GNUTLS_MAC_FLAG_PREIMAGE_INSECURE_REVERTIBLE | + GNUTLS_MAC_FLAG_PREIMAGE_INSECURE; + } + +#endif +} + +/** + * gnutls_digest_set_secure: + * @dig: is a digest algorithm + * @secure: whether to mark the digest algorithm secure + * + * Modify the previous system wide setting that marked @dig as secure + * or insecure. This only has effect when the algorithm is enabled + * through the allowlisting mode in the configuration file, or when + * the setting is modified with a prior call to this function. + * + * Since: 3.7.3 + */ +int +gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, + unsigned int secure) +{ +#ifndef DISABLE_SYSTEM_CONFIG + mac_entry_st *p; + + for(p = hash_algorithms; p->name != NULL; p++) { + if (p->oid != NULL && p->id == (gnutls_mac_algorithm_t)dig) { + if (!(p->flags & GNUTLS_MAC_FLAG_PREIMAGE_INSECURE_REVERTIBLE)) { + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + if (secure) { + p->flags &= ~GNUTLS_MAC_FLAG_PREIMAGE_INSECURE; + } else { + p->flags |= GNUTLS_MAC_FLAG_PREIMAGE_INSECURE; + } + return 0; + } + } + +#endif + return GNUTLS_E_INVALID_REQUEST; +} + unsigned _gnutls_digest_is_insecure(gnutls_digest_algorithm_t dig) { const mac_entry_st *p; @@ -320,6 +372,21 @@ unsigned _gnutls_digest_is_insecure(gnutls_digest_algorithm_t dig) return 1; } +bool _gnutls_digest_is_insecure2(gnutls_digest_algorithm_t dig, unsigned flags) +{ + const mac_entry_st *p; + + for(p = hash_algorithms; p->name != NULL; p++) { + if (p->oid != NULL && p->id == (gnutls_mac_algorithm_t)dig) { + return (p->flags & GNUTLS_MAC_FLAG_PREIMAGE_INSECURE && + !(flags & GNUTLS_MAC_FLAG_ALLOW_INSECURE_REVERTIBLE && + p->flags & GNUTLS_MAC_FLAG_PREIMAGE_INSECURE_REVERTIBLE)); + } + } + + return true; +} + /** * gnutls_mac_get_id: * @name: is a MAC algorithm name diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c index 4283cd0388..b0f3e0bc30 100644 --- a/lib/algorithms/protocols.c +++ b/lib/algorithms/protocols.c @@ -198,6 +198,7 @@ version_is_valid_for_session(gnutls_session_t session, return 0; } +/* This is only called by cfg_apply in priority.c, in blocklisting mode. */ int _gnutls_version_mark_disabled(gnutls_protocol_t version) { #ifndef DISABLE_SYSTEM_CONFIG @@ -205,7 +206,54 @@ int _gnutls_version_mark_disabled(gnutls_protocol_t version) for (p = sup_versions; p->name != NULL; p++) if (p->id == version) { - p->supported = 0; + p->supported = false; + return 0; + } + +#endif + return GNUTLS_E_INVALID_REQUEST; +} + +/* This is only called by cfg_apply in priority.c, in allowlisting mode. */ +void _gnutls_version_mark_revertible_all(void) +{ +#ifndef DISABLE_SYSTEM_CONFIG + version_entry_st *p; + + for (p = sup_versions; p->name != NULL; p++) { + p->supported_revertible = true; + } + +#endif +} + +/** + * gnutls_protocol_set_enabled: + * @version: is a (gnutls) version number + * @enabled: whether to enable the protocol + * + * Mark the previous system wide setting that marked @version as + * enabled or disabled. This only has effect when the version is + * enabled through the allowlisting mode in the configuration file, or + * when the setting is modified with a prior call to this function. + * + * Returns: 0 on success or negative error code otherwise. + * + * Since: 3.7.3 + */ +int +gnutls_protocol_set_enabled(gnutls_protocol_t version, + unsigned int enabled) +{ +#ifndef DISABLE_SYSTEM_CONFIG + version_entry_st *p; + + for (p = sup_versions; p->name != NULL; p++) + if (p->id == version) { + if (!p->supported_revertible) { + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + p->supported = enabled; return 0; } @@ -469,6 +517,25 @@ const gnutls_protocol_t *gnutls_protocol_list(void) return supported_protocols; } +/* Return all versions, including non-supported ones. + */ +const gnutls_protocol_t *_gnutls_protocol_list(void) +{ + const version_entry_st *p; + static gnutls_protocol_t protocols[MAX_ALGOS] = { 0 }; + + if (protocols[0] == 0) { + int i = 0; + + for (p = sup_versions; p->name != NULL; p++) { + protocols[i++] = p->id; + } + protocols[i++] = 0; + } + + return protocols; +} + /* Returns a version number given the major and minor numbers. */ gnutls_protocol_t _gnutls_version_get(uint8_t major, uint8_t minor) 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 |