[rs-commit] r108 - in /redwax-tool/trunk: config.h.in configure.ac redwax_openssl.c

rs-commit at redwax.eu rs-commit at redwax.eu
Thu Dec 2 16:47:43 CET 2021


Author: minfrin at redwax.eu
Date: Thu Dec  2 16:47:43 2021
New Revision: 108

Log:
Add support for certificate transparency.

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

Modified: redwax-tool/trunk/config.h.in
==============================================================================
--- redwax-tool/trunk/config.h.in	(original)
+++ redwax-tool/trunk/config.h.in	Thu Dec  2 16:47:43 2021
@@ -5,6 +5,9 @@
 
 /* Define to 1 if you have the `ASN1_TIME_diff' function. */
 #undef HAVE_ASN1_TIME_DIFF
+
+/* Define to 1 if you have the `ASN1_TIME_print_ex' function. */
+#undef HAVE_ASN1_TIME_PRINT_EX
 
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
@@ -30,6 +33,9 @@
 
 /* Define to 1 if you have the <openssl/core_names.h> header file. */
 #undef HAVE_OPENSSL_CORE_NAMES_H
+
+/* Define to 1 if you have the <openssl/ct.h> header file. */
+#undef HAVE_OPENSSL_CT_H
 
 /* Define to 1 if you have the `OPENSSL_init_crypto' function. */
 #undef HAVE_OPENSSL_INIT_CRYPTO

Modified: redwax-tool/trunk/configure.ac
==============================================================================
--- redwax-tool/trunk/configure.ac	(original)
+++ redwax-tool/trunk/configure.ac	Thu Dec  2 16:47:43 2021
@@ -92,11 +92,11 @@
 AC_TYPE_UINT32_T
 
 # Checks for headers
-AC_CHECK_HEADERS([unistd.h libgen.h openssl/core_names.h])
+AC_CHECK_HEADERS([unistd.h libgen.h openssl/core_names.h openssl/ct.h])
 
 # Checks for library functions.
 AC_FUNC_MALLOC
-AC_CHECK_FUNCS([OPENSSL_init_crypto PKCS12_SAFEBAG_get0_safes PKCS12_SAFEBAG_get_bag_nid PKCS12_SAFEBAG_get_nid PKCS12_SAFEBAG_get0_attr PKCS12_SAFEBAG_get0_p8inf PKCS12_SAFEBAG_get1_cert PKCS12_SAFEBAG_get1_crl OPENSSL_uni2utf8 ASN1_TIME_diff X509_STORE_get0_param X509_STORE_CTX_set0_trusted_stack X509_STORE_CTX_get_num_untrusted X509_get0_notBefore X509_get0_notAfter X509_get0_tbs_sigalg X509_get0_uids X509_get0_extensions X509_get0_signature X509_get_extension_flags X509_up_ref EVP_PKEY_get0_description EVP_PKEY_get_bn_param RSA_get0_n RSA_get0_e RSA_get0_d RSA_get0_p RSA_get0_q RSA_get0_dmp1 RSA_get0_dmq1 RSA_get0_iqmp RSA_set0_key RSA_set0_factors RSA_set0_crt_params NSS_Initialize p11_kit_modules_load_and_initialize apr_crypto_clear])
+AC_CHECK_FUNCS([OPENSSL_init_crypto PKCS12_SAFEBAG_get0_safes PKCS12_SAFEBAG_get_bag_nid PKCS12_SAFEBAG_get_nid PKCS12_SAFEBAG_get0_attr PKCS12_SAFEBAG_get0_p8inf PKCS12_SAFEBAG_get1_cert PKCS12_SAFEBAG_get1_crl OPENSSL_uni2utf8 ASN1_TIME_diff ASN1_TIME_print_ex X509_STORE_get0_param X509_STORE_CTX_set0_trusted_stack X509_STORE_CTX_get_num_untrusted X509_get0_notBefore X509_get0_notAfter X509_get0_tbs_sigalg X509_get0_uids X509_get0_extensions X509_get0_signature X509_get_extension_flags X509_up_ref EVP_PKEY_get0_description EVP_PKEY_get_bn_param RSA_get0_n RSA_get0_e RSA_get0_d RSA_get0_p RSA_get0_q RSA_get0_dmp1 RSA_get0_dmq1 RSA_get0_iqmp RSA_set0_key RSA_set0_factors RSA_set0_crt_params NSS_Initialize p11_kit_modules_load_and_initialize apr_crypto_clear])
 
 AC_OUTPUT
 

Modified: redwax-tool/trunk/redwax_openssl.c
==============================================================================
--- redwax-tool/trunk/redwax_openssl.c	(original)
+++ redwax-tool/trunk/redwax_openssl.c	Thu Dec  2 16:47:43 2021
@@ -44,6 +44,9 @@
 #if HAVE_OPENSSL_CORE_NAMES_H
 #include <openssl/core_names.h>
 #endif
