[rt-commit] r228 - in /redwax-tool/trunk: ChangeLog configure.ac redwax-tool.c redwax-tool.h redwax_openssl.c

rt-commit at redwax.eu rt-commit at redwax.eu
Wed Jul 22 13:58:00 CEST 2026


Author: minfrin at redwax.eu
Date: Wed Jul 22 13:57:58 2026
New Revision: 228

Log:
Add --filter-signature to limit certificates by
key type.

Modified:
    redwax-tool/trunk/ChangeLog
    redwax-tool/trunk/configure.ac
    redwax-tool/trunk/redwax-tool.c
    redwax-tool/trunk/redwax-tool.h
    redwax-tool/trunk/redwax_openssl.c

Modified: redwax-tool/trunk/ChangeLog
==============================================================================
--- redwax-tool/trunk/ChangeLog	(original)
+++ redwax-tool/trunk/ChangeLog	Wed Jul 22 13:57:58 2026
@@ -1,7 +1,12 @@
+
+Changes with v1.1.0
+
+ *) Add --filter-signature to limit certificates by
+    key type. [Graham Leggett]
 
 Changes with v1.0.1
 
- *) Add --pems-out to output certificates as seperate
+ *) Add --pems-out to output certificates as separate
     files. [Graham Leggett]
 
  *) Implement the generation of the secret file when

Modified: redwax-tool/trunk/configure.ac
==============================================================================
--- redwax-tool/trunk/configure.ac	(original)
+++ redwax-tool/trunk/configure.ac	Wed Jul 22 13:57:58 2026
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(redwax-tool, 1.0.1, minfrin at sharp.fm)
+AC_INIT(redwax-tool, 1.1.0, minfrin at sharp.fm)
 AC_CONFIG_AUX_DIR(build-aux)
 AC_CONFIG_MACRO_DIRS([m4])
 AM_INIT_AUTOMAKE([dist-bzip2])

Modified: redwax-tool/trunk/redwax-tool.c
==============================================================================
--- redwax-tool/trunk/redwax-tool.c	(original)
+++ redwax-tool/trunk/redwax-tool.c	Wed Jul 22 13:57:58 2026
@@ -85,6 +85,8 @@
         APR_HOOK_LINK(complete_verify_dane)
         APR_HOOK_LINK(set_purpose)
         APR_HOOK_LINK(complete_purpose)
+        APR_HOOK_LINK(set_signature)
+        APR_HOOK_LINK(complete_signature)
         APR_HOOK_LINK(set_tlsa)
         APR_HOOK_LINK(process_tlsa)
         APR_HOOK_LINK(set_smimea)
@@ -161,6 +163,10 @@
         (redwax_tool_t * r, const char *arg), (r, arg), DECLINED)
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, complete_purpose,
         (redwax_tool_t * r, apr_hash_t *purposes), (r, purposes), OK, DECLINED)
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, apr_status_t, set_signature,
+        (redwax_tool_t * r, const char *arg), (r, arg), DECLINED)
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, complete_signature,
+		        (redwax_tool_t * r, apr_hash_t *signatures), (r, signatures), OK, DECLINED)
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, apr_status_t, set_tlsa,
         (redwax_tool_t * r, const char *arg), (r, arg), DECLINED)
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_tlsa,
@@ -277,61 +283,62 @@
 #define REDWAX_TOOL_FILTER_EXPIRY 270
 #define REDWAX_TOOL_FILTER_DANE 271
 #define REDWAX_TOOL_FILTER_PURPOSE 272
