summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorStephan Wurm <atomisirsi@gsklan.de>2023-08-09 09:07:46 +0200
committerTomas Mraz <tomas@openssl.org>2024-04-09 20:13:31 +0200
commit8120223773d4c707dd43d9cc42a7fcab19609813 (patch)
treed6ba640c8b11135d9c6f214a507bbcbad744804f /apps
parent4514e02cdfc96589d5e8ab0a08942fafa8e418ae (diff)
apps: ca,req,x509: Add explicit start and end dates options
- Added options `-not_before` (start date) and `-not-after` (end date) for explicit setting of the validity period of a certificate in the apps `ca`, `req` and `x509` - The new options accept time strings or "today" - In app `ca`, use the new options as aliases of the already existing options `-startdate` and `-enddate` - When used in apps `req` and `x509`, the end date must be >= the start date, in app `ca` end date < start date is also accepted - In any case, `-not-after` overrides the `-days` option - Added helper function `check_cert_time_string` to validate given certificate time strings - Use the new helper function in apps `ca`, `req` and `x509` - Moved redundant code for time string checking into `set_cert_times` helper function. - Added tests for explicit start and end dates in apps `req` and `x509` - test: Added auxiliary functions for parsing fields from `-text` formatted output to `tconversion.pl` - CHANGES: Added to new section 3.4 Signed-off-by: Stephan Wurm <atomisirsi@gsklan.de> Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/21716)
Diffstat (limited to 'apps')
-rw-r--r--apps/ca.c32
-rw-r--r--apps/include/apps.h6
-rw-r--r--apps/lib/apps.c41
-rw-r--r--apps/req.c34
-rw-r--r--apps/x509.c31
5 files changed, 105 insertions, 39 deletions
diff --git a/apps/ca.c b/apps/ca.c
index e12a8c2370..d6dd26a413 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -150,7 +150,7 @@ typedef enum OPTION_choice {
OPT_IN, OPT_INFORM, OPT_OUT, OPT_DATEOPT, OPT_OUTDIR, OPT_VFYOPT,
OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN,
OPT_GENCRL, OPT_MSIE_HACK, OPT_CRL_LASTUPDATE, OPT_CRL_NEXTUPDATE,
- OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
+ OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, OPT_NOT_BEFORE, OPT_NOT_AFTER,
OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID,
OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS,
OPT_RAND_SERIAL, OPT_QUIET,
@@ -199,10 +199,13 @@ const OPTIONS ca_options[] = {
"Always create a random serial; do not store it"},
{"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
"Deprecated; multi-valued RDNs support is always on."},
- {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"},
+ {"startdate", OPT_STARTDATE, 's',
+ "[CC]YYMMDDHHMMSSZ value for notBefore certificate field"},
+ {"not_before", OPT_NOT_BEFORE, 's', "An alias for -startdate"},
{"enddate", OPT_ENDDATE, 's',
- "YYMMDDHHMMSSZ cert notAfter (overrides -days)"},
- {"days", OPT_DAYS, 'p', "Number of days to certify the cert for"},
+ "[CC]YYMMDDHHMMSSZ value for notAfter certificate field, overrides -days"},
+ {"not_after", OPT_NOT_AFTER, 's', "An alias for -enddate"},
+ {"days", OPT_DAYS, 'p', "Number of days from today to certify the cert for"},
{"extensions", OPT_EXTENSIONS, 's',
"Extension section (override value in config file)"},
{"extfile", OPT_EXTFILE, '<',
@@ -359,9 +362,11 @@ opthelp:
/* obsolete */
break;
case OPT_STARTDATE:
+ case OPT_NOT_BEFORE:
startdate = opt_arg();
break;
case OPT_ENDDATE:
+ case OPT_NOT_AFTER:
enddate = opt_arg();
break;
case OPT_DAYS:
@@ -874,22 +879,8 @@ end_of_options:
if (startdate == NULL)
startdate =
app_conf_try_string(conf, section, ENV_DEFAULT_STARTDATE);
- if (startdate != NULL && !ASN1_TIME_set_string_X509(NULL, startdate)) {
- BIO_printf(bio_err,
- "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
- goto end;
- }
- if (startdate == NULL)
- startdate = "today";
-
if (enddate == NULL)
enddate = app_conf_try_string(conf, section, ENV_DEFAULT_ENDDATE);
- if (enddate != NULL && !ASN1_TIME_set_string_X509(NULL, enddate)) {
- BIO_printf(bio_err,
- "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
- goto end;
- }
-
if (days == 0) {
if (!app_conf_try_number(conf, section, ENV_DEFAULT_DAYS, &days))
days = 0;
@@ -898,6 +889,9 @@ end_of_options:
BIO_printf(bio_err, "cannot lookup how many days to certify for\n");
goto end;
}
+ if (days != 0 && enddate != NULL)
+ BIO_printf(bio_err,
+ "Warning: -enddate or -not_after option overriding -days option\n");
if (rand_ser) {
if ((serial = BN_new()) == NULL || !rand_serial(serial, NULL)) {
@@ -1671,7 +1665,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
goto end;
}
- if (!set_cert_times(ret, startdate, enddate, days))
+ if (!set_cert_times(ret, startdate, enddate, days, 0))
goto end;
if (enddate != NULL) {
diff --git a/apps/include/apps.h b/apps/include/apps.h
index a1b2cbbdc3..f1d5fccc41 100644
--- a/apps/include/apps.h
+++ b/apps/include/apps.h
@@ -82,8 +82,12 @@ int has_stdin_waiting(void);
# endif
void corrupt_signature(const ASN1_STRING *signature);
+
+/* Helpers for setting X509v3 certificate fields notBefore and notAfter */
+int check_cert_time_string(const char *time, const char *desc);
int set_cert_times(X509 *x, const char *startdate, const char *enddate,
- int days);
+ int days, int strict_compare_times);
+
int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate);
int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate,
long days, long hours, long secs);
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index e04530ff44..c87f0f02f1 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -3275,23 +3275,54 @@ void corrupt_signature(const ASN1_STRING *signature)
s[signature->length - 1] ^= 0x1;
}
+int check_cert_time_string(const char *time, const char *desc)
+{
+ if (time == NULL || strcmp(time, "today") == 0
+ || ASN1_TIME_set_string_X509(NULL, time))
+ return 1;
+ BIO_printf(bio_err,
+ "%s is invalid, it should be \"today\" or have format [CC]YYMMDDHHMMSSZ\n",
+ desc);
+ return 0;
+}
+
int set_cert_times(X509 *x, const char *startdate, const char *enddate,
- int days)
+ int days, int strict_compare_times)
{
+ if (!check_cert_time_string(startdate, "start date"))
+ return 0;
+ if (!check_cert_time_string(enddate, "end date"))
+ return 0;
if (startdate == NULL || strcmp(startdate, "today") == 0) {
- if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL)
+ if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) {
+ BIO_printf(bio_err, "Error setting notBefore certificate field\n");
return 0;
+ }
} else {
- if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate))
+ if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) {
+ BIO_printf(bio_err, "Error setting notBefore certificate field\n");
return 0;
+ }
+ }
+ if (enddate != NULL && strcmp(enddate, "today") == 0) {
+ enddate = NULL;
+ days = 0;
}
if (enddate == NULL) {
- if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL)
- == NULL)
+ if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) == NULL) {
+ BIO_printf(bio_err, "Error setting notAfter certificate field\n");
return 0;
+ }
} else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) {
+ BIO_printf(bio_err, "Error setting notAfter certificate field\n");
return 0;
}
+ if (ASN1_TIME_compare(X509_get0_notAfter(x), X509_get0_notBefore(x)) < 0) {
+ BIO_printf(bio_err, "%s: end date before start date\n",
+ strict_compare_times ? "Error" : "Warning");
+ if (strict_compare_times)
+ return 0;
+ }
return 1;
}
diff --git a/apps/req.c b/apps/req.c
index b54a489722..dfa8319156 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -43,7 +43,7 @@
#define DEFAULT_KEY_LENGTH 2048
#define MIN_KEY_LENGTH 512
-#define DEFAULT_DAYS 30 /* default cert validity period in days */
+#define DEFAULT_DAYS 30 /* default certificate validity period in days */
#define UNSET_DAYS -2 /* -1 may be used for testing expiration checks */
#define EXT_COPY_UNSET -1
@@ -87,7 +87,7 @@ typedef enum OPTION_choice {
OPT_VERIFY, OPT_NOENC, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT,
OPT_X509, OPT_X509V1, OPT_CA, OPT_CAKEY,
- OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL,
+ OPT_MULTIVALUE_RDN, OPT_NOT_BEFORE, OPT_NOT_AFTER, OPT_DAYS, OPT_SET_SERIAL,
OPT_COPY_EXTENSIONS, OPT_EXTENSIONS, OPT_REQEXTS, OPT_ADDEXT,
OPT_PRECERT, OPT_MD,
OPT_SECTION, OPT_QUIET,
@@ -127,7 +127,11 @@ const OPTIONS req_options[] = {
"Print the subject of the output request or cert"},
{"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
"Deprecated; multi-valued RDNs support is always on."},
- {"days", OPT_DAYS, 'p', "Number of days cert is valid for"},
+ {"not_before", OPT_NOT_BEFORE, 's',
+ "[CC]YYMMDDHHMMSSZ value for notBefore certificate field"},
+ {"not_after", OPT_NOT_AFTER, 's',
+ "[CC]YYMMDDHHMMSSZ value for notAfter certificate field, overrides -days"},
+ {"days", OPT_DAYS, 'p', "Number of days certificate is valid for"},
{"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
{"copy_extensions", OPT_COPY_EXTENSIONS, 's',
"copy extensions from request when using -x509"},
@@ -259,6 +263,7 @@ int req_main(int argc, char **argv)
char *template = default_config_file, *keyout = NULL;
const char *keyalg = NULL;
OPTION_CHOICE o;
+ char *not_before = NULL, *not_after = NULL;
int days = UNSET_DAYS;
int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0, progress = 1;
int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF;
@@ -423,9 +428,15 @@ int req_main(int argc, char **argv)
case OPT_CAKEY:
CAkeyfile = opt_arg();
break;
+ case OPT_NOT_BEFORE:
+ not_before = opt_arg();
+ break;
+ case OPT_NOT_AFTER:
+ not_after = opt_arg();
+ break;
case OPT_DAYS:
days = atoi(opt_arg());
- if (days < -1) {
+ if (days <= UNSET_DAYS) {
BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
prog);
goto end;
@@ -494,9 +505,13 @@ int req_main(int argc, char **argv)
if (!gen_x509) {
if (days != UNSET_DAYS)
- BIO_printf(bio_err, "Ignoring -days without -x509; not generating a certificate\n");
+ BIO_printf(bio_err, "Warning: Ignoring -days without -x509; not generating a certificate\n");
+ if (not_before != NULL)
+ BIO_printf(bio_err, "Warning: Ignoring -not_before without -x509; not generating a certificate\n");
+ if (not_after != NULL)
+ BIO_printf(bio_err, "Warning: Ignoring -not_after without -x509; not generating a certificate\n");
if (ext_copy == EXT_COPY_NONE)
- BIO_printf(bio_err, "Ignoring -copy_extensions 'none' when -x509 is not given\n");
+ BIO_printf(bio_err, "Warning: Ignoring -copy_extensions 'none' when -x509 is not given\n");
}
if (infile == NULL) {
if (gen_x509)
@@ -802,10 +817,11 @@ int req_main(int argc, char **argv)
if (!X509_set_issuer_name(new_x509, issuer))
goto end;
- if (days == UNSET_DAYS) {
+ if (days == UNSET_DAYS)
days = DEFAULT_DAYS;
- }
- if (!set_cert_times(new_x509, NULL, NULL, days))
+ else if (not_after != NULL)
+ BIO_printf(bio_err,"Warning: -not_after option overriding -days option\n");
+ if (!set_cert_times(new_x509, not_before, not_after, days, 1))
goto end;
if (!X509_set_subject_name(new_x509, n_subj))
goto end;
diff --git a/apps/x509.c b/apps/x509.c
index d96e7819b2..cd5b7bf796 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -29,8 +29,8 @@
#undef POSTFIX
#define POSTFIX ".srl"
-#define DEFAULT_DAYS 30 /* default cert validity period in days */
-#define UNSET_DAYS -2 /* -1 is used for testing expiration checks */
+#define DEFAULT_DAYS 30 /* default certificate validity period in days */
+#define UNSET_DAYS -2 /* -1 may be used for testing expiration checks */
#define EXT_COPY_UNSET -1
static int callb(int ok, X509_STORE_CTX *ctx);
@@ -54,6 +54,7 @@ typedef enum OPTION_choice {
OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
OPT_SUBJECT_HASH_OLD, OPT_ISSUER_HASH_OLD, OPT_COPY_EXTENSIONS,
OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
+ OPT_NOT_BEFORE, OPT_NOT_AFTER,
OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT
} OPTION_CHOICE;
@@ -135,6 +136,10 @@ const OPTIONS x509_options[] = {
"Serial number to use, overrides -CAserial"},
{"next_serial", OPT_NEXT_SERIAL, '-',
"Increment current certificate serial number"},
+ {"not_before", OPT_NOT_BEFORE, 's',
+ "[CC]YYMMDDHHMMSSZ value for notBefore certificate field"},
+ {"not_after", OPT_NOT_AFTER, 's',
+ "[CC]YYMMDDHHMMSSZ value for notAfter certificate field, overrides -days"},
{"days", OPT_DAYS, 'n',
"Number of days until newly generated certificate expires - default 30"},
{"preserve_dates", OPT_PRESERVE_DATES, '-',
@@ -279,7 +284,7 @@ int x509_main(int argc, char **argv)
char *ext_names = NULL;
char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
char *infile = NULL, *outfile = NULL, *privkeyfile = NULL, *CAfile = NULL;
- char *prog;
+ char *prog, *not_before = NULL, *not_after = NULL;
int days = UNSET_DAYS; /* not explicitly set */
int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0;
int CAformat = FORMAT_UNDEF, CAkeyformat = FORMAT_UNDEF;
@@ -376,9 +381,15 @@ int x509_main(int argc, char **argv)
if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
goto opthelp;
break;
+ case OPT_NOT_BEFORE:
+ not_before = opt_arg();
+ break;
+ case OPT_NOT_AFTER:
+ not_after = opt_arg();
+ break;
case OPT_DAYS:
days = atoi(opt_arg());
- if (days < -1) {
+ if (days <= UNSET_DAYS) {
BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
prog);
goto err;
@@ -610,12 +621,22 @@ int x509_main(int argc, char **argv)
if (!opt_check_md(digest))
goto opthelp;
+ if (preserve_dates && not_before != NULL) {
+ BIO_printf(bio_err, "Cannot use -preserve_dates with -not_before option\n");
+ goto err;
+ }
+ if (preserve_dates && not_after != NULL) {
+ BIO_printf(bio_err, "Cannot use -preserve_dates with -not_after option\n");
+ goto err;
+ }
if (preserve_dates && days != UNSET_DAYS) {
BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n");
goto err;
}
if (days == UNSET_DAYS)
days = DEFAULT_DAYS;
+ else if (not_after != NULL)
+ BIO_printf(bio_err, "Warning: -not_after option overriding -days option\n");
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
@@ -837,7 +858,7 @@ int x509_main(int argc, char **argv)
goto end;
if (reqfile || newcert || privkey != NULL || CAfile != NULL) {
- if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
+ if (!preserve_dates && !set_cert_times(x, not_before, not_after, days, 1))
goto end;
if (fissu != NULL) {
if (!X509_set_issuer_name(x, fissu))