+#if HAVE_OPENSSL_CT_H
+#include <openssl/ct.h>
+#endif
 
 #define REDWAX_OPENSSL_SEARCH "search"
 #define REDWAX_OPENSSL_VERIFY "verify"
@@ -117,7 +120,7 @@
 #define PKCS12_SAFEBAG_get1_crl PKCS12_certbag2x509crl
 #endif
 
-#if !HAVE_ASN1_TIME_DIFF
+#if !HAVE_ASN1_TIME_DIFF || !HAVE_ASN1_TIME_PRINT_EX
 
 #define SECS_PER_DAY (24 * 60 * 60)
 
@@ -507,6 +510,10 @@
     return 0;
 }
 
+#endif
+
+#if !HAVE_ASN1_TIME_DIFF
+
 int redwax_ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
 {
     if (s == NULL) {
@@ -565,6 +572,94 @@
 }
 #endif
 
+#if !HAVE_ASN1_TIME_PRINT_EX
+
+/* Lower 8 bits are reserved as an output type specifier */
+# define ASN1_DTFLGS_TYPE_MASK    0x0FUL
+# define ASN1_DTFLGS_RFC822       0x00UL
+# define ASN1_DTFLGS_ISO8601      0x01UL
+
+static const char _asn1_mon[12][4] = {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static int ossl_ascii_isdigit(const char inchar) {
+    if (inchar > 0x2F && inchar < 0x3A)
+        return 1;
+    return 0;
+}
+
+/* prints the time with the date format of ISO 8601 */
+/* returns 0 on BIO write error, else -1 in case of parse failure, else 1 */
+int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
+{
+    char *v;
+    int gmt = 0, l;
+    struct tm stm;
+    const char upper_z = 0x5A, period = 0x2E;
+
+    /* asn1_time_to_tm will check the time type */
+    if (!asn1_time_to_tm(&stm, tm))
+        return BIO_write(bp, "Bad time value", 14) ? -1 : 0;
+
+    l = tm->length;
+    v = (char *)tm->data;
+    if (v[l - 1] == upper_z)
+        gmt = 1;
+
+    if (tm->type == V_ASN1_GENERALIZEDTIME) {
+        char *f = NULL;
+        int f_len = 0;
+
+        /*
+         * Try to parse fractional seconds. '14' is the place of
+         * 'fraction point' in a GeneralizedTime string.
+         */
+        if (tm->length > 15 && v[14] == period) {
+            f = &v[14];
+            f_len = 1;
+            while (14 + f_len < l && ossl_ascii_isdigit(f[f_len]))
+                ++f_len;
+        }
+
+        if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+            return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%.*s%s",
+                          stm.tm_year + 1900, stm.tm_mon + 1,
+                          stm.tm_mday, stm.tm_hour,
+                          stm.tm_min, stm.tm_sec, f_len, f,
+                          (gmt ? "Z" : "")) > 0;
+        }
+        else {
+            return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
+                          _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
+                          stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900,
+                          (gmt ? " GMT" : "")) > 0;
+        }
+    } else {
+        if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+            return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%s",
+                          stm.tm_year + 1900, stm.tm_mon + 1,
+                          stm.tm_mday, stm.tm_hour,
+                          stm.tm_min, stm.tm_sec,
+                          (gmt ? "Z" : "")) > 0;
+        }
+        else {
+            return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
+                          _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
+                          stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
+                          (gmt ? " GMT" : "")) > 0;
+        }
+    }
+}
+
+/* returns 1 on success, 0 on BIO write error or parse failure */
+int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
+{
+    return ossl_asn1_time_print_ex(bp, tm, flags) > 0;
+}
+#endif
+
 #if !HAVE_X509_STORE_CTX_GET_NUM_UNTRUSTED
 int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx)
 {
@@ -729,10 +824,36 @@
         return NULL;
     }
 
-    if (name != NULL) {
+    if (name) {
         X509_NAME_print_ex(bio,
                         name,
                         0, XN_FLAG_RFC2253);
+        len = BIO_get_mem_data(bio, &buf);
+    }
+
+    buf = apr_pstrndup(p, buf, len);
+
+    BIO_free(bio);
+
+    return buf;
+}
+
+static const char* redwax_openssl_time(apr_pool_t *p,
+        const ASN1_GENERALIZEDTIME *tm)
+{
+    BIO *bio;
+    char *buf = NULL;
+    int len = 0;
+
+    if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+        return NULL;
+    }
+
+    if (tm) {
+
+        ASN1_TIME_print_ex(bio, tm,
+                ASN1_DTFLGS_ISO8601);
+
         len = BIO_get_mem_data(bio, &buf);
     }
 
@@ -3377,6 +3498,98 @@
 
         break;
     }