-#define REDWAX_TOOL_FILTER_VERIFY_PARAM 273
-#define REDWAX_TOOL_FILTER_VERIFY_TLSA 274
-#define REDWAX_TOOL_FILTER_VERIFY_SMIMEA 275
-#define REDWAX_TOOL_CERT_OUT 276
-#define REDWAX_TOOL_NO_CERT_OUT 277
-#define REDWAX_TOOL_CHAIN_OUT 278
-#define REDWAX_TOOL_NO_CHAIN_OUT 279
-#define REDWAX_TOOL_ROOT_OUT 280
-#define REDWAX_TOOL_NO_ROOT_OUT 281
-#define REDWAX_TOOL_TRUST_OUT 282
-#define REDWAX_TOOL_NO_TRUST_OUT 283
-#define REDWAX_TOOL_CRL_OUT 284
-#define REDWAX_TOOL_NO_CRL_OUT 285
-#define REDWAX_TOOL_PARAM_OUT 286
-#define REDWAX_TOOL_NO_PARAM_OUT 287
-#define REDWAX_TOOL_KEY_IN 288
-#define REDWAX_TOOL_NO_KEY_IN 289
-#define REDWAX_TOOL_KEY_OUT 290
-#define REDWAX_TOOL_NO_KEY_OUT 291
-#define REDWAX_TOOL_AUTO_OUT 292
-#define REDWAX_TOOL_NO_AUTO_OUT 293
-#define REDWAX_TOOL_SECRET_SUFFIX_IN 294
-#define REDWAX_TOOL_SECRET_SUFFIX_OUT 295
-#define REDWAX_TOOL_SECRET_TOKEN_IN 296
-#define REDWAX_TOOL_SECRET_TOKEN_OUT 297
-#define REDWAX_TOOL_LABEL_OUT 298
-#define REDWAX_TOOL_NSS_OUT 299
-#define REDWAX_TOOL_NSS_SLOT_OUT 300
-#define REDWAX_TOOL_DER_OUT 301
-#define REDWAX_TOOL_PEMS_OUT 302
-#define REDWAX_TOOL_PEM_OUT 303
-#define REDWAX_TOOL_PKCS12_OUT 304
-#define REDWAX_TOOL_PKCS11_OUT 305
-#define REDWAX_TOOL_PKCS11_MODULE_OUT 306
-#define REDWAX_TOOL_METADATA_OUT 307
-#define REDWAX_TOOL_METADATA_THRESHOLD 308
-#define REDWAX_TOOL_FORMAT_OUT 309
-#define REDWAX_TOOL_CALENDAR_OUT 310
-#define REDWAX_TOOL_CALENDAR_ALARM 311
-#define REDWAX_TOOL_REMINDER_OUT 312
-#define REDWAX_TOOL_JWKS_OUT 313
-#define REDWAX_TOOL_TEXT_OUT 314
-#define REDWAX_TOOL_NO_TEXT_OUT 315
-#define REDWAX_TOOL_SSH_PRIVATE_OUT 316
-#define REDWAX_TOOL_SSH_PUBLIC_OUT 317
-#define REDWAX_TOOL_SMIMEA_OUT 318
-#define REDWAX_TOOL_SSHFP_OUT 319
-#define REDWAX_TOOL_TLSA_OUT 320
-#define REDWAX_TOOL_USER_IN 321
-#define REDWAX_TOOL_USER_OUT 322
-#define REDWAX_TOOL_GROUP_IN 323
-#define REDWAX_TOOL_GROUP_OUT 324
-#define REDWAX_TOOL_ORDER_OUT 325
-#define REDWAX_TOOL_DNS_SERVER 326
-#define REDWAX_TOOL_DNS_TRUST_ANCHOR 327
+#define REDWAX_TOOL_FILTER_SIGNATURE 273
+#define REDWAX_TOOL_FILTER_VERIFY_PARAM 274
+#define REDWAX_TOOL_FILTER_VERIFY_TLSA 275
+#define REDWAX_TOOL_FILTER_VERIFY_SMIMEA 276
+#define REDWAX_TOOL_CERT_OUT 277
+#define REDWAX_TOOL_NO_CERT_OUT 278
+#define REDWAX_TOOL_CHAIN_OUT 279
+#define REDWAX_TOOL_NO_CHAIN_OUT 280
+#define REDWAX_TOOL_ROOT_OUT 281
+#define REDWAX_TOOL_NO_ROOT_OUT 282
+#define REDWAX_TOOL_TRUST_OUT 283
+#define REDWAX_TOOL_NO_TRUST_OUT 284
+#define REDWAX_TOOL_CRL_OUT 285
+#define REDWAX_TOOL_NO_CRL_OUT 286
+#define REDWAX_TOOL_PARAM_OUT 287
+#define REDWAX_TOOL_NO_PARAM_OUT 288
+#define REDWAX_TOOL_KEY_IN 289
+#define REDWAX_TOOL_NO_KEY_IN 290
+#define REDWAX_TOOL_KEY_OUT 291
+#define REDWAX_TOOL_NO_KEY_OUT 292
+#define REDWAX_TOOL_AUTO_OUT 293
+#define REDWAX_TOOL_NO_AUTO_OUT 294
+#define REDWAX_TOOL_SECRET_SUFFIX_IN 295
+#define REDWAX_TOOL_SECRET_SUFFIX_OUT 296
+#define REDWAX_TOOL_SECRET_TOKEN_IN 297
+#define REDWAX_TOOL_SECRET_TOKEN_OUT 298
+#define REDWAX_TOOL_LABEL_OUT 299
+#define REDWAX_TOOL_NSS_OUT 300
+#define REDWAX_TOOL_NSS_SLOT_OUT 301
+#define REDWAX_TOOL_DER_OUT 302
+#define REDWAX_TOOL_PEMS_OUT 303
+#define REDWAX_TOOL_PEM_OUT 304
+#define REDWAX_TOOL_PKCS12_OUT 305
+#define REDWAX_TOOL_PKCS11_OUT 306
+#define REDWAX_TOOL_PKCS11_MODULE_OUT 307
+#define REDWAX_TOOL_METADATA_OUT 308
+#define REDWAX_TOOL_METADATA_THRESHOLD 309
+#define REDWAX_TOOL_FORMAT_OUT 310
+#define REDWAX_TOOL_CALENDAR_OUT 311
+#define REDWAX_TOOL_CALENDAR_ALARM 312
+#define REDWAX_TOOL_REMINDER_OUT 313
+#define REDWAX_TOOL_JWKS_OUT 314
+#define REDWAX_TOOL_TEXT_OUT 315
+#define REDWAX_TOOL_NO_TEXT_OUT 316
+#define REDWAX_TOOL_SSH_PRIVATE_OUT 317
+#define REDWAX_TOOL_SSH_PUBLIC_OUT 318
+#define REDWAX_TOOL_SMIMEA_OUT 319
+#define REDWAX_TOOL_SSHFP_OUT 320
+#define REDWAX_TOOL_TLSA_OUT 321
+#define REDWAX_TOOL_USER_IN 322
+#define REDWAX_TOOL_USER_OUT 323
+#define REDWAX_TOOL_GROUP_IN 324
+#define REDWAX_TOOL_GROUP_OUT 325
+#define REDWAX_TOOL_ORDER_OUT 326
+#define REDWAX_TOOL_DNS_SERVER 327
+#define REDWAX_TOOL_DNS_TRUST_ANCHOR 328
 
 #define REDWAX_EXIT_OK 0
 #define REDWAX_EXIT_INIT 1
