From a9411d009d62502bc57272a824b18181ff2dd33b Mon Sep 17 00:00:00 2001 From: fm4dd Date: Sat, 13 Jan 2024 17:37:45 +0900 Subject: [PATCH] OpenSSL v3 API update --- html/changelog.shtm | 7 + readme.md | 1 + scripts/update-crl.sh | 4 +- scripts/webCA.cnf | 390 ++++++++++++++++++++++++++++++++++++++++++ src/certexport.c | 14 +- src/certrenew.c | 16 +- src/certrevoke.c | 19 ++ src/certsearch.c | 12 +- src/certsign.c | 12 +- src/certvalidate.c | 9 +- src/genrequest.c | 62 +++++-- src/keycompare.c | 249 +++++++++++++++++++-------- src/p12convert.c | 16 +- src/pagefoot.c | 2 +- src/serial.c | 7 + src/webcert.c | 61 ++++++- src/webcert.h | 4 +- 17 files changed, 769 insertions(+), 116 deletions(-) create mode 100644 scripts/webCA.cnf diff --git a/html/changelog.shtm b/html/changelog.shtm index f0ad492..419e1c5 100755 --- a/html/changelog.shtm +++ b/html/changelog.shtm @@ -18,6 +18,13 @@
+

2024-01-13 new version 1.8.5 released

+
+

Bug fixes:

+
    +
  • Code update to latest OpenSSL version 3 API calls
  • +
+

2021-12-20 new version 1.8.4 released


Bug fixes:

diff --git a/readme.md b/readme.md index 1dae757..da1ec52 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,7 @@ ## WebCert ![test](https://github.com/fm4dd/webcert/workflows/test/badge.svg) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://opensource.org/licenses/MIT) #### A Web Tool for Generation and Management of digital Certificates diff --git a/scripts/update-crl.sh b/scripts/update-crl.sh index bdce68b..664e3a3 100755 --- a/scripts/update-crl.sh +++ b/scripts/update-crl.sh @@ -5,7 +5,7 @@ # and publishes a new CRL file. Runs daily from cron. ########################################################## # set debug: 0=off 1=normal 2=verbose -DEBUG=2 +DEBUG=0 ########################################################## # binaries location @@ -73,7 +73,7 @@ CHECK_UPDATE() { ########################################################## NEW_CRL() { if [ $update_crl == "1" ]; then - $OSSL ca -cert /srv/app/webCA/cacert.pem -gencrl -crldays 90 \ + $OSSL ca -config /srv/app/webCA/webCA.cnf -gencrl -crldays 90 \ -out $crlfile --passin file:/srv/app/webCA/private/passin.src 2>/dev/null [ $DEBUG == "2" ] && echo "update-crl.sh: created new crl file $crlfile" diff --git a/scripts/webCA.cnf b/scripts/webCA.cnf new file mode 100644 index 0000000..8039674 --- /dev/null +++ b/scripts/webCA.cnf @@ -0,0 +1,390 @@ +# +# OpenSSL example configuration file. +# See doc/man5/config.pod for more info. +# +# This is mostly being used for generation of certificate requests, +# but may be used for auto loading of providers + +# Note that you can include other files from the main configuration +# file using the .include directive. +#.include filename + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . + + # Use this in order to automatically load providers. +openssl_conf = openssl_init + +# Comment out the next line to ignore configuration errors +config_diagnostics = 1 + +# Extra OBJECT IDENTIFIER info: +# oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] +# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +# Policies used by the TSA examples. +tsa_policy1 = 1.2.3.4.1 +tsa_policy2 = 1.2.3.4.5.6 +tsa_policy3 = 1.2.3.4.5.7 + +# For FIPS +# Optionally include a file that is generated by the OpenSSL fipsinstall +# application. This file contains configuration data required by the OpenSSL +# fips provider. It contains a named section e.g. [fips_sect] which is +# referenced from the [provider_sect] below. +# Refer to the OpenSSL security policy for more information. +# .include fipsmodule.cnf + +[openssl_init] +# providers = provider_sect + +# List of providers to load +# [provider_sect] +# default = default_sect +# The fips section name should match the section name inside the +# included fipsmodule.cnf. +# fips = fips_sect + +# If no providers are activated explicitly, the default one is activated implicitly. +# See man 7 OSSL_PROVIDER-default for more details. +# +# If you add a section explicitly activating any other provider(s), you most +# probably need to explicitly activate the default provider, otherwise it +# becomes unavailable in openssl. As a consequence applications depending on +# OpenSSL may not work correctly which could lead to significant system +# problems including inability to remotely access the system. +# [default_sect] +# activate = 1 + + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = /srv/app/webCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certs with same subject. +new_certs_dir = $dir/certs # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 90 # how long before next CRL +default_md = default # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 2048 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = AU +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Some-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = FM4DD + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Webcert Support + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +basicConstraints = critical,CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo + +#################################################################### +[ tsa ] + +default_tsa = tsa_config1 # the default TSA section + +[ tsa_config1 ] + +# These are used by the TSA reply generation only. +dir = ./demoCA # TSA root directory +serial = $dir/tsaserial # The current serial number (mandatory) +crypto_device = builtin # OpenSSL engine to use for signing +signer_cert = $dir/tsacert.pem # The TSA signing certificate + # (optional) +certs = $dir/cacert.pem # Certificate chain to include in reply + # (optional) +signer_key = $dir/private/tsakey.pem # The TSA private key (optional) +signer_digest = sha256 # Signing digest to use. (Optional) +default_policy = tsa_policy1 # Policy if request did not specify it + # (optional) +other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) +digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory) +accuracy = secs:1, millisecs:500, microsecs:100 # (optional) +clock_precision_digits = 0 # number of digits after dot. (optional) +ordering = yes # Is ordering defined for timestamps? + # (optional, default: no) +tsa_name = yes # Must the TSA name be included in the reply? + # (optional, default: no) +ess_cert_id_chain = no # Must the ESS cert id chain be included? + # (optional, default: no) +ess_cert_id_alg = sha1 # algorithm to compute certificate + # identifier (optional, default: sha1) + +[insta] # CMP using Insta Demo CA +# Message transfer +server = pki.certificate.fi:8700 +# proxy = # set this as far as needed, e.g., http://192.168.1.1:8080 +# tls_use = 0 +path = pkix/ + +# Server authentication +recipient = "/C=FI/O=Insta Demo/CN=Insta Demo CA" # or set srvcert or issuer +ignore_keyusage = 1 # potentially needed quirk +unprotected_errors = 1 # potentially needed quirk +extracertsout = insta.extracerts.pem + +# Client authentication +ref = 3078 # user identification +secret = pass:insta # can be used for both client and server side + +# Generic message options +cmd = ir # default operation, can be overridden on cmd line with, e.g., kur + +# Certificate enrollment +subject = "/CN=openssl-cmp-test" +newkey = insta.priv.pem +out_trusted = apps/insta.ca.crt # does not include keyUsage digitalSignature +certout = insta.cert.pem + +[pbm] # Password-based protection for Insta CA +# Server and client authentication +ref = $insta::ref # 3078 +secret = $insta::secret # pass:insta + +[signature] # Signature-based protection for Insta CA +# Server authentication +trusted = $insta::out_trusted # apps/insta.ca.crt + +# Client authentication +secret = # disable PBM +key = $insta::newkey # insta.priv.pem +cert = $insta::certout # insta.cert.pem + +[ir] +cmd = ir + +[cr] +cmd = cr + +[kur] +# Certificate update +cmd = kur +oldcert = $insta::certout # insta.cert.pem + +[rr] +# Certificate revocation +cmd = rr +oldcert = $insta::certout # insta.cert.pem diff --git a/src/certexport.c b/src/certexport.c index e10d270..b17d3eb 100644 --- a/src/certexport.c +++ b/src/certexport.c @@ -99,9 +99,9 @@ int cgiMain() { fprintf(cgiOut, "\n"); fprintf(cgiOut, ""); - fprintf(cgiOut, "", + fprintf(cgiOut, "", HTTP_TYPE, cgiServerName, CERTEXPORTURL, certnamestr, format); - fprintf(cgiOut, "http://%s%s/%s.%s", + fprintf(cgiOut, "%s://%s%s/%s.%s", HTTP_TYPE, cgiServerName, CERTEXPORTURL, certnamestr, format); fprintf(cgiOut, ""); fprintf(cgiOut, "\n"); @@ -213,9 +213,15 @@ int cgiMain() { * These function calls are essential to make many PEM + other openssl * * functions work. * * -------------------------------------------------------------------------- */ + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now loads error strings automatically: + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html +#else OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); ERR_load_BIO_strings(); +#endif /* -------------------------------------------------------------------------- * * read the certstore certificate and define a BIO output stream * @@ -337,9 +343,9 @@ int cgiMain() { fprintf(cgiOut, "\n"); fprintf(cgiOut, ""); - fprintf(cgiOut, "\n", + fprintf(cgiOut, "\n", HTTP_TYPE, cgiServerName, CERTEXPORTURL, certnamestr, format); - fprintf(cgiOut, "http://%s%s/%s.%s\n", + fprintf(cgiOut, "%s://%s%s/%s.%s\n", HTTP_TYPE, cgiServerName, CERTEXPORTURL, certnamestr, format); fprintf(cgiOut, "\n"); fprintf(cgiOut, "\n"); diff --git a/src/certrenew.c b/src/certrenew.c index f29cf4c..f10abba 100644 --- a/src/certrenew.c +++ b/src/certrenew.c @@ -23,9 +23,16 @@ int cgiMain() { /* ---------------------------------------------------------- * * These function calls initialize openssl for correct work. * * ---------------------------------------------------------- */ + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now loads error strings automatically: + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html +#else OpenSSL_add_all_algorithms(); - ERR_load_BIO_strings(); ERR_load_crypto_strings(); + ERR_load_BIO_strings(); +#endif + add_missing_ev_oids(); outbio = BIO_new(BIO_s_file()); @@ -153,7 +160,14 @@ int cgiMain() { * ---------------------------------------------------------- */ char cmp_res1_str[40]; // contains the string for match, missmatch, etc int cmp_res1; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 changed EVP_PKEY_cmp() to EVP_PKEY_eq(): + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html + cmp_res1 = EVP_PKEY_eq(priv_key, pub_key); +#else cmp_res1 = EVP_PKEY_cmp(priv_key, pub_key); +#endif if(cmp_res1 == -2) { snprintf(error_str, sizeof(error_str), "Error in EVP_PKEY_cmp(): operation is not supported."); diff --git a/src/certrevoke.c b/src/certrevoke.c index f97cfd3..519f06a 100644 --- a/src/certrevoke.c +++ b/src/certrevoke.c @@ -47,9 +47,15 @@ int cgiMain() { * These function calls are essential to make many PEM + * * other openssl functions work. * * ---------------------------------------------------------- */ + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now loads error strings automatically: + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html +#else OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); ERR_load_BIO_strings(); +#endif /* ---------------------------------------------------------- * * process the CGI calling arguments * @@ -194,7 +200,14 @@ int cgiMain() { * ---------------------------------------------------------- */ char cmp_res1_str[40]; // contains the string for match, missmatch, etc int cmp_res1; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 changed EVP_PKEY_cmp() to EVP_PKEY_eq(): + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html + cmp_res1 = EVP_PKEY_eq(priv_key, pub_key); +#else cmp_res1 = EVP_PKEY_cmp(priv_key, pub_key); +#endif if(cmp_res1 == -2) int_error("Cert key problem in EVP_PKEY_cmp(): operation is not supported"); if(cmp_res1 == -1) snprintf(cmp_res1_str, sizeof(cmp_res1_str), "Cert key type missmatch"); @@ -213,7 +226,13 @@ int cgiMain() { if (! (revo_key = PEM_read_bio_PUBKEY(revbio, NULL, NULL, NULL))) int_error("Error loading revocation key content"); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 changed EVP_PKEY_cmp() to EVP_PKEY_eq(): + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html + cmp_res1 = EVP_PKEY_eq(priv_key, revo_key); +#else cmp_res1 = EVP_PKEY_cmp(priv_key, revo_key); +#endif if(cmp_res1 == -2) int_error("Revocation key problem in EVP_PKEY_cmp(): operation is not supported"); if(cmp_res1 == -1) snprintf(cmp_res1_str, sizeof(cmp_res1_str), "Revocation key type missmatch"); diff --git a/src/certsearch.c b/src/certsearch.c index cc32a0a..82931ba 100644 --- a/src/certsearch.c +++ b/src/certsearch.c @@ -548,10 +548,10 @@ int cgiMain() { int_error("Error retrieving CGI form expiration end time."); strncat(exp_startstr, exp_startdate, sizeof(exp_startstr)-1); - strncat(exp_startstr, " ", 1); /* add a space between date and time */ + strcat(exp_startstr, " "); /* add a space between date and time */ strncat(exp_startstr, exp_starttime, sizeof(exp_startstr)-strlen(exp_startstr)-1); strncat(exp_endstr, exp_enddate, sizeof(exp_endstr)-1); - strncat(exp_endstr, " ", 1); /* add a space between date and time */ + strcat(exp_endstr, " "); /* add a space between date and time */ strncat(exp_endstr, exp_endtime, sizeof(exp_endstr)-strlen(exp_endstr)-1); snprintf(title, sizeof(title), "Search Certs by Expiration"); snprintf(subtitle, sizeof(subtitle), "Certificates with expiration between %s and %s", exp_startstr, exp_endstr); @@ -574,10 +574,10 @@ int cgiMain() { int_error("Error retrieving CGI form enable end time."); strncat(ena_startstr, ena_startdate, sizeof(ena_startstr)-1); - strncat(ena_startstr, " ", 1); /* add a space between date and time */ + strcat(ena_startstr, " "); /* add a space between date and time */ strncat(ena_startstr, ena_starttime, sizeof(ena_startstr)-strlen(ena_startstr)-1); strncat(ena_endstr, ena_enddate, sizeof(ena_endstr)-1); - strncat(ena_endstr, " ", 1); /* add a space between date and time */ + strcat(ena_endstr, " "); /* add a space between date and time */ strncat(ena_endstr, ena_endtime, sizeof(ena_endstr)-strlen(ena_endstr)-1); snprintf(title, sizeof(title), "Search Certs by Start Date"); snprintf(subtitle, sizeof(subtitle), "Certificates with start date between %s and %s", ena_startstr, ena_endstr); @@ -600,10 +600,10 @@ int cgiMain() { int_error("Error retrieving CGI form enable end time."); strncat(rev_startstr, rev_startdate, sizeof(rev_startstr)-1); - strncat(rev_startstr, " ", 1); /* add a space between date and time */ + strcat(rev_startstr, " "); /* add a space between date and time */ strncat(rev_startstr, rev_starttime, sizeof(rev_startstr)-strlen(rev_startstr)-1); strncat(rev_endstr, rev_enddate, sizeof(rev_endstr)-1); - strncat(rev_endstr, " ", 1); /* add a space between date and time */ + strcat(rev_endstr, " "); /* add a space between date and time */ strncat(rev_endstr, rev_endtime, sizeof(rev_endstr)-strlen(rev_endstr)-1); snprintf(title, sizeof(title), "Search Revoked Certificates"); snprintf(subtitle, sizeof(subtitle), "Certificates revoked between %s and %s", rev_startstr, rev_endstr); diff --git a/src/certsign.c b/src/certsign.c index 6688d59..8f68551 100644 --- a/src/certsign.c +++ b/src/certsign.c @@ -49,9 +49,15 @@ int cgiMain() { * These function calls are essential to make many PEM + * * other openssl functions work. * * ---------------------------------------------------------- */ - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - ERR_load_BIO_strings(); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now loads error strings automatically: + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html +#else + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + ERR_load_BIO_strings(); +#endif /* ---------------------------------------------------------- * * check if a certificate was handed to certsign.cgi or if * diff --git a/src/certvalidate.c b/src/certvalidate.c index 29f4e21..0a9fb65 100644 --- a/src/certvalidate.c +++ b/src/certvalidate.c @@ -98,9 +98,16 @@ int cgiMain() { /* ---------------------------------------------------------- * * These function calls initialize openssl for correct work. * * ---------------------------------------------------------- */ + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now loads error strings automatically: + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html +#else OpenSSL_add_all_algorithms(); - ERR_load_BIO_strings(); ERR_load_crypto_strings(); + ERR_load_BIO_strings(); +#endif + add_missing_ev_oids(); time(&now); diff --git a/src/genrequest.c b/src/genrequest.c index 1b8d50c..827c538 100644 --- a/src/genrequest.c +++ b/src/genrequest.c @@ -41,9 +41,6 @@ int cgiMain() { X509_REQ *webrequest = NULL; EVP_PKEY *pkey = NULL; X509_NAME *reqname = NULL; - DSA *mydsa = NULL; - RSA *myrsa = NULL; - EC_KEY *myecc = NULL; EVP_MD const *digest = NULL; BIO *outbio = NULL; @@ -117,13 +114,22 @@ int cgiMain() { if(strlen(cname) == 0) int_error("No CN has been provided. The CN field is mandatory."); + if(cgiFormString("sigalg", sigalgstr, sizeof(sigalgstr)) != cgiFormSuccess) + int_error("Error getting the signature algorithm from buildrequest.cgi form"); + /* ------------------------------------------------------------------------ * * These function calls are essential to make many PEM + other openssl * * functions work. * * ------------------------------------------------------------------------ */ + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now loads error strings automatically: + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html +#else OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); ERR_load_BIO_strings(); +#endif /* ------------------------------------------------------------------------- * * Generate the key pair based on the selected keytype * @@ -131,30 +137,64 @@ int cgiMain() { if ((pkey=EVP_PKEY_new()) == NULL) int_error("Error creating EVP_PKEY structure."); - BIGNUM *exp = BN_new(); - BN_set_word(exp, RSA_F4); - if(strcmp(keytype, "rsa") == 0) { - myrsa = RSA_new(); + BIGNUM *exp = BN_new(); + BN_set_word(exp, RSA_F4); // this sets e=65537 (0x10001L) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY_CTX *ctx = NULL; + ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + EVP_PKEY_keygen_init(ctx); + EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, rsastrength); + EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, 2); +// EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, RSA_F4); + EVP_PKEY_generate(ctx, &pkey); + EVP_PKEY_CTX_free(ctx); +#else + RSA *myrsa = RSA_new(); if (! (RSA_generate_key_ex(myrsa, rsastrength, exp, NULL))) int_error("Error generating the RSA key."); if (!EVP_PKEY_assign_RSA(pkey,myrsa)) int_error("Error assigning RSA key to EVP_PKEY structure."); +#endif } else if(strcmp(keytype, "dsa") == 0) { - mydsa = DSA_new(); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *paramkey = NULL; + pctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL); + if(!EVP_PKEY_paramgen_init(pctx)) + int_error("Error initializing DSA key parameters."); + if(!EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx, dsastrength)) + int_error("Error setting DSA key strength."); + if (!EVP_PKEY_paramgen(pctx, ¶mkey)) + int_error("Error setting DSA parameter list object."); + EVP_PKEY_CTX_free(pctx); + + EVP_PKEY_CTX *ctx = NULL; + ctx = EVP_PKEY_CTX_new(paramkey, NULL); + if(!EVP_PKEY_keygen_init(ctx)) + int_error("Error initializing DSA key."); + if(!EVP_PKEY_keygen(ctx, &pkey)) + int_error("Error generating the DSA key."); + EVP_PKEY_CTX_free(ctx); +#else + DSA *mydsa = DSA_new(); DSA_generate_parameters_ex(mydsa, dsastrength, NULL, 0, NULL, NULL, NULL); if (! (DSA_generate_key(mydsa))) int_error("Error generating the DSA key."); if (!EVP_PKEY_assign_DSA(pkey,mydsa)) int_error("Error assigning DSA key to EVP_PKEY structure."); +#endif } else if(strcmp(keytype, "ecc") == 0) { - myecc = EC_KEY_new(); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + pkey = EVP_EC_gen(eccstrength); +#else + EC_KEY *myecc = EC_KEY_new(); int eccgrp = OBJ_txt2nid(eccstrength); myecc = EC_KEY_new_by_curve_name(eccgrp); /* Important to set the OPENSSL_EC_NAMED_CURVE flag, * @@ -165,13 +205,11 @@ int cgiMain() { if (!EVP_PKEY_assign_EC_KEY(pkey,myecc)) int_error("Error assigning ECC key to EVP_PKEY structure."); +#endif } else int_error("Error: Wrong keytype - choose either RSA, DSA or ECC."); - if(cgiFormString("sigalg", sigalgstr, sizeof(sigalgstr)) != cgiFormSuccess) - int_error("Error getting the signature algorithm from buildrequest.cgi form"); - /* ------------------------------------------------------------------------- * * Generate the certificate request from scratch * * ------------------------------------------------------------------------- */ diff --git a/src/keycompare.c b/src/keycompare.c index 2e367de..a89ba61 100644 --- a/src/keycompare.c +++ b/src/keycompare.c @@ -18,11 +18,16 @@ #include #include "webcert.h" +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#endif + int key_enc_check(EVP_PKEY *, EVP_PKEY *); -int rsa_cmp_mod(RSA *, RSA *); -int rsa_enc_check(RSA *, RSA *); -int dsa_enc_check(DSA *, DSA *); +int rsa_cmp_mod(EVP_PKEY *, EVP_PKEY *); +int rsa_enc_check(EVP_PKEY *, EVP_PKEY *); +int dsa_enc_check(EVP_PKEY *, EVP_PKEY *); int ec_enc_check(EC_KEY *, EC_KEY *); int cgiMain() { @@ -30,9 +35,15 @@ int cgiMain() { * These function calls are essential to make many PEM + other* * OpenSSL functions work. * * ---------------------------------------------------------- */ - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - ERR_load_BIO_strings(); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now loads error strings automatically: + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html +#else + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + ERR_load_BIO_strings(); +#endif static char title[] = "Key Checker"; @@ -196,7 +207,14 @@ int cgiMain() { * ---------------------------------------------------------- */ char cmp_res1_str[40]; // contains the string for match, missmatch, etc int cmp_res1; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 changed EVP_PKEY_cmp() to EVP_PKEY_eq(): + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html + cmp_res1 = EVP_PKEY_eq(priv_key, pub_key); +#else cmp_res1 = EVP_PKEY_cmp(priv_key, pub_key); +#endif if(cmp_res1 == -2) { snprintf(error_str, sizeof(error_str), "Error in EVP_PKEY_cmp(): operation is not supported."); @@ -263,15 +281,7 @@ int key_data_check(EVP_PKEY *priv, EVP_PKEY *pub) { switch (EVP_PKEY_base_id(priv)) { case EVP_PKEY_RSA: if(EVP_PKEY_base_id(pub) == EVP_PKEY_RSA) { - RSA *privrsa, *pubrsa; - - if((privrsa = EVP_PKEY_get1_RSA(priv)) == NULL) - int_error("Error getting RSA private key data."); - - if((pubrsa = EVP_PKEY_get1_RSA(pub)) == NULL) - int_error("Error getting RSA public key data."); - - ret = rsa_cmp_mod(privrsa, pubrsa); + ret = rsa_cmp_mod(priv, pub); return ret; } else return -1; @@ -305,73 +315,78 @@ int key_data_check(EVP_PKEY *priv, EVP_PKEY *pub) { * matches by comparing the RSA modulus. Returns 1 for OK, 0 for * * missmatch. * * ------------------------------------------------------------- */ -int rsa_cmp_mod(RSA *priv, RSA *pub) { +int rsa_cmp_mod(EVP_PKEY *priv, EVP_PKEY *pub) { int match; - const BIGNUM **priv_mod = NULL; - const BIGNUM **pub_mod = NULL; - RSA_get0_key(priv, priv_mod, NULL, NULL); - char *priv_mod_hex = BN_bn2hex(*priv_mod); - - RSA_get0_key(pub, pub_mod, NULL, NULL); - char *pub_mod_hex = BN_bn2hex(*pub_mod); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + /* -------------------------------------------------------- * + * Old code for OpenSSL versions before version 3.0 * + * ---------------------------------------------------------*/ + const BIGNUM *priv_mod; + const BIGNUM *pub_mod; + RSA *privrsa = NULL; + if((privrsa = EVP_PKEY_get1_RSA(priv)) == NULL) + int_error("Error getting RSA private key data."); + RSA_get0_key(privrsa, &priv_mod, NULL, NULL); + + RSA *pubrsa = NULL; + if((pubrsa = EVP_PKEY_get1_RSA(pub)) == NULL) + int_error("Error getting RSA public key data."); + RSA_get0_key(pubrsa, &pub_mod, NULL, NULL); +#else + /* -------------------------------------------------------- * + * New code for latest OpenSSL version 3.0 * + * ---------------------------------------------------------*/ + BIGNUM *priv_mod = NULL; + BIGNUM *pub_mod = NULL; + EVP_PKEY_get_bn_param(priv, OSSL_PKEY_PARAM_RSA_N, &priv_mod); + EVP_PKEY_get_bn_param(pub, OSSL_PKEY_PARAM_RSA_N, &pub_mod); +#endif + + char *priv_mod_hex = BN_bn2hex(priv_mod); + char *pub_mod_hex = BN_bn2hex(pub_mod); //printf("priv: %s\n", priv_mod_hex); - //printf("pub: %s\n", pub_mod_hex); + //printf(" pub: %s\n", pub_mod_hex); if(strcmp(priv_mod_hex, pub_mod_hex) == 0) match = 1; // the keys modulus is matching else match = 0; // the keys modulus don't match +#if OPENSSL_VERSION_NUMBER < 0x30000000L OPENSSL_free(priv_mod_hex); OPENSSL_free(pub_mod_hex); +#endif return match; } /* ------------------------------------------------------------- * * Function key_encr_check() checks if a public and private key * * matches by doing EVP_PKEY_sign/EVP_PKEY_verify. Returns 1 for * - * OK, 0 for key missmatch, -1 for type missmatch. * + * OK the keys match, 0 for key missmatch, -1 for type missmatch * * ------------------------------------------------------------- */ int key_enc_check(EVP_PKEY *priv, EVP_PKEY *pub) { int ret = -1; - switch (EVP_PKEY_base_id(priv)) { + switch (EVP_PKEY_id(priv)) { case EVP_PKEY_RSA: - if(EVP_PKEY_base_id(pub) == EVP_PKEY_RSA) { - RSA *privrsa, *pubrsa; - - if((privrsa = EVP_PKEY_get1_RSA(priv)) == NULL) - int_error("Error getting RSA private key data."); - - if((pubrsa = EVP_PKEY_get1_RSA(pub)) == NULL) - int_error("Error getting RSA public key data."); - - ret = rsa_enc_check(privrsa, pubrsa); - RSA_free(privrsa); - RSA_free(pubrsa); - return ret; - } - else return -1; + /* ------------------------------------------------------- * + ` * Type match RSA: If privkey is RSA, is pubkey also RSA? * + * If not return -1, if yes do encrypt/decrypt test next * + * ------------------------------------------------------- */ + if(EVP_PKEY_id(pub) != EVP_PKEY_RSA) return -1; + ret = rsa_enc_check(priv, pub); + return ret; break; case EVP_PKEY_DSA: - if(EVP_PKEY_base_id(pub) == EVP_PKEY_DSA) { - DSA *privdsa, *pubdsa; - - if((privdsa = EVP_PKEY_get1_DSA(priv)) == NULL) - int_error("Error getting DSA private key data."); - - if((pubdsa = EVP_PKEY_get1_DSA(pub)) == NULL) - int_error("Error getting DSA public key data."); - - ret = dsa_enc_check(privdsa, pubdsa); - DSA_free(privdsa); - DSA_free(pubdsa); - return ret; - } - else - int_error("Error public key type does not match private DSA key"); + /* ------------------------------------------------------- * + ` * Type match DSA: If privkey is DSA, is pubkey also DSA? * + * If not return -1, if yes do encrypt/decrypt test next * + * ------------------------------------------------------- */ + if(EVP_PKEY_id(pub) != EVP_PKEY_DSA) return -1; + ret = dsa_enc_check(priv, pub); + return ret; break; case EVP_PKEY_EC: @@ -389,53 +404,135 @@ int key_enc_check(EVP_PKEY *priv, EVP_PKEY *pub) { return ret; } -int rsa_enc_check(RSA *priv, RSA *pub) { +/* ------------------------------------------------------------ * + * rsa_enc_check takes a private and public key to encrypt and * + * decrypt a test string, then compares the decrypted string. * + * ------------------------------------------------------------ */ +int rsa_enc_check(EVP_PKEY *priv, EVP_PKEY *pub) { int match = -1; /* ---------------------------------------------------------- * - * Create a random 512 byte md string for signing * + * Create a random 24 byte test string to encrypt with priv * * ---------------------------------------------------------- */ - const char md[] = "This is a secret string"; + const unsigned char md[] = "This is a secret string"; size_t md_len = sizeof(md); /* ---------------------------------------------------------- * - * Define the encrypted buffer, assign memory * + * Define the RSA padding method for both encrypt/decrypt ops * * ---------------------------------------------------------- */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const char pad = RSA_PKCS1_PADDING; +#else + OSSL_PARAM params[2]; + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, + OSSL_PKEY_RSA_PAD_MODE_PKCSV15, 0); + params[1] = OSSL_PARAM_construct_end(); + EVP_PKEY_CTX *ctx = NULL; +#endif + + /* ---------------------------------------------------------- * + * Define the encrypted buffer, assign and zero out memory * + * buffer size is hardcoded as 1024 bytes (1K) to simplify. * + * watch buffer overrun if we get large key sizes or large * + * md test strings. * + * ---------------------------------------------------------- */ + size_t enc_len; unsigned char *enc_str; - enc_str = OPENSSL_malloc(RSA_size(priv)); + enc_str = OPENSSL_zalloc(1024); if (!enc_str) int_error("Error allocating memory for encryption result."); /* ---------------------------------------------------------- * * Encrypt string with private RSA key * * ---------------------------------------------------------- */ - size_t enc_len; - const unsigned char pad = RSA_PKCS1_PADDING; - - enc_len = RSA_public_encrypt(md_len, (unsigned char*) md, enc_str, priv, pad); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + RSA *privrsa; + if((privrsa = EVP_PKEY_get1_RSA(priv)) == NULL) + int_error("Error getting RSA private key data."); + enc_len = RSA_public_encrypt(md_len, (unsigned char*) md, enc_str, privrsa, pad); + RSA_free(privrsa); +# else + ctx = NULL; + ctx = EVP_PKEY_CTX_new_from_pkey(NULL, priv, NULL); + EVP_PKEY_encrypt_init_ex(ctx, params); + EVP_PKEY_encrypt(ctx, enc_str, (size_t *) &enc_len, md, md_len); + EVP_PKEY_CTX_free(ctx); +#endif if(enc_len <= 0) int_error("Error encrypting digest with private RSA key."); /* ---------------------------------------------------------- * * Successfully encrypted, now decrypt it with public RSA key * + * buffer size is hardcoded as 1024 bytes (1K) to simplify. * + * watch buffer overrun if we set larger md test strings. * * ---------------------------------------------------------- */ - char *clr_str; - clr_str = OPENSSL_malloc(RSA_size(pub)); - if (!clr_str) - int_error("Error allocating memory for decryption result."); - size_t clr_len; - clr_len = RSA_private_decrypt(enc_len, enc_str, (unsigned char*) clr_str, pub, pad); + unsigned char clr_str[1024] = ""; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + RSA *pubrsa; + if((pubrsa = EVP_PKEY_get1_RSA(pub)) == NULL) + int_error("Error getting RSA public key data."); + clr_len = RSA_private_decrypt(enc_len, enc_str, (unsigned char*) clr_str, pubrsa, pad); + RSA_free(pubrsa); +#else + ctx = NULL; + ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pub, NULL); + EVP_PKEY_decrypt_init_ex(ctx, params); + EVP_PKEY_decrypt(ctx, clr_str, (size_t *) &clr_len, enc_str, enc_len); + EVP_PKEY_CTX_free(ctx); +#endif if(clr_len <= 0) int_error("Error decrypting digest with public RSA key."); - - if(strcmp(md, clr_str) == 0) match = 1; // The keys match + /* ---------------------------------------------------------- * + * Successfully decrypted, compare decrypt string with orig. * + * ---------------------------------------------------------- */ + if(strcmp((char *)md, (char *)clr_str) == 0) match = 1; // The keys match else match = 0; // The keys don't match - return match; } -int dsa_enc_check(DSA *priv, DSA *pub) { +/* ------------------------------------------------------------ * + * dsa_enc_check takes a private and public key to encrypt and * + * decrypt a test string, then compares the decrypted string. * + * THIS FUNCTION IS IN DEV - not implemented yet!!!!!!!!!!!!! * + * ------------------------------------------------------------ */ +int dsa_enc_check(EVP_PKEY *priv, EVP_PKEY *pub) { + //int match = -1; + /* ---------------------------------------------------------- * + * Create a random 24 byte test string to encrypt with priv * + * ---------------------------------------------------------- */ + //const unsigned char md[] = "This is a secret string"; + //size_t md_len = sizeof(md); + + /* ---------------------------------------------------------- * + * Define the encrypted buffer, assign and zero out memory * + * buffer size is hardcoded as 1024 bytes (1K) to simplify. * + * watch buffer overrun if we get large key sizes or large * + * md test strings. * + * ---------------------------------------------------------- */ + //size_t enc_len; + unsigned char *enc_str; + enc_str = OPENSSL_zalloc(1024); + if (!enc_str) + int_error("Error allocating memory for encryption result."); + + /* ---------------------------------------------------------- * + * Encrypt string with private DSA key * + * ---------------------------------------------------------- */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L + DSA *privdsa; + if((privdsa = EVP_PKEY_get1_DSA(priv)) == NULL) + int_error("Error getting DSA private key data."); + // encryption function goes here + DSA_free(privdsa); + + DSA *pubdsa; + if((pubdsa = EVP_PKEY_get1_DSA(pub)) == NULL) + int_error("Error getting DSA public key data."); + // decryption function goes here + DSA_free(pubdsa); +#endif return 1; } int ec_enc_check(EC_KEY *priv, EC_KEY *pub) { diff --git a/src/p12convert.c b/src/p12convert.c index ca87c9f..c94097d 100644 --- a/src/p12convert.c +++ b/src/p12convert.c @@ -38,9 +38,15 @@ int cgiMain() { * These function calls are essential to make many PEM + other* * OpenSSL functions work. * * ---------------------------------------------------------- */ - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - ERR_load_BIO_strings(); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now loads error strings automatically: + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html +#else + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + ERR_load_BIO_strings(); +#endif /* ---------------------------------------------------------- * * If called w/o arguments, display the data gathering form. * @@ -409,9 +415,9 @@ int cgiMain() { fprintf(cgiOut, ""); fprintf(cgiOut, "PKCS12 URL:"); fprintf(cgiOut, ""); - fprintf(cgiOut, "", + fprintf(cgiOut, "", HTTP_TYPE, cgiServerName, CERTEXPORTURL, p12name); - fprintf(cgiOut, "http://%s%s/tmp/%s\n", + fprintf(cgiOut, "%s://%s%s/tmp/%s\n", HTTP_TYPE, cgiServerName, CERTEXPORTURL, p12name); fprintf(cgiOut, "\n"); fprintf(cgiOut, "\n"); diff --git a/src/pagefoot.c b/src/pagefoot.c index 8d7d65b..751207b 100644 --- a/src/pagefoot.c +++ b/src/pagefoot.c @@ -32,7 +32,7 @@ void pagefoot() { fprintf(cgiOut, "
\n"); fprintf(cgiOut, "
\n"); - fprintf(cgiOut, "© %s by Frank4DD.\n", SW_VERSION); + fprintf(cgiOut, "© %s by Frank4DD.\n", SW_VERSION); fprintf(cgiOut, ""); fprintf(cgiOut, "Generated on: %s", hostport); fprintf(cgiOut, " for "); diff --git a/src/serial.c b/src/serial.c index 4648cbf..cb1c45a 100644 --- a/src/serial.c +++ b/src/serial.c @@ -24,7 +24,14 @@ int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) { if (!btmp) return 0; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + // OpenSSL v3.0 now uses BN_rand(): + // https://www.openssl.org/docs/manmaster/man7/migration_guide.html + if (!BN_rand(btmp, SERIAL_RAND_BITS, 0, 0)) goto err; +#else if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) goto err; +#endif + if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) goto err; return 1; diff --git a/src/webcert.c b/src/webcert.c index 58f8983..5b738ac 100644 --- a/src/webcert.c +++ b/src/webcert.c @@ -18,6 +18,11 @@ #include #include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif + + int check_index(X509 *x509, CA_DB *db); /* ---------------------------------------------------------- * @@ -281,7 +286,6 @@ void display_csr(X509_REQ *csr) { fprintf(cgiOut, "Public Key:\n"); fprintf(cgiOut, ""); if (pkey) { - EC_KEY *myecc = NULL; switch (EVP_PKEY_base_id(pkey)) { case EVP_PKEY_RSA: fprintf(cgiOut, "%d bit RSA Key", EVP_PKEY_bits(pkey)); @@ -290,10 +294,23 @@ void display_csr(X509_REQ *csr) { fprintf(cgiOut, "%d bit DSA Key", EVP_PKEY_bits(pkey)); break; case EVP_PKEY_EC: +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + char curvestr[80]; + EVP_PKEY_get_utf8_string_param(pkey, + OSSL_PKEY_PARAM_GROUP_NAME, + curvestr, + sizeof(curvestr), + NULL); + fprintf(cgiOut, "%d bit ECC Key, type %s", + EVP_PKEY_bits(pkey), + curvestr); +#else + EC_KEY *myecc = NULL; myecc = EVP_PKEY_get1_EC_KEY(pkey); const EC_GROUP *ecgrp = EC_KEY_get0_group(myecc); fprintf(cgiOut, "%d bit ECC Key, type %s", EVP_PKEY_bits(pkey), OBJ_nid2sn(EC_GROUP_get_curve_name(ecgrp))); +#endif break; default: fprintf(cgiOut, "%d bit %s Key", EVP_PKEY_bits(pkey), OBJ_nid2sn(EVP_PKEY_base_id(pkey))); @@ -397,7 +414,6 @@ void display_key(EVP_PKEY *pkey) { fprintf(cgiOut, ""); /* display the key type and size here */ if (pkey) { - EC_KEY *myecc = NULL; switch (EVP_PKEY_base_id(pkey)) { case EVP_PKEY_RSA: fprintf(cgiOut, "%d bit RSA Key", EVP_PKEY_bits(pkey)); @@ -406,10 +422,23 @@ void display_key(EVP_PKEY *pkey) { fprintf(cgiOut, "%d bit DSA Key", EVP_PKEY_bits(pkey)); break; case EVP_PKEY_EC: +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + char curvestr[80]; + EVP_PKEY_get_utf8_string_param(pkey, + OSSL_PKEY_PARAM_GROUP_NAME, + curvestr, + sizeof(curvestr), + NULL); + fprintf(cgiOut, "%d bit ECC Key, type %s", + EVP_PKEY_bits(pkey), + curvestr); +#else + EC_KEY *myecc = NULL; myecc = EVP_PKEY_get1_EC_KEY(pkey); const EC_GROUP *ecgrp = EC_KEY_get0_group(myecc); fprintf(cgiOut, "%d bit ECC Key, type %s", EVP_PKEY_bits(pkey), OBJ_nid2sn(EC_GROUP_get_curve_name(ecgrp))); +#endif break; default: fprintf(cgiOut, "%d bit non-RSA/DSA Key", EVP_PKEY_bits(pkey)); @@ -436,7 +465,6 @@ void display_key(EVP_PKEY *pkey) { fprintf(cgiOut, ""); /* display the key type and size here */ if (pkey) { - EC_KEY *myecc = NULL; switch (EVP_PKEY_base_id(pkey)) { case EVP_PKEY_RSA: fprintf(cgiOut, "%d bit RSA Key", EVP_PKEY_bits(pkey)); @@ -445,10 +473,23 @@ void display_key(EVP_PKEY *pkey) { fprintf(cgiOut, "%d bit DSA Key", EVP_PKEY_bits(pkey)); break; case EVP_PKEY_EC: +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + char curvestr[80]; + EVP_PKEY_get_utf8_string_param(pkey, + OSSL_PKEY_PARAM_GROUP_NAME, + curvestr, + sizeof(curvestr), + NULL); + fprintf(cgiOut, "%d bit ECC Key, type %s", + EVP_PKEY_bits(pkey), + curvestr); +#else + EC_KEY *myecc = NULL; myecc = EVP_PKEY_get1_EC_KEY(pkey); const EC_GROUP *ecgrp = EC_KEY_get0_group(myecc); fprintf(cgiOut, "%d bit ECC Key, type %s", EVP_PKEY_bits(pkey), OBJ_nid2sn(EC_GROUP_get_curve_name(ecgrp))); +#endif break; default: fprintf(cgiOut, "%d bit non-RSA/DSA Key", EVP_PKEY_bits(pkey)); @@ -662,7 +703,6 @@ void display_cert(X509 *ct, char ct_type[], char chain_type[], int level) { fprintf(cgiOut, ""); /* display the key type and size here */ if (pkey) { - EC_KEY *myecc = NULL; switch (EVP_PKEY_base_id(pkey)) { case EVP_PKEY_RSA: fprintf(cgiOut, "%d bit RSA Key", EVP_PKEY_bits(pkey)); @@ -671,10 +711,23 @@ void display_cert(X509 *ct, char ct_type[], char chain_type[], int level) { fprintf(cgiOut, "%d bit DSA Key", EVP_PKEY_bits(pkey)); break; case EVP_PKEY_EC: +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + char curvestr[80]; + EVP_PKEY_get_utf8_string_param(pkey, + OSSL_PKEY_PARAM_GROUP_NAME, + curvestr, + sizeof(curvestr), + NULL); + fprintf(cgiOut, "%d bit ECC Key, type %s", + EVP_PKEY_bits(pkey), + curvestr); +#else + EC_KEY *myecc = NULL; myecc = EVP_PKEY_get1_EC_KEY(pkey); const EC_GROUP *ecgrp = EC_KEY_get0_group(myecc); fprintf(cgiOut, "%d bit ECC Key, type %s", EVP_PKEY_bits(pkey), OBJ_nid2sn(EC_GROUP_get_curve_name(ecgrp))); +#endif break; default: fprintf(cgiOut, "%d bit non-RSA/DSA Key", EVP_PKEY_bits(pkey)); diff --git a/src/webcert.h b/src/webcert.h index c7c5389..6f57ccb 100644 --- a/src/webcert.h +++ b/src/webcert.h @@ -10,6 +10,8 @@ #include "openssl/bn.h" #include +/*********** Set https / http protocol for webcert file download **************/ +#define HTTP_TYPE "https" /*********** the main URL where the webcert application resides ***************/ #define HOMELINK "/webcert/" /*********** the application entry URL which is seen first ********************/ @@ -61,7 +63,7 @@ /***************** *********************************** ************************/ #define CONTACT_EMAIL "support@fm4dd.com" -#define SW_VERSION "WebCert v1.8.4 (12/20/2021)" +#define SW_VERSION "WebCert v1.8.5 (01/13/2024)" /*********** html code template for populating the sidebar *******************/ #define SIDEBAR_TEMPL "../sidebar-template.htm" /* optional */