+#if HAVE_OPENSSL_CT_H
+    case NID_ct_precert_scts:
+    case NID_ct_cert_scts: {
+
+        STACK_OF(SCT) *sct_list = X509V3_EXT_d2i(ex);
+
+        int i;
+
+        if (sk_SCT_num(sct_list)) {
+
+            redwax_metadata_push_array(m, "SignedCertificateTimestamps", 0);
+
+            for (i = 0; i < sk_SCT_num(sct_list); ++i) {
+
+                SCT *sct;
+                ASN1_GENERALIZEDTIME *gen;
+                char genstr[20];
+                unsigned char *ext, *sig;
+                apr_size_t ext_len, sig_len;
+                uint64_t timestamp;
+                int nid;
+
+                sct = sk_SCT_value(sct_list, i);
+
+                redwax_metadata_push_object(m, "SignedCertificateTimestamp", 0);
+
+                if (SCT_get_version(sct) == SCT_VERSION_V1) {
+                    redwax_metadata_add_string(m, "Version", "v1 (0x0)");
+                }
+
+                timestamp = SCT_get_timestamp(sct);
+
+                gen = ASN1_GENERALIZEDTIME_new();
+                if (!gen) {
+                    return APR_ENOMEM;
+                }
+
+                ASN1_GENERALIZEDTIME_adj(gen, (time_t)0,
+                                         (int)(timestamp / 86400000),
+                                         (timestamp % 86400000) / 1000);
+
+                BIO_snprintf(genstr, sizeof(genstr), "%.14s.%03dZ",
+                             ASN1_STRING_get0_data(gen), (unsigned int)(timestamp % 1000));
+                if (ASN1_GENERALIZEDTIME_set_string(gen, genstr)) {
+
+                    redwax_metadata_add_string(m, "Timestamp", redwax_openssl_time(m->pool, gen));
+                }
+
+                ASN1_GENERALIZEDTIME_free(gen);
+
+                ext_len = SCT_get0_extensions(sct, &ext);
+                if (ext_len) {
+                    redwax_metadata_add_string(m, "Extensions",
+                            redwax_pencode_base16_binary(m->pool,
+                                    ext, ext_len,
+                                    REDWAX_ENCODE_LOWER | REDWAX_ENCODE_COLON, NULL));
+
+                }
+
+                nid = SCT_get_signature_nid(sct);
+                if (nid != NID_undef) {
+
+                    redwax_metadata_push_object(m, "Signature", 0);
+                    redwax_metadata_add_string(m, "SignatureAlgorithm", OBJ_nid2sn(nid));
+
+                    sig_len = SCT_get0_signature(sct, &sig);
+                    if (sig_len) {
+                        redwax_metadata_add_string(m, "SignatureValue",
+                                redwax_pencode_base16_binary(m->pool,
+                                        sig, sig_len,
+                                        REDWAX_ENCODE_LOWER | REDWAX_ENCODE_COLON, NULL));
+
+                    }
+
+                    redwax_metadata_pop_object(m);
+                }
+
+                redwax_metadata_pop_object(m);
+            }
+
+            redwax_metadata_pop_array(m);
+        }
+
+        break;
+    }
+    case NID_ct_precert_poison: {
+
+        /* no metadata needed */
+
+        break;
+    }
+#endif
     default:
 
         /*
@@ -3540,45 +3753,13 @@
             tm = X509_get0_notBefore(x);
             if (tm) {
 
-                BIO *bio;
-                char *buf = NULL;
-                int len = 0;
-
-                if ((bio = BIO_new(BIO_s_mem())) == NULL) {
-                    return APR_ENOMEM;
-                }
-
-                ASN1_TIME_print(bio, tm);
-
-                len = BIO_get_mem_data(bio, &buf);
-
-                redwax_metadata_add_string(m, "NotBefore",
-                        apr_psprintf(m->pool, "%.*s", len, buf));
-
-                BIO_free(bio);
-
+                redwax_metadata_add_string(m, "NotBefore", redwax_openssl_time(m->pool, tm));
             }
 
             tm = X509_get0_notAfter(x);
             if (tm) {
 
-                BIO *bio;
-                char *buf = NULL;
-                int len = 0;
-
-                if ((bio = BIO_new(BIO_s_mem())) == NULL) {
-                    return APR_ENOMEM;
-                }
-
-                ASN1_TIME_print(bio, tm);
-
-                len = BIO_get_mem_data(bio, &buf);
-
-                redwax_metadata_add_string(m, "NotAfter",
-                        apr_psprintf(m->pool, "%.*s", len, buf));
-
-                BIO_free(bio);
-
+                redwax_metadata_add_string(m, "NotAfter", redwax_openssl_time(m->pool, tm));
             }
 
             redwax_metadata_pop_object(m);



More information about the rs-commit mailing list