@@ -490,6 +497,9 @@
     { "filter-purpose", REDWAX_TOOL_FILTER_PURPOSE, 1,
             "  --filter-purpose=purpose\tSet the purpose of the certificate to verify.\n"
             "\t\t\t\tIf unset, it will default to any purpose." },
+    { "filter-signature", REDWAX_TOOL_FILTER_SIGNATURE, 1,
+            "  --filter-signature=algorithm\tSet the signature algorithm of the certificate to verify.\n"
+            "\t\t\t\tIf unset, it will default to any algorithm." },
     { "text-out", REDWAX_TOOL_TEXT_OUT, 0,
         "  --text-out\t\t\tInclude additional text in certificate PEM and\n"
             "\t\t\t\tmetadata output." },
@@ -796,7 +806,7 @@
         (*cp >= '0' && *cp <= '9') ? *cp - '0' : \
         (*cp >= 'A' && *cp <= 'F') ? *cp - 'A' + 10 : \
         (*cp >= 'a' && *cp <= 'f') ? *cp - 'a' + 10 : \
-        (!(error = cp))        /* last line of macro... */
+        ((error = cp) ? 0 : 0) /* last line of macro... */
 
 /*
  * OCTAL_TO_3BITS:
@@ -805,7 +815,7 @@
  */
 #define OCTAL_TO_3BITS(cp,error) \
         (*cp >= '0' && *cp <= '7') ? *cp - '0' : \
