summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2012-03-18 11:31:44 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-03-18 11:43:01 +0100
commit1dd7d7955774b3384c7d6d2c38aa87a85a9cfba1 (patch)
treef1a22617b03cb59fb62a2890c6385894496f9a4b
parent33162437d298621b441ab074e295762f833fe859 (diff)
downloadgnutls-1dd7d7955774b3384c7d6d2c38aa87a85a9cfba1.tar.gz
Added gnutls_x509_crt_set_private_key_usage_period() and
gnutls_x509_crt_get_private_key_usage_period(). The time stored in generated certificates is now GeneralizedTime.
-rw-r--r--NEWS9
-rw-r--r--lib/includes/gnutls/x509.h12
-rw-r--r--lib/libgnutls.map3
-rw-r--r--lib/pkix.asn4
-rw-r--r--lib/pkix_asn1_tab.c5
-rw-r--r--lib/x509/common.c148
-rw-r--r--lib/x509/common.h4
-rw-r--r--lib/x509/crl.c6
-rw-r--r--lib/x509/crl_write.c6
-rw-r--r--lib/x509/crq.c134
-rw-r--r--lib/x509/output.c58
-rw-r--r--lib/x509/x509.c87
-rw-r--r--lib/x509/x509_write.c76
-rw-r--r--tests/cert-tests/template-test.pem34
14 files changed, 481 insertions, 105 deletions
diff --git a/NEWS b/NEWS
index e212072c1e..182951b456 100644
--- a/NEWS
+++ b/NEWS
@@ -7,9 +7,14 @@ See the end for copying conditions.
** certtool: Avoid a Y2K38 bug when generating certificates.
Patch by Robert Millan.
-** API and ABI modifications:
-No changes since last version.
+** libgnutls: Time in generated certificates is stored
+as GeneralizedTime instead of UTCTime (which only stores
+2 digits of a year).
+** API and ABI modifications:
+gnutls_x509_crt_set_private_key_usage_period: Added
+gnutls_x509_crt_get_private_key_usage_period: Added
+gnutls_x509_crq_set_private_key_usage_period: Added
* Version 3.0.17 (released 2012-03-17)
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index ac6de53595..859966b8d2 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -123,6 +123,9 @@ extern "C"
int gnutls_x509_crt_export (gnutls_x509_crt_t cert,
gnutls_x509_crt_fmt_t format,
void *output_data, size_t * output_data_size);
+ int gnutls_x509_crt_get_private_key_usage_period (gnutls_x509_crt_t cert, time_t* activation, time_t* expiration,
+ unsigned int *critical);
+
int gnutls_x509_crt_get_issuer_dn (gnutls_x509_crt_t cert, char *buf,
size_t * buf_size);
int gnutls_x509_crt_get_issuer_dn_oid (gnutls_x509_crt_t cert, int indx,
@@ -151,6 +154,9 @@ extern "C"
unsigned char *output_data,
size_t * output_data_size);
+ int gnutls_x509_crt_set_private_key_usage_period (gnutls_x509_crt_t crt,
+ time_t activation,
+ time_t expiration);
int gnutls_x509_crt_set_authority_key_id (gnutls_x509_crt_t cert,
const void *id, size_t id_size);
int gnutls_x509_crt_get_authority_key_id (gnutls_x509_crt_t cert,
@@ -810,6 +816,9 @@ extern "C"
const gnutls_datum_t * data,
gnutls_x509_crt_fmt_t format);
+ int gnutls_x509_crq_get_private_key_usage_period (gnutls_x509_crq_t cert, time_t* activation, time_t* expiration,
+ unsigned int *critical);
+
int gnutls_x509_crq_get_dn (gnutls_x509_crq_t crq, char *buf,
size_t * sizeof_buf);
int gnutls_x509_crq_get_dn_oid (gnutls_x509_crq_t crq, int indx,
@@ -850,6 +859,9 @@ extern "C"
int gnutls_x509_crt_set_crq_extensions (gnutls_x509_crt_t crt,
gnutls_x509_crq_t crq);
+ int gnutls_x509_crq_set_private_key_usage_period (gnutls_x509_crq_t crq,
+ time_t activation,
+ time_t expiration);
int gnutls_x509_crq_set_key_rsa_raw (gnutls_x509_crq_t crq,
const gnutls_datum_t * m,
const gnutls_datum_t * e);
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 519d5fcbd7..bd665c195d 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -781,6 +781,9 @@ GNUTLS_3_0_0 {
gnutls_tdb_set_verify_func;
gnutls_tdb_deinit;
gnutls_x509_crt_set_authority_info_access;
+ gnutls_x509_crt_get_private_key_usage_period;
+ gnutls_x509_crt_set_private_key_usage_period;
+ gnutls_x509_crq_set_private_key_usage_period;
} GNUTLS_2_12;
GNUTLS_PRIVATE {
diff --git a/lib/pkix.asn b/lib/pkix.asn
index e0121c6d32..59919aecba 100644
--- a/lib/pkix.asn
+++ b/lib/pkix.asn
@@ -15,6 +15,10 @@ id-pkix OBJECT IDENTIFIER ::=
-- authority key identifier OID and syntax
+PrivateKeyUsagePeriod ::= SEQUENCE {
+ notBefore [0] GeneralizedTime OPTIONAL,
+ notAfter [1] GeneralizedTime OPTIONAL }
+
AuthorityKeyIdentifier ::= SEQUENCE {
keyIdentifier [0] KeyIdentifier OPTIONAL,
authorityCertIssuer [1] GeneralNames OPTIONAL,
diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c
index 159bba5fcd..d5b820cb6b 100644
--- a/lib/pkix_asn1_tab.c
+++ b/lib/pkix_asn1_tab.c
@@ -15,6 +15,11 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[] = {
{ "security", 1073741825, "5"},
{ "mechanisms", 1073741825, "5"},
{ "pkix", 1, "7"},
+ { "PrivateKeyUsagePeriod", 1610612741, NULL },
+ { "notBefore", 1619025937, NULL },
+ { NULL, 4104, "0"},
+ { "notAfter", 545284113, NULL },
+ { NULL, 4104, "1"},
{ "AuthorityKeyIdentifier", 1610612741, NULL },
{ "keyIdentifier", 1610637314, "KeyIdentifier"},
{ NULL, 4104, "0"},
diff --git a/lib/x509/common.c b/lib/x509/common.c
index bfb6aa66c2..052eb7cd73 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -486,11 +486,10 @@ mktime_utc (const struct fake_tm *tm)
* and year is given. Returns a time_t date.
*/
static time_t
-_gnutls_x509_time2gtime (const char *ttime, int year)
+time2gtime (const char *ttime, int year)
{
char xx[4];
struct fake_tm etime;
- time_t ret;
if (strlen (ttime) < 8)
{
@@ -544,9 +543,7 @@ _gnutls_x509_time2gtime (const char *ttime, int year)
else
etime.tm_sec = 0;
- ret = mktime_utc (&etime);
-
- return ret;
+ return mktime_utc (&etime);
}
@@ -557,7 +554,7 @@ _gnutls_x509_time2gtime (const char *ttime, int year)
* (seconds are optional)
*/
static time_t
-_gnutls_x509_utcTime2gtime (const char *ttime)
+utcTime2gtime (const char *ttime)
{
char xx[3];
int year;
@@ -579,35 +576,7 @@ _gnutls_x509_utcTime2gtime (const char *ttime)
else
year += 2000;
- return _gnutls_x509_time2gtime (ttime, year);
-}
-
-/* returns a time value that contains the given time.
- * The given time is expressed as:
- * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)
- */
-static int
-_gnutls_x509_gtime2utcTime (time_t gtime, char *str_time, size_t str_time_size)
-{
- size_t ret;
- struct tm _tm;
-
- if (!gmtime_r (&gtime, &_tm))
- {
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
- }
-
- ret = strftime (str_time, str_time_size, "%y%m%d%H%M%SZ", &_tm);
- if (!ret)
- {
- gnutls_assert ();
- return GNUTLS_E_SHORT_MEMORY_BUFFER;
- }
-
-
- return 0;
-
+ return time2gtime (ttime, year);
}
/* returns a time_t value that contains the given time.
@@ -641,60 +610,89 @@ _gnutls_x509_generalTime2gtime (const char *ttime)
year = atoi (xx);
ttime += 4;
- return _gnutls_x509_time2gtime (ttime, year);
+ return time2gtime (ttime, year);
+}
+
+static int
+gtime2generalTime (time_t gtime, char *str_time, size_t str_time_size)
+{
+ size_t ret;
+ struct tm _tm;
+ if (!gmtime_r (&gtime, &_tm))
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ ret = strftime (str_time, str_time_size, "%Y%m%d%H%M%SZ", &_tm);
+ if (!ret)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+
+ return 0;
}
+
/* Extracts the time in time_t from the ASN1_TYPE given. When should
* be something like "tbsCertList.thisUpdate".
*/
#define MAX_TIME 64
time_t
-_gnutls_x509_get_time (ASN1_TYPE c2, const char *when)
+_gnutls_x509_get_time (ASN1_TYPE c2, const char *when, int nochoice)
{
char ttime[MAX_TIME];
char name[128];
time_t c_time = (time_t) - 1;
int len, result;
- _gnutls_str_cpy (name, sizeof (name), when);
-
len = sizeof (ttime) - 1;
- if ((result = asn1_read_value (c2, name, ttime, &len)) < 0)
+ result = asn1_read_value (c2, when, ttime, &len);
+ if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return (time_t) (-1);
}
- /* CHOICE */
- if (strcmp (ttime, "generalTime") == 0)
+ if (nochoice != 0)
{
-
- _gnutls_str_cat (name, sizeof (name), ".generalTime");
- len = sizeof (ttime) - 1;
- result = asn1_read_value (c2, name, ttime, &len);
- if (result == ASN1_SUCCESS)
- c_time = _gnutls_x509_generalTime2gtime (ttime);
+ c_time = _gnutls_x509_generalTime2gtime (ttime);
}
else
- { /* UTCTIME */
-
- _gnutls_str_cat (name, sizeof (name), ".utcTime");
- len = sizeof (ttime) - 1;
- result = asn1_read_value (c2, name, ttime, &len);
- if (result == ASN1_SUCCESS)
- c_time = _gnutls_x509_utcTime2gtime (ttime);
- }
+ {
+ _gnutls_str_cpy (name, sizeof (name), when);
- /* We cannot handle dates after 2031 in 32 bit machines.
- * a time_t of 64bits has to be used.
- */
+ /* CHOICE */
+ if (strcmp (ttime, "generalTime") == 0)
+ {
+ _gnutls_str_cat (name, sizeof (name), ".generalTime");
+ len = sizeof (ttime) - 1;
+ result = asn1_read_value (c2, name, ttime, &len);
+ if (result == ASN1_SUCCESS)
+ c_time = _gnutls_x509_generalTime2gtime (ttime);
+ }
+ else
+ { /* UTCTIME */
+ _gnutls_str_cat (name, sizeof (name), ".utcTime");
+ len = sizeof (ttime) - 1;
+ result = asn1_read_value (c2, name, ttime, &len);
+ if (result == ASN1_SUCCESS)
+ c_time = utcTime2gtime (ttime);
+ }
- if (result != ASN1_SUCCESS)
- {
- gnutls_assert ();
- return (time_t) (-1);
+ /* We cannot handle dates after 2031 in 32 bit machines.
+ * a time_t of 64bits has to be used.
+ */
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ return (time_t) (-1);
+ }
}
+
return c_time;
}
@@ -702,28 +700,42 @@ _gnutls_x509_get_time (ASN1_TYPE c2, const char *when)
* be something like "tbsCertList.thisUpdate".
*/
int
-_gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim)
+_gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim, int nochoice)
{
char str_time[MAX_TIME];
char name[128];
int result, len;
+ if (nochoice != 0)
+ {
+ result = gtime2generalTime( tim, str_time, sizeof(str_time));
+ if (result < 0)
+ return gnutls_assert_val(result);
+
+ len = strlen (str_time);
+ result = asn1_write_value(c2, where, str_time, len);
+ if (result != ASN1_SUCCESS)
+ return gnutls_assert_val(_gnutls_asn2err (result));
+
+ return 0;
+ }
+
_gnutls_str_cpy (name, sizeof (name), where);
- if ((result = asn1_write_value (c2, name, "utcTime", 1)) < 0)
+ if ((result = asn1_write_value (c2, name, "generalTime", 1)) < 0)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
- result = _gnutls_x509_gtime2utcTime (tim, str_time, sizeof (str_time));
+ result = gtime2generalTime (tim, str_time, sizeof (str_time));
if (result < 0)
{
gnutls_assert ();
return result;
}
- _gnutls_str_cat (name, sizeof (name), ".utcTime");
+ _gnutls_str_cat (name, sizeof (name), ".generalTime");
len = strlen (str_time);
result = asn1_write_value (c2, name, str_time, len);
@@ -985,7 +997,7 @@ cleanup:
}
/* DER Encodes the src ASN1_TYPE and stores it to
- * the given datum. If str is non null then the data are encoded as
+ * the given datum. If str is non zero then the data are encoded as
* an OCTET STRING.
*/
int
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 59b661a1eb..1d7116ccb6 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -66,7 +66,7 @@
#define ASN1_NULL "\x05\x00"
#define ASN1_NULL_SIZE 2
-int _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim);
+int _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim, int general);
int _gnutls_x509_decode_octet_string (const char *string_type,
const uint8_t * der, size_t der_size,
@@ -82,7 +82,7 @@ const char *_gnutls_x509_oid2asn_string (const char *oid);
int _gnutls_x509_oid_data_choice (const char *OID);
int _gnutls_x509_oid_data_printable (const char *OID);
-time_t _gnutls_x509_get_time (ASN1_TYPE c2, const char *when);
+time_t _gnutls_x509_get_time (ASN1_TYPE c2, const char *when, int general);
gnutls_x509_subject_alt_name_t _gnutls_x509_san_find_type (char *str_type);
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index 3a514c98cd..cfd4b9305c 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -416,7 +416,7 @@ gnutls_x509_crl_get_this_update (gnutls_x509_crl_t crl)
return (time_t) - 1;
}
- return _gnutls_x509_get_time (crl->crl, "tbsCertList.thisUpdate");
+ return _gnutls_x509_get_time (crl->crl, "tbsCertList.thisUpdate", 0);
}
/**
@@ -438,7 +438,7 @@ gnutls_x509_crl_get_next_update (gnutls_x509_crl_t crl)
return (time_t) - 1;
}
- return _gnutls_x509_get_time (crl->crl, "tbsCertList.nextUpdate");
+ return _gnutls_x509_get_time (crl->crl, "tbsCertList.nextUpdate", 0);
}
/**
@@ -524,7 +524,7 @@ gnutls_x509_crl_get_crt_serial (gnutls_x509_crl_t crl, int indx,
if (t)
{
- *t = _gnutls_x509_get_time (crl->crl, date_name);
+ *t = _gnutls_x509_get_time (crl->crl, date_name, 0);
}
return 0;
diff --git a/lib/x509/crl_write.c b/lib/x509/crl_write.c
index 9964551271..ec758ea806 100644
--- a/lib/x509/crl_write.c
+++ b/lib/x509/crl_write.c
@@ -174,7 +174,7 @@ gnutls_x509_crl_set_this_update (gnutls_x509_crl_t crl, time_t act_time)
return GNUTLS_E_INVALID_REQUEST;
}
- return _gnutls_x509_set_time (crl->crl, "tbsCertList.thisUpdate", act_time);
+ return _gnutls_x509_set_time (crl->crl, "tbsCertList.thisUpdate", act_time, 0);
}
/**
@@ -195,7 +195,7 @@ gnutls_x509_crl_set_next_update (gnutls_x509_crl_t crl, time_t exp_time)
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
- return _gnutls_x509_set_time (crl->crl, "tbsCertList.nextUpdate", exp_time);
+ return _gnutls_x509_set_time (crl->crl, "tbsCertList.nextUpdate", exp_time, 0);
}
/**
@@ -244,7 +244,7 @@ gnutls_x509_crl_set_crt_serial (gnutls_x509_crl_t crl,
ret =
_gnutls_x509_set_time (crl->crl,
"tbsCertList.revokedCertificates.?LAST.revocationDate",
- revocation_time);
+ revocation_time, 0);
if (ret < 0)
{
gnutls_assert ();
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index 4873d69087..0a2e13de80 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -165,6 +165,71 @@ cleanup:
return result;
}
+/**
+ * gnutls_x509_crq_get_private_key_usage_period:
+ * @cert: should contain a #gnutls_x509_crq_t structure
+ * @activation: The activation time
+ * @expiration: The expiration time
+ * @critical: the extension status
+ *
+ * This function will return the expiration and activation
+ * times of the private key of the certificate.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
+ * if the extension is not present, otherwise a negative error value.
+ **/
+int
+gnutls_x509_crq_get_private_key_usage_period (gnutls_x509_crq_t crq, time_t* activation, time_t* expiration,
+ unsigned int *critical)
+{
+ int result, ret;
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+ uint8_t buf[128];
+ size_t buf_size = sizeof (buf);
+
+ if (crq == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ ret = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.16", 0,
+ buf, &buf_size, critical);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ result = asn1_create_element
+ (_gnutls_get_pkix (), "PKIX1.PrivateKeyUsagePeriod", &c2);
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ ret = _gnutls_asn2err (result);
+ goto cleanup;
+ }
+
+ result = asn1_der_decoding (&c2, buf, buf_size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ ret = _gnutls_asn2err (result);
+ goto cleanup;
+ }
+
+ if (activation)
+ *activation = _gnutls_x509_get_time (c2,
+ "notBefore", 1);
+
+ if (expiration)
+ *expiration = _gnutls_x509_get_time (c2,
+ "notAfter", 1);
+
+ ret = 0;
+
+cleanup:
+ asn1_delete_structure (&c2);
+
+ return ret;
+}
/**
@@ -2489,3 +2554,72 @@ cleanup:
return ret;
}
+/**
+ * gnutls_x509_crq_set_private_key_usage_period:
+ * @crq: a certificate of type #gnutls_x509_crq_t
+ * @activation: The activation time
+ * @expiration: The expiration time
+ *
+ * This function will set the private key usage period extension (2.5.29.16).
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_crq_set_private_key_usage_period (gnutls_x509_crq_t crq,
+ time_t activation,
+ time_t expiration)
+{
+ int result;
+ gnutls_datum_t der_data;
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+
+ if (crq == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ result =
+ asn1_create_element (_gnutls_get_pkix (), "PKIX1.PrivateKeyUsagePeriod", &c2);
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (result);
+ }
+
+ result = _gnutls_x509_set_time (c2,
+ "notBefore",
+ activation, 1);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_set_time (c2,
+ "notAfter",
+ expiration, 1);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode (c2, "", &der_data, 0);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_crq_set_extension (crq, "2.5.29.16",
+ &der_data, 0);
+
+ _gnutls_free_datum(&der_data);
+
+cleanup:
+ asn1_delete_structure (&c2);
+
+ return result;
+}
diff --git a/lib/x509/output.c b/lib/x509/output.c
index a16ec4a7da..1797b26419 100644
--- a/lib/x509/output.c
+++ b/lib/x509/output.c
@@ -438,6 +438,47 @@ print_key_usage (gnutls_buffer_st * str, const char *prefix, int type,
}
static void
+print_private_key_usage_period (gnutls_buffer_st * str, const char *prefix, int type,
+ cert_type_t cert)
+{
+ time_t activation, expiration;
+ int err;
+ char s[42];
+ struct tm t;
+ size_t max;
+
+ if (type == TYPE_CRT)
+ err = gnutls_x509_crt_get_private_key_usage_period (cert.crt, &activation, &expiration, NULL);
+ else if (type == TYPE_CRQ)
+ err = gnutls_x509_crq_get_private_key_usage_period (cert.crq, &activation, &expiration, NULL);
+ else
+ return;
+
+ if (err < 0)
+ {
+ addf (str, "error: get_private_key_usage_period: %s\n", gnutls_strerror (err));
+ return;
+ }
+
+ max = sizeof (s);
+
+ if (gmtime_r (&activation, &t) == NULL)
+ addf (str, "error: gmtime_r (%ld)\n", (unsigned long) activation);
+ else if (strftime (s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
+ addf (str, "error: strftime (%ld)\n", (unsigned long) activation);
+ else
+ addf (str, _("\t\t\tNot Before: %s\n"), s);
+
+ if (gmtime_r (&expiration, &t) == NULL)
+ addf (str, "error: gmtime_r (%ld)\n", (unsigned long) expiration);
+ else if (strftime (s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
+ addf (str, "error: strftime (%ld)\n", (unsigned long) expiration);
+ else
+ addf (str, _("\t\t\tNot After: %s\n"), s);
+
+}
+
+static void
print_crldist (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
{
char *buffer = NULL;
@@ -854,7 +895,7 @@ print_extensions (gnutls_buffer_st * str, const char *prefix, int type,
int keypurpose_idx = 0;
int ski_idx = 0;
int aki_idx = 0;
- int crldist_idx = 0;
+ int crldist_idx = 0, pkey_usage_period_idx = 0;
for (i = 0;; i++)
{
@@ -952,6 +993,21 @@ print_extensions (gnutls_buffer_st * str, const char *prefix, int type,
keyusage_idx++;
}
+ else if (strcmp (oid, "2.5.29.16") == 0)
+ {
+ if (pkey_usage_period_idx)
+ {
+ addf (str, "error: more than one private key usage period extension\n");
+ continue;
+ }
+
+ addf (str, _("%s\t\tPrivate Key Usage Period (%s):\n"), prefix,
+ critical ? _("critical") : _("not critical"));
+
+ print_private_key_usage_period (str, prefix, type, cert);
+
+ pkey_usage_period_idx++;
+ }
else if (strcmp (oid, "2.5.29.37") == 0)
{
if (keypurpose_idx)
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index fc36e89192..b9cf50cd5f 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -594,7 +594,7 @@ gnutls_x509_crt_get_activation_time (gnutls_x509_crt_t cert)
}
return _gnutls_x509_get_time (cert->cert,
- "tbsCertificate.validity.notBefore");
+ "tbsCertificate.validity.notBefore", 0);
}
/**
@@ -616,10 +616,82 @@ gnutls_x509_crt_get_expiration_time (gnutls_x509_crt_t cert)
}
return _gnutls_x509_get_time (cert->cert,
- "tbsCertificate.validity.notAfter");
+ "tbsCertificate.validity.notAfter", 0);
}
/**
+ * gnutls_x509_crt_get_private_key_usage_period:
+ * @cert: should contain a #gnutls_x509_crt_t structure
+ * @activation: The activation time
+ * @expiration: The expiration time
+ * @critical: the extension status
+ *
+ * This function will return the expiration and activation
+ * times of the private key of the certificate. It relies on
+ * the PKIX extension 2.5.29.16 being present.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
+ * if the extension is not present, otherwise a negative error value.
+ **/
+int
+gnutls_x509_crt_get_private_key_usage_period (gnutls_x509_crt_t cert, time_t* activation, time_t* expiration,
+ unsigned int *critical)
+{
+ int result, ret;
+ gnutls_datum_t der = {NULL, 0};
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+
+ if (cert == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ ret =
+ _gnutls_x509_crt_get_extension (cert, "2.5.29.16", 0, &der,
+ critical);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ if (der.size == 0 || der.data == NULL)
+ return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
+ result = asn1_create_element
+ (_gnutls_get_pkix (), "PKIX1.PrivateKeyUsagePeriod", &c2);
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ ret = _gnutls_asn2err (result);
+ goto cleanup;
+ }
+
+ result = asn1_der_decoding (&c2, der.data, der.size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ ret = _gnutls_asn2err (result);
+ goto cleanup;
+ }
+
+ if (activation)
+ *activation = _gnutls_x509_get_time (c2,
+ "notBefore", 1);
+
+ if (expiration)
+ *expiration = _gnutls_x509_get_time (c2,
+ "notAfter", 1);
+
+ ret = 0;
+
+cleanup:
+ _gnutls_free_datum(&der);
+ asn1_delete_structure (&c2);
+
+ return ret;
+}
+
+
+/**
* gnutls_x509_crt_get_serial:
* @cert: should contain a #gnutls_x509_crt_t structure
* @result: The place where the serial number will be copied
@@ -670,8 +742,8 @@ gnutls_x509_crt_get_serial (gnutls_x509_crt_t cert, void *result,
* identifier. This is obtained by the X.509 Subject Key identifier
* extension field (2.5.29.14).
*
- * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
- * negative error value.
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
+ * if the extension is not present, otherwise a negative error value.
**/
int
gnutls_x509_crt_get_subject_key_id (gnutls_x509_crt_t cert, void *ret,
@@ -815,7 +887,8 @@ _get_authority_key_id (gnutls_x509_crt_t cert, ASN1_TYPE *c2,
* @seq can be used as a counter to request them all until
* %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
*
- * Returns: Returns 0 on success, or an error code.
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
+ * if the extension is not present, otherwise a negative error value.
*
* Since: 3.0
**/
@@ -879,8 +952,8 @@ fail:
* the name and serial number of the certificate. In that case
* gnutls_x509_crt_get_authority_key_gn_serial() may be used.
*
- * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
- * negative error value.
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
+ * if the extension is not present, otherwise a negative error value.
**/
int
gnutls_x509_crt_get_authority_key_id (gnutls_x509_crt_t cert, void *id,
diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c
index e2a28c4e85..40cd55ba88 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -728,6 +728,78 @@ gnutls_x509_crt_set_proxy (gnutls_x509_crt_t crt,
}
/**
+ * gnutls_x509_crt_set_private_key_usage_period:
+ * @crt: a certificate of type #gnutls_x509_crt_t
+ * @activation: The activation time
+ * @expiration: The expiration time
+ *
+ * This function will set the private key usage period extension (2.5.29.16).
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_crt_set_private_key_usage_period (gnutls_x509_crt_t crt,
+ time_t activation,
+ time_t expiration)
+{
+ int result;
+ gnutls_datum_t der_data;
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+
+ if (crt == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ result =
+ asn1_create_element (_gnutls_get_pkix (), "PKIX1.PrivateKeyUsagePeriod", &c2);
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (result);
+ }
+
+ result = _gnutls_x509_set_time (c2,
+ "notBefore",
+ activation, 1);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_set_time (c2,
+ "notAfter",
+ expiration, 1);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode (c2, "", &der_data, 0);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_crt_set_extension (crt, "2.5.29.16",
+ &der_data, 0);
+
+ _gnutls_free_datum(&der_data);
+
+ crt->use_extensions = 1;
+
+cleanup:
+ asn1_delete_structure (&c2);
+
+ return result;
+}
+
+/**
* gnutls_x509_crt_sign2:
* @crt: a certificate of type #gnutls_x509_crt_t
* @issuer: is the certificate of the certificate issuer
@@ -828,7 +900,7 @@ gnutls_x509_crt_set_activation_time (gnutls_x509_crt_t cert, time_t act_time)
return _gnutls_x509_set_time (cert->cert,
"tbsCertificate.validity.notBefore",
- act_time);
+ act_time, 0);
}
/**
@@ -850,7 +922,7 @@ gnutls_x509_crt_set_expiration_time (gnutls_x509_crt_t cert, time_t exp_time)
return GNUTLS_E_INVALID_REQUEST;
}
return _gnutls_x509_set_time (cert->cert,
- "tbsCertificate.validity.notAfter", exp_time);
+ "tbsCertificate.validity.notAfter", exp_time, 0);
}
/**
diff --git a/tests/cert-tests/template-test.pem b/tests/cert-tests/template-test.pem
index a03f76af1f..30ddd8a219 100644
--- a/tests/cert-tests/template-test.pem
+++ b/tests/cert-tests/template-test.pem
@@ -1,22 +1,22 @@
-----BEGIN CERTIFICATE-----
-MIIDnDCCAwWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBuDELMAkGA1UEBhMCR1Ix
+MIIDoDCCAwmgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBuDELMAkGA1UEBhMCR1Ix
EjAQBgNVBAoTCUtva28gaW5jLjEXMBUGA1UECxMOc2xlZXBpbmcgZGVwdC4xDzAN
BgNVBAgTBkF0dGlraTEVMBMGA1UEAxMMQ2luZHkgTGF1cGVyMRcwFQYKCZImiZPy
LGQBARMHY2xhdXBlcjEMMAoGA1UEDBMDRHIuMQ8wDQYDVQRBEwZqYWNrYWwxHDAa
-BgkqhkiG9w0BCQEWDW5vbmVAbm9uZS5vcmcwHhcNMDcwNDIxMjIwMDAwWhcNMTQw
-NTI0MjIwMDAwWjCBuDELMAkGA1UEBhMCR1IxEjAQBgNVBAoTCUtva28gaW5jLjEX
-MBUGA1UECxMOc2xlZXBpbmcgZGVwdC4xDzANBgNVBAgTBkF0dGlraTEVMBMGA1UE
-AxMMQ2luZHkgTGF1cGVyMRcwFQYKCZImiZPyLGQBARMHY2xhdXBlcjEMMAoGA1UE
-DBMDRHIuMQ8wDQYDVQRBEwZqYWNrYWwxHDAaBgkqhkiG9w0BCQEWDW5vbmVAbm9u
-ZS5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKXGznVDhL9kngInE/ED
-Wfd5LZLtfC9QpAPxLXm5hosFfjq7RKqvhM8TmB4cSjj3My16n3LUa20msDE3cBD7
-QunYnRhlfhlJ/AWWBGiDHneGv+315RI7E/4zGJwaeh1pr0cCYHofuejP28g0MFGW
-PYyWXAC8Yd4ID7E2IX+pAOMFAgMBAAGjgbMwgbAwDwYDVR0TAQH/BAUwAwEB/zAo
-BgNVHREEITAfgQ1ub25lQG5vbmUub3JngQ53aGVyZUBub25lLm9yZzATBgNVHSUE
-DDAKBggrBgEFBQcDCTAPBgNVHQ8BAf8EBQMDBwQAMB0GA1UdDgQWBBRdQK3wzpRA
-lYt+mZQdklQiynI2XzAuBgNVHR8EJzAlMCOgIaAfhh1odHRwOi8vd3d3LmdldGNy
-bC5jcmwvZ2V0Y3JsLzANBgkqhkiG9w0BAQsFAAOBgQAsb5CiRDrbnjVVdYf61tit
-YvgVHbGvJF+Pfh7wjCVI0fccI5utg4Db6BMcIsmApEiuPyT6zg3/rbfHjeI7ECsA
-dYElh+vchUfG/O7vF93rPx0SuAy1vyQNSsva4LrfI/85QurlQHXPeWzoze9QsPuw
-vY5pG1TfOd68ezbj+k3J0Q==
+BgkqhkiG9w0BCQEWDW5vbmVAbm9uZS5vcmcwIhgPMjAwNzA0MjEyMjAwMDBaGA8y
+MDE0MDUyNDIyMDAwMFowgbgxCzAJBgNVBAYTAkdSMRIwEAYDVQQKEwlLb2tvIGlu
+Yy4xFzAVBgNVBAsTDnNsZWVwaW5nIGRlcHQuMQ8wDQYDVQQIEwZBdHRpa2kxFTAT
+BgNVBAMTDENpbmR5IExhdXBlcjEXMBUGCgmSJomT8ixkAQETB2NsYXVwZXIxDDAK
+BgNVBAwTA0RyLjEPMA0GA1UEQRMGamFja2FsMRwwGgYJKoZIhvcNAQkBFg1ub25l
+QG5vbmUub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClxs51Q4S/ZJ4C
+JxPxA1n3eS2S7XwvUKQD8S15uYaLBX46u0Sqr4TPE5geHEo49zMtep9y1GttJrAx
+N3AQ+0Lp2J0YZX4ZSfwFlgRogx53hr/t9eUSOxP+MxicGnodaa9HAmB6H7noz9vI
+NDBRlj2MllwAvGHeCA+xNiF/qQDjBQIDAQABo4GzMIGwMA8GA1UdEwEB/wQFMAMB
+Af8wKAYDVR0RBCEwH4ENbm9uZUBub25lLm9yZ4EOd2hlcmVAbm9uZS5vcmcwEwYD
+VR0lBAwwCgYIKwYBBQUHAwkwDwYDVR0PAQH/BAUDAwcEADAdBgNVHQ4EFgQUXUCt
+8M6UQJWLfpmUHZJUIspyNl8wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDovL3d3dy5n
+ZXRjcmwuY3JsL2dldGNybC8wDQYJKoZIhvcNAQELBQADgYEASd+38D+lbUJIcDCK
+s8QbRpsfw3aRrgIjxY0kSpPeeJ6t+zttbUkdl3xVqZkldJHWZihdY1h0Nqh3W3An
+I6yr+Uex8az0LUrimc3EwYh4QWNUq142Dy2IXlmE3WOipjOatXeMZFj4mruJbYqZ
+psMUofmkNLXu8fEFauBU5jQ2SEA=
-----END CERTIFICATE-----