From 5d0e6706358132e7cd7c8c9904c7399a2f5b5044 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 2 Jun 2015 11:00:26 +0200 Subject: pkcs7 verification: parse the signing time --- lib/includes/gnutls/pkcs7.h | 2 ++ lib/x509/common.c | 19 +++++++++++------ lib/x509/pkcs7.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/lib/includes/gnutls/pkcs7.h b/lib/includes/gnutls/pkcs7.h index d952b2d94e..7955dd601a 100644 --- a/lib/includes/gnutls/pkcs7.h +++ b/lib/includes/gnutls/pkcs7.h @@ -78,6 +78,8 @@ typedef struct gnutls_pkcs7_signature_info_st { gnutls_datum_t issuer_dn; gnutls_datum_t signer_serial; gnutls_datum_t issuer_keyid; + time_t signing_time; + char pad[64]; } gnutls_pkcs7_signature_info_st; void gnutls_pkcs7_signature_info_deinit(gnutls_pkcs7_signature_info_st *info); diff --git a/lib/x509/common.c b/lib/x509/common.c index 321fa7d7f4..1a368ea73b 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -767,7 +767,7 @@ gtime2generalTime(time_t gtime, char *str_time, size_t str_time_size) * be something like "tbsCertList.thisUpdate". */ #define MAX_TIME 64 -time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when, int nochoice) +time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *where, int nochoice) { char ttime[MAX_TIME]; char name[128]; @@ -775,7 +775,7 @@ time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when, int nochoice) int len, result; len = sizeof(ttime) - 1; - result = asn1_read_value(c2, when, ttime, &len); + result = asn1_read_value(c2, where, ttime, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); return (time_t) (-1); @@ -784,19 +784,26 @@ time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when, int nochoice) if (nochoice != 0) { c_time = _gnutls_x509_generalTime2gtime(ttime); } else { - _gnutls_str_cpy(name, sizeof(name), when); + _gnutls_str_cpy(name, sizeof(name), where); /* choice */ if (strcmp(ttime, "generalTime") == 0) { - _gnutls_str_cat(name, sizeof(name), - ".generalTime"); + if (name[0] == 0) + _gnutls_str_cpy(name, sizeof(name), + "generalTime"); + else + _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"); + if (name[0] == 0) + _gnutls_str_cpy(name, sizeof(name), "utcTime"); + else + _gnutls_str_cat(name, sizeof(name), ".utcTime"); len = sizeof(ttime) - 1; result = asn1_read_value(c2, name, ttime, &len); if (result == ASN1_SUCCESS) diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c index 3ebfb741da..781d21b350 100644 --- a/lib/x509/pkcs7.c +++ b/lib/x509/pkcs7.c @@ -441,6 +441,42 @@ void gnutls_pkcs7_signature_info_deinit(gnutls_pkcs7_signature_info_st *info) memset(info, 0, sizeof(*info)); } +static time_t parse_time(gnutls_pkcs7_t pkcs7, const char *root) +{ + char tval[128]; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + time_t ret; + int result, len; + + result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Time", &c2); + if (result != ASN1_SUCCESS) { + ret = -1; + gnutls_assert(); + goto cleanup; + } + + len = sizeof(tval); + result = asn1_read_value(pkcs7->signed_data, root, tval, &len); + if (result != ASN1_SUCCESS) { + ret = -1; + gnutls_assert(); + goto cleanup; + } + + result = _asn1_strict_der_decode(&c2, tval, len, NULL); + if (result != ASN1_SUCCESS) { + ret = -1; + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_x509_get_time(c2, "", 0); + + cleanup: + asn1_delete_structure(&c2); + return ret; +} + /** * gnutls_pkcs7_get_signature_info: * @pkcs7: should contain a #gnutls_pkcs7_t type @@ -463,11 +499,13 @@ int gnutls_pkcs7_get_signature_info(gnutls_pkcs7_t pkcs7, unsigned idx, gnutls_p char oid[MAX_OID_SIZE]; gnutls_pk_algorithm_t pk; gnutls_sign_algorithm_t sig; + unsigned i; if (pkcs7 == NULL) return GNUTLS_E_INVALID_REQUEST; memset(info, 0, sizeof(*info)); + info->signing_time = -1; ret = asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count); if (ret != ASN1_SUCCESS || idx+1 > (unsigned)count) { @@ -551,6 +589,20 @@ int gnutls_pkcs7_get_signature_info(gnutls_pkcs7_t pkcs7, unsigned idx, gnutls_p goto fail; } + /* read the signing time */ + for (i=0;;i++) { + snprintf(root, sizeof(root), "signerInfos.?%u.signedAttrs.?%u.type", idx+1, i+1); + len = sizeof(oid)-1; + ret = asn1_read_value(pkcs7->signed_data, root, oid, &len); + if (ret != ASN1_SUCCESS) { + break; + } + + if (strcmp(oid, ATTR_SIGNING_TIME) == 0) { + snprintf(root, sizeof(root), "signerInfos.?%u.signedAttrs.?%u.values.?1", idx+1, i+1); + info->signing_time = parse_time(pkcs7, root); + } + } return 0; fail: gnutls_pkcs7_signature_info_deinit(info); -- cgit v1.2.1