-        (!(error = cp))        /* last line of macro... */
+        ((error = cp) ? 0 : 0) /* last line of macro... */
 
 
     if (state_out) {
@@ -1224,10 +1234,10 @@
                 case 'N': /* shift out */ \
                 case 'O': /* shift in */ \
                 case 'P': /* data line escape */ \
-                case 'Q': /* redwax control 1 */ \
-                case 'R': /* redwax control 2 */ \
-                case 'S': /* redwax control 3 */ \
-                case 'T': /* redwax control 4 */ \
+                case 'Q': /* device control 1 */ \
+                case 'R': /* device control 2 */ \
+                case 'S': /* device control 3 */ \
+                case 'T': /* device control 4 */ \
                 case 'U': /* nack */ \
                 case 'V': /* sync idel */ \
                 case 'W': /* end of transmit block */ \
@@ -1292,50 +1302,50 @@
                         case 'P': /* data line escape */ \
                             *cc++ = '\x10'; \
                             break; \
-                        case 'Q': /* redwax control 1 */ \
+                        case 'Q': /* device control 1 */ \
                             *cc++ = '\x11'; \
                             break; \
-                        case 'R': /* redwax control 2 */ \
+                        case 'R': /* device control 2 */ \
                             *cc++ = '\x12'; \
                             break; \
-                        case 'S': /* redwax control 3 */ \
+                        case 'S': /* device control 3 */ \
                             *cc++ = '\x13'; \
                             break; \
-                        case 'T': /* redwax control 4 */ \
-                            *cc++ = '\x24'; \
+                        case 'T': /* device control 4 */ \
+                            *cc++ = '\x14'; \
                             break; \
                         case 'U': /* nack */ \
-                            *cc++ = '\x25'; \
+                            *cc++ = '\x15'; \
                             break; \
                         case 'V': /* sync idel */ \
-                            *cc++ = '\x26'; \
+                            *cc++ = '\x16'; \
                             break; \
                         case 'W': /* end of transmit block */ \
-                            *cc++ = '\x27'; \
+                            *cc++ = '\x17'; \
                             break; \
                         case 'X': /* cancel */ \
-                            *cc++ = '\x28'; \
+                            *cc++ = '\x18'; \
                             break; \
                         case 'Y': /* end of medium */ \
-                            *cc++ = '\x29'; \
+                            *cc++ = '\x19'; \
                             break; \
                         case 'Z': /* substitute */ \
-                            *cc++ = '\x2A'; \
+                            *cc++ = '\x1A'; \
                             break; \
                         case '[': /* escape */ \
-                            *cc++ = '\x2B'; \
+                            *cc++ = '\x1B'; \
                             break; \
                         case '\\': /* file separator */ \
-                            *cc++ = '\x2C'; \
+                            *cc++ = '\x1C'; \
                             break; \
                         case ']': /* group separator */ \
-                            *cc++ = '\x2D'; \
+                            *cc++ = '\x1D'; \
                             break; \
                         case '^': /* record separator */ \
-                            *cc++ = '\x2E'; \
+                            *cc++ = '\x1E'; \
                             break; \
                         case '_': /* unit separator */ \
-                            *cc++ = '\x2F'; \
+                            *cc++ = '\x1F'; \
                             break; \
                         } \
                         if (offset) *offset++ = (cp - arg_str); \
@@ -2909,6 +2919,13 @@
             }
             break;
         }
