diff --git a/apps/signer/gst-plugin/gstsigning.c b/apps/signer/gst-plugin/gstsigning.c index d8300ce..be5a0ff 100644 --- a/apps/signer/gst-plugin/gstsigning.c +++ b/apps/signer/gst-plugin/gstsigning.c @@ -27,17 +27,34 @@ #ifdef HAVE_CONFIG_H #include #endif +#include // FILE, etc +#include // strstr, strcat +#if defined(_WIN32) || defined(_WIN64) +#include +#define getcwd _getcwd // "deprecation" warning +#else +#include // getcwd +#endif #include "gstsigning.h" #include "gstsigning_defines.h" #include #include #include +#include GST_DEBUG_CATEGORY_STATIC(gst_signing_debug); #define GST_CAT_DEFAULT gst_signing_debug +enum +{ + PROP_0, + PROP_PROVISIONED +}; +#define DEFAULT_PROVISIONED 0 // Key is not provisioned + struct _GstSigningPrivate { + gint provisioned; signed_video_t *signed_video; GstClockTime last_pts; }; @@ -72,6 +89,42 @@ setup_signing(GstSigning *signing, GstCaps *caps); static gboolean terminate_signing(GstSigning *signing); +static void +gst_signing_get_property(GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstSigning *signing = GST_SIGNING(object); + + GST_OBJECT_LOCK(signing); + switch (prop_id) { + case PROP_PROVISIONED: + g_value_set_int(value, signing->priv->provisioned); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK(signing); +} + +static void +gst_signing_set_property(GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstSigning *signing = GST_SIGNING(object); + GstSigningPrivate *priv = signing->priv; + + GST_OBJECT_LOCK(signing); + switch (prop_id) { + case PROP_PROVISIONED: + priv->provisioned = g_value_get_int(value); + GST_DEBUG_OBJECT(object, "new provisioned value: %d", priv->provisioned); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK(signing); +} + static void gst_signing_class_init(GstSigningClass *klass) { @@ -89,13 +142,20 @@ gst_signing_class_init(GstSigningClass *klass) transform_class->sink_event = GST_DEBUG_FUNCPTR(gst_signing_sink_event); gst_element_class_set_static_metadata(element_class, "Signed Video", "Formatter/Video", - "Add SEI nalus containing signatures for authentication.", + "Add SEIs containing signatures for authentication.", "Signed Video Framework "); gst_element_class_add_static_pad_template(element_class, &sink_template); gst_element_class_add_static_pad_template(element_class, &src_template); gobject_class->finalize = gst_signing_finalize; + gobject_class->get_property = gst_signing_get_property; + gobject_class->set_property = gst_signing_set_property; + + // Install properties + g_object_class_install_property(gobject_class, PROP_PROVISIONED, + g_param_spec_int("provisioned", "Provisioned key", "Use pre-generated key and certificate", + 0, 1, DEFAULT_PROVISIONED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -168,7 +228,8 @@ create_buffer_with_current_time(GstSigning *signing) * Returns the number of nalus that were prepended to @current_au, * or -1 on error. */ static gint -get_and_add_sei(GstSigning *signing, GstBuffer * current_au, gint idx, const guint8 * peek_nalu, gsize peek_nalu_size) +get_and_add_sei(GstSigning *signing, GstBuffer * current_au, gint idx, const guint8 * peek_nalu, + gsize peek_nalu_size) { SignedVideoReturnCode sv_rc; gint prepend_count = 0; @@ -180,7 +241,8 @@ get_and_add_sei(GstSigning *signing, GstBuffer * current_au, gint idx, const gui * signed_video_get_sei(signed_video_t *self, uint8_t **sei, size_t *sei_size, * unsigned *payload_offset, const uint8_t *peek_nalu, * size_t peek_nalu_size, unsigned *num_pending_seis); */ - sv_rc = signed_video_get_sei (signing->priv->signed_video, &sei, &sei_size, NULL, peek_nalu, peek_nalu_size, NULL); + sv_rc = signed_video_get_sei (signing->priv->signed_video, &sei, &sei_size, NULL, peek_nalu, + peek_nalu_size, NULL); while (sv_rc == SV_OK && sei_size > 0 && sei) { GstMemory *prepend_mem; @@ -193,7 +255,8 @@ get_and_add_sei(GstSigning *signing, GstBuffer * current_au, gint idx, const gui gst_buffer_insert_memory(current_au, idx, prepend_mem); prepend_count++; - sv_rc = signed_video_get_sei(signing->priv->signed_video, &sei, &sei_size, NULL, peek_nalu, peek_nalu_size, NULL); + sv_rc = signed_video_get_sei(signing->priv->signed_video, &sei, &sei_size, NULL, peek_nalu, + peek_nalu_size, NULL); } if (sv_rc != SV_OK) { @@ -220,7 +283,8 @@ gst_signing_transform_ip(GstBaseTransform *trans, GstBuffer *buf) priv->last_pts = GST_BUFFER_PTS(buf); // last_pts is an GstClockTime object, which is measured in nanoseconds. const gint64 timestamp_usec = (const gint64)(priv->last_pts / 1000); - const gint64 *timestamp_usec_ptr = priv->last_pts == GST_CLOCK_TIME_NONE ? NULL : ×tamp_usec; + const gint64 *timestamp_usec_ptr = + priv->last_pts == GST_CLOCK_TIME_NONE ? NULL : ×tamp_usec; GST_DEBUG_OBJECT(signing, "got buffer with %d memories", gst_buffer_n_memory(buf)); while (idx < gst_buffer_n_memory(buf)) { @@ -331,6 +395,82 @@ terminate_signing(GstSigning *signing) return TRUE; } +#define MAX_PATH_LENGTH 500 +static gboolean +read_file_content(const char *filename, char **content, gsize *content_size) +{ + gboolean success = FALSE; + FILE *fp = NULL; + char full_path[MAX_PATH_LENGTH] = {0}; + char cwd[MAX_PATH_LENGTH] = {0}; + + *content = NULL; + *content_size = 0; + + if (!getcwd(cwd, sizeof(cwd))) { + goto done; + } + + // Find the root location of the library. + char *lib_root = NULL; + char *next_lib_root = strstr(cwd, "signed-video-framework-examples"); + if (!next_lib_root) { + // Current location is not inside signed-video-framework. Assuming current working directory is + // the parent directory, to give it another try. If that is not the case opening the |full_path| + // will fail, which is fine since the true location is not known anyhow. + strcat(cwd, "/signed-video-framework-examples"); + next_lib_root = strstr(cwd, "signed-video-framework-examples"); + } + while (next_lib_root) { + lib_root = next_lib_root; + next_lib_root = strstr(next_lib_root + 1, "signed-video-framework-examples"); + } + if (!lib_root) { + goto done; + } + // Terminate string after lib root. + memset(lib_root + strlen("signed-video-framework-examples"), '\0', 1); + + // Get certificate chain from folder test-files/. + strcat(full_path, cwd); + strcat(full_path, "/test-files/"); + strcat(full_path, filename); + + fp = fopen(full_path, "rb"); + if (!fp) { + goto done; + } + + fseek(fp, 0L, SEEK_END); + size_t file_size = ftell(fp); + if (file_size == 0) { + goto done; + } + + *content = calloc(1, file_size + 1); // One extra byte for '\0' in case the content is a string. + if (!(*content)) { + goto done; + } + + rewind(fp); + if (fread(*content, sizeof(char), file_size / sizeof(char), fp) == 0) { + goto done; + } + *content_size = file_size; + + success = TRUE; + +done: + if (fp) { + fclose(fp); + } + if (!success) { + free(*content); + } + + return success; +} + static gboolean setup_signing(GstSigning *signing, GstCaps *caps) { @@ -340,6 +480,8 @@ setup_signing(GstSigning *signing, GstCaps *caps) SignedVideoCodec codec; char *private_key = NULL; size_t private_key_size = 0; + char *certificate_chain = NULL; + size_t certificate_chain_size = 0; g_assert(caps != NULL); @@ -367,9 +509,26 @@ setup_signing(GstSigning *signing, GstCaps *caps) GST_ERROR_OBJECT(signing, "could not create Signed Video object"); goto create_failed; } - if (signed_video_generate_ecdsa_private_key(PATH_TO_KEY_FILES, &private_key, &private_key_size) != SV_OK) { - GST_DEBUG_OBJECT(signing, "failed to generate pem file"); - goto generate_private_key_failed; + + if (!priv->provisioned) { + if (signed_video_generate_ecdsa_private_key(PATH_TO_KEY_FILES, &private_key, &private_key_size) != SV_OK) { + GST_DEBUG_OBJECT(signing, "failed to generate pem file"); + goto generate_private_key_failed; + } + } else { + if (!read_file_content("private_ecdsa_key.pem", &private_key, &private_key_size)) { + goto generate_private_key_failed; + } + if (!read_file_content("cert_chain.pem", &certificate_chain, &certificate_chain_size)) { + goto read_cert_failed; + } + // Use the Axis api to set the certificate chain without attestation. This will + // trigger factory provisioned signing in the library. + if (sv_vendor_axis_communications_set_attestation_report(priv->signed_video, NULL, 0, + certificate_chain) != SV_OK) { + GST_DEBUG_OBJECT(signing, "failed to set certificate chain content"); + goto set_cert_failed; + } } if (signed_video_set_private_key(priv->signed_video, private_key, private_key_size) != SV_OK) { GST_DEBUG_OBJECT(signing, "failed to set private key content"); @@ -384,12 +543,18 @@ setup_signing(GstSigning *signing, GstCaps *caps) goto product_info_failed; } + g_free(certificate_chain); + g_free(private_key); + return TRUE; product_info_failed: set_private_key_failed: -generate_private_key_failed: +set_cert_failed: + g_free(certificate_chain); +read_cert_failed: g_free(private_key); +generate_private_key_failed: signed_video_free(priv->signed_video); priv->signed_video = NULL; create_failed: diff --git a/apps/signer/main.c b/apps/signer/main.c index e596180..3a219b7 100644 --- a/apps/signer/main.c +++ b/apps/signer/main.c @@ -102,6 +102,7 @@ main(gint argc, gchar *argv[]) "Usage:\n%s [-h] [-c codec] filename\n\n" "Optional\n" " -c codec : 'h264' (default) or 'h265'\n" + " -p : provisioned key, i.e., public key in cert (needs lib to be built with Axis)'\n" "Required\n" " filename : Name of the file to be signed.\n", argv[0]); @@ -112,6 +113,7 @@ main(gint argc, gchar *argv[]) gchar *mux_str = "mp4mux"; gchar *filename = NULL; gchar *outfilename = NULL; + gboolean provisioned = FALSE; GstElement *pipeline = NULL; GstElement *filesrc = NULL; @@ -139,6 +141,8 @@ main(gint argc, gchar *argv[]) } else if (strcmp(argv[arg], "-c") == 0) { arg++; codec_str = argv[arg]; + } else if (strcmp(argv[arg], "-p") == 0) { + provisioned = TRUE; } else if (strncmp(argv[arg], "-", 1) == 0) { // Unknown option. g_message("Unknown option: %s\n%s", argv[arg], usage); @@ -216,6 +220,9 @@ main(gint argc, gchar *argv[]) parser = gst_element_factory_make("h265parse", NULL); } signedvideo = gst_element_factory_make("signing", NULL); + if (provisioned) { + g_object_set(G_OBJECT(signedvideo), "provisioned", 1, NULL); + } muxer = gst_element_factory_make(mux_str, NULL); filesink = gst_element_factory_make("filesink", NULL); diff --git a/apps/validator/main.c b/apps/validator/main.c index ea41fb8..c3017b2 100644 --- a/apps/validator/main.c +++ b/apps/validator/main.c @@ -386,6 +386,11 @@ on_new_sample_from_sink(GstElement *elt, ValidationData *data) } // Allocate memory and copy version strings. if (strlen(data->auth_report->this_version) > 0) { + if (strstr(data->auth_report->this_version, "ONVIF") != NULL) { + g_free(data->this_version); + data->this_version = g_malloc0(strlen(data->auth_report->this_version) + 1); + strcpy(data->this_version, data->auth_report->this_version); + } if (strcmp(data->this_version, data->auth_report->this_version) != 0) { g_error("unexpected mismatch in 'this_version'"); } diff --git a/test-files/cert_chain.pem b/test-files/cert_chain.pem new file mode 100644 index 0000000..4d945b7 --- /dev/null +++ b/test-files/cert_chain.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIBaDCCAQ8CFG6wXFCygzYra7AmaFv2FoSsZfHGMAoGCCqGSM49BAMCMDcxEDAO +BgNVBAoMB1NvbWVPcmcxDTALBgNVBAsMBFRlc3QxFDASBgNVBAMMC1Rlc3QgUm9v +dENBMB4XDTI1MDMwNDExMDUxOFoXDTI2MDMwNDExMDUxOFowNzEQMA4GA1UECgwH +U29tZU9yZzENMAsGA1UECwwEVGVzdDEUMBIGA1UEAwwLVGVzdCBjYW1lcmEwWTAT +BgcqhkjOPQIBBggqhkjOPQMBBwNCAAQNWFD88M9YY2Ru/4TPFPSaoK/ffAnwb9GK +0N3Oh6AQu6ZjAudSvo8ppTEF4RnXIP8Pi0Tzy3SmvQLasNOKv7YxMAoGCCqGSM49 +BAMCA0cAMEQCIA/TMei9Djg/MqZsRDE+iEVWGjhrp3AzskFa8+pQXrPrAiAazMme +PARDL6NyRB9t/yu/D1ivho/YwD/7s80UJrdQ6w== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIBwDCCAWagAwIBAgIBATAKBggqhkjOPQQDAjA3MRAwDgYDVQQKDAdTb21lT3Jn +MQ0wCwYDVQQLDARUZXN0MRQwEgYDVQQDDAtUZXN0IFJvb3RDQTAeFw0yNTAzMDQx +MTA1MThaFw0yNzEyMjMxMTA1MThaMDcxEDAOBgNVBAoMB1NvbWVPcmcxDTALBgNV +BAsMBFRlc3QxFDASBgNVBAMMC1Rlc3QgUm9vdENBMFkwEwYHKoZIzj0CAQYIKoZI +zj0DAQcDQgAEBFUk0epqqkErED/dVSnxpUqLtIwJso7jysocYt7YHORcAN1vA32F +hopjFFjqW3uJwNqyW92t27sL/6jMS+YDFaNjMGEwHQYDVR0OBBYEFPNF4anpKL4C +n3PNj9DRRj0FgJNRMB8GA1UdIwQYMBaAFPNF4anpKL4Cn3PNj9DRRj0FgJNRMBIG +A1UdEwEB/wQIMAYBAf8CAQEwCwYDVR0PBAQDAgEGMAoGCCqGSM49BAMCA0gAMEUC +IAN7nh6b0Xele60l5u+di/T8sYNogZAMZX8/xH19uB5ZAiEA+XIQAu2ASRE3ZIIH +Lh4X5Z39xEGH8vVyCyLhBXac6KE= +-----END CERTIFICATE----- diff --git a/test-files/generate-cert.sh b/test-files/generate-cert.sh new file mode 100755 index 0000000..9ff0c98 --- /dev/null +++ b/test-files/generate-cert.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# Create CA private key (provide a password for the key): +openssl ecparam -name prime256v1 -genkey -noout -out ca_ec.key + +# Create CA certificate (provide suitable input when asked): +openssl req -x509 -new -nodes -key ca_ec.key -sha256 -days 1024 -set_serial 1 -out ca_ec.pem -subj "/O=SomeOrg/OU=Test/CN=Test RootCA" -config ./test_openssl.cnf + +# Print the CA +openssl x509 -in ca_ec.pem -text -noout + +# ## Intermediate EC cert ## +# # Generate test private keys +# openssl ecparam -name prime256v1 -genkey -noout -out intermediate_signing.key + +# # Create CSR requirements file: +# openssl req -new -key intermediate_signing.key -out intermediate_signing.csr -subj "/O=SomeOrg/OU=Test/CN=Test camera" + +# # Sign CSR +# openssl x509 -req -in intermediate_signing.csr -CA ca_ec.pem -CAkey ca_ec.key -CAcreateserial -out intermediate_signing.crt -days 365 -sha256 -extensions req_ext + +# # Print signed certificate +# openssl x509 -in intermediate_signing.crt -text -noout + +# # Verify certificate +# openssl verify -verbose -CAfile ca_ec.pem intermediate_signing.crt + +## EC ## +# Create CSR requirements file: +# openssl req -new -key ec_signing.key -out ec_signing.csr -subj "/O=SomeOrg/OU=Test/CN=Test camera" +openssl req -new -key private_ecdsa_key.pem -out ec_signing.csr -subj "/O=SomeOrg/OU=Test/CN=Test camera" + +# Sign CSR +openssl x509 -req -in ec_signing.csr -CA ca_ec.pem -CAkey ca_ec.key -CAcreateserial -out ec_signing.crt -days 365 -sha256 -extensions req_ext +# openssl x509 -req -in ec_signing.csr -CA intermediate_signing.crt -CAkey intermediate_signing.key -CAcreateserial -out ec_signing.crt -days 365 -sha256 -extensions req_ext + +# Print signed certificate +openssl x509 -in ec_signing.crt -text -noout + +# Verify certificate +openssl verify -verbose -CAfile ca_ec.pem ec_signing.crt +# openssl verify -verbose -CAfile intermediate_signing.crt ec_signing.crt + +# Concatenate certificates +cat ec_signing.crt ca_ec.pem > cert_chain.pem +# cat ec_signing.crt intermediate_signing.crt ca_ec.pem > cert_chain.pem diff --git a/test-files/private_ecdsa_key.pem b/test-files/private_ecdsa_key.pem new file mode 100644 index 0000000..e5bcacf --- /dev/null +++ b/test-files/private_ecdsa_key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgQtKsG+aYuzLV9H1e +xuPZ4KbclAF4vjQW88aPzisfcX6hRANCAAQNWFD88M9YY2Ru/4TPFPSaoK/ffAnw +b9GK0N3Oh6AQu6ZjAudSvo8ppTEF4RnXIP8Pi0Tzy3SmvQLasNOKv7Yx +-----END PRIVATE KEY----- diff --git a/test-files/signed_test_h264.mp4 b/test-files/signed_test_h264.mp4 index d35b8bf..baa847e 100644 Binary files a/test-files/signed_test_h264.mp4 and b/test-files/signed_test_h264.mp4 differ diff --git a/test-files/test_openssl.cnf b/test-files/test_openssl.cnf new file mode 100644 index 0000000..83b2806 --- /dev/null +++ b/test-files/test_openssl.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 = ./demoCA # 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/newcerts # 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= 30 # 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 = Internet Widgits Pty Ltd + +# 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 = + +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,pathlen:1 + +# 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