diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-03-18 11:31:44 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-03-18 11:43:01 +0100 |
commit | 1dd7d7955774b3384c7d6d2c38aa87a85a9cfba1 (patch) | |
tree | f1a22617b03cb59fb62a2890c6385894496f9a4b | |
parent | 33162437d298621b441ab074e295762f833fe859 (diff) | |
download | gnutls-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-- | NEWS | 9 | ||||
-rw-r--r-- | lib/includes/gnutls/x509.h | 12 | ||||
-rw-r--r-- | lib/libgnutls.map | 3 | ||||
-rw-r--r-- | lib/pkix.asn | 4 | ||||
-rw-r--r-- | lib/pkix_asn1_tab.c | 5 | ||||
-rw-r--r-- | lib/x509/common.c | 148 | ||||
-rw-r--r-- | lib/x509/common.h | 4 | ||||
-rw-r--r-- | lib/x509/crl.c | 6 | ||||
-rw-r--r-- | lib/x509/crl_write.c | 6 | ||||
-rw-r--r-- | lib/x509/crq.c | 134 | ||||
-rw-r--r-- | lib/x509/output.c | 58 | ||||
-rw-r--r-- | lib/x509/x509.c | 87 | ||||
-rw-r--r-- | lib/x509/x509_write.c | 76 | ||||
-rw-r--r-- | tests/cert-tests/template-test.pem | 34 |
14 files changed, 481 insertions, 105 deletions
@@ -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 (>ime, &_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 (>ime, &_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----- |