+        case REDWAX_TOOL_FILTER_SIGNATURE: {
+            if (redwax_set_option(r, optarg, &rt_run_set_signature,
+                    "filter-signature")) {
+                return r->rc;
+            }
+            break;
+        }
         case REDWAX_TOOL_FILTER_VERIFY_TLSA: {
             if (redwax_set_option(r, optarg, &rt_run_set_tlsa,
                     "filter-verify-tlsa")) {
@@ -3334,6 +3351,10 @@
                 redwax_complete_hash(r, optarg, &rt_run_complete_purpose, state.isquoted);
                 break;
             }
+            case REDWAX_TOOL_FILTER_SIGNATURE: {
+                redwax_complete_hash(r, optarg, &rt_run_complete_signature, state.isquoted);
+                break;
+            }
             case REDWAX_TOOL_NSS_OUT: {
                 redwax_complete_directory(r, optarg, state.isquoted);
                 break;
@@ -3560,6 +3581,10 @@
         }
         case REDWAX_TOOL_FILTER_PURPOSE: {
             redwax_complete_hash(r, "", &rt_run_complete_purpose, state.isquoted);
+            break;
+        }
+        case REDWAX_TOOL_FILTER_SIGNATURE: {
+            redwax_complete_hash(r, "", &rt_run_complete_signature, state.isquoted);
             break;
         }
         case REDWAX_TOOL_NSS_OUT: {

Modified: redwax-tool/trunk/redwax-tool.h
==============================================================================
--- redwax-tool/trunk/redwax-tool.h	(original)
+++ redwax-tool/trunk/redwax-tool.h	Wed Jul 22 13:57:58 2026
@@ -143,6 +143,7 @@
     const char *verify_param;
     const char *verify_date;
     const char *purpose;
+    const char *signature;
     const char *secret_suffix_in;
     const char *secret_suffix_out;
     const char *secret_token_in;
@@ -884,6 +885,22 @@
         (redwax_tool_t *r, const char *arg))
 
 /**
+ * Hook to complete signatures.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_signature,
+        (redwax_tool_t *r, apr_hash_t *signatures))
+
+/**
+ * Hook to set the signature.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_signature,
+        (redwax_tool_t *r, const char *arg))
+
+/**
  * Hook to set the tlsa.
  *
  * @param r The redwax-tool context.

Modified: redwax-tool/trunk/redwax_openssl.c
==============================================================================
--- redwax-tool/trunk/redwax_openssl.c	(original)
+++ redwax-tool/trunk/redwax_openssl.c	Wed Jul 22 13:57:58 2026
@@ -1853,6 +1853,64 @@
     return APR_SUCCESS;
 }
 
+static apr_status_t redwax_openssl_set_signature(redwax_tool_t *r, const char *arg)
+{
+	int nid = OBJ_txt2nid(arg);
+
+    if (nid == NID_undef) {
+
+        redwax_print_error(r,
+                "--filter-signature: signature '%s' not found\n", arg);
+
+        return APR_ENOENT;
+    }
+
+    r->signature = arg;
+
+    return APR_SUCCESS;
+}
+
+static void complete_signature_name_cb(const char *name, void *data)
+{
+    apr_hash_t *params = data;
+
+    if (OBJ_txt2obj(name, 1)) {
+    	return;
+    }
+
+    EVP_SIGNATURE *sig = EVP_SIGNATURE_fetch(NULL, name, NULL);
+
+    if (sig) {
+        apr_hash_set(params, name, APR_HASH_KEY_STRING, name);
+        EVP_SIGNATURE_free(sig);
+    }
+}
+
+static void complete_signature_cb(EVP_KEYMGMT *km, void *data)
+{
+    const OSSL_PARAM *params = EVP_KEYMGMT_gettable_params(km);
+
+    if (params) {
+        for (; params->key; params++) {
+            if (strcmp(params->key, OSSL_PKEY_PARAM_BITS) == 0 ||
+                strcmp(params->key, OSSL_PKEY_PARAM_MAX_SIZE) == 0) {
+
+                EVP_KEYMGMT_names_do_all(km, complete_signature_name_cb, data);
+
+                break;
+            }
+        }
+    }
+}
+
+static apr_status_t redwax_openssl_complete_signature(redwax_tool_t *r,
+        apr_hash_t *params)
+{
+    EVP_KEYMGMT_do_all_provided(NULL, complete_signature_cb, params);
+
+    return APR_SUCCESS;
+}
+
 static apr_status_t redwax_openssl_complete_filter_search(redwax_tool_t *r,
         apr_hash_t *filters)
 {
@@ -1882,7 +1940,7 @@
 
             if (purpose == -1) {
                 redwax_print_error(r,
-                        "When searchinging, purpose was not recognised: %s\n", r->purpose);
+                        "search-filter: purpose was not recognised: %s\n", r->purpose);
                 return APR_EINVAL;
             }
 
@@ -1893,6 +1951,16 @@
             purpose = X509_PURPOSE_get_id(xptmp);
 
             if (!X509_check_purpose(x, purpose, 0)) {
+                X509_free(x);
+                return 0;
+            }
+        }
+
+        if (r->signature) {
+
+        	EVP_PKEY *pkey = X509_get0_pubkey(x);
+
+            if (pkey && !EVP_PKEY_is_a(pkey, r->signature)) {
                 X509_free(x);
                 return 0;
             }
@@ -2200,6 +2268,24 @@
     if (!config) {
         config = apr_pcalloc(cert->pool, sizeof(openssl_certificate_config_t));
         redwax_set_module_config(cert->per_module, &openssl_module, config);
+    }
+
+    /* signature check */
+    if (r->signature && current_cert) {
+
+    	EVP_PKEY *pkey = X509_get0_pubkey(current_cert);
+
+        int nid;
+
+        X509_get_signature_info(current_cert, NULL, &nid, NULL, NULL);
+
+        if (!EVP_PKEY_is_a(pkey, r->signature)) {
+            redwax_print_error(r,
+                    "verify-filter: %d: %.*s: %s != %s, skipping\n",
+                    X509_STORE_CTX_get_error_depth(ctx), len, buf,
+                    r->signature, OBJ_nid2sn(nid));
+            return 0;
+        }
     }
 
     /* set verification result */
@@ -3620,7 +3706,7 @@
             status = apr_file_puts(buf, sfile);
 
             if (APR_SUCCESS != status) {
-            	apr_file_remove(template, pool);
+                apr_file_remove(template, pool);
                 redwax_print_error(r,
                         "Could not write to '%s': %pm\n", secret, &status);
                 return NULL;
@@ -3629,7 +3715,7 @@
             status = apr_file_close(sfile);
 
             if (APR_SUCCESS != status) {
-            	apr_file_remove(template, pool);
+                apr_file_remove(template, pool);
                 redwax_print_error(r,
                         "Could not close '%s': %pm\n", secret, &status);
                 return NULL;
@@ -3638,7 +3724,7 @@
             status = apr_file_rename(template, secret, pool);
 
             if (APR_SUCCESS != status) {
-            	apr_file_remove(template, pool);
+                apr_file_remove(template, pool);
                 redwax_print_error(r,
                         "Could not rename '%s': %pm\n", secret, &status);
                 return NULL;
@@ -7258,6 +7344,8 @@
     rt_hook_set_verify_dane(redwax_openssl_set_verify_dane, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_complete_purpose(redwax_openssl_complete_purpose, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_set_purpose(redwax_openssl_set_purpose, NULL, NULL, APR_HOOK_MIDDLE);
+    rt_hook_complete_signature(redwax_openssl_complete_signature, NULL, NULL, APR_HOOK_MIDDLE);
+    rt_hook_set_signature(redwax_openssl_set_signature, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_process_pem_in(redwax_openssl_process_pem_in, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_process_trust_pem_in(redwax_openssl_process_trust_pem_in, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_process_pkcs12_in(redwax_openssl_process_pkcs12_in, NULL, NULL, APR_HOOK_MIDDLE);



More information about the rt-commit mailing list