summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-10-17 15:07:03 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-10-18 12:59:04 +0200
commit6b9818ec4a10466c871b7a99bc7b392d4a590877 (patch)
treebd0f6dc53138e8a719844063980ceef1fec49bc0
parent08a8f68e38c1c6491db4997140a0d43711b54830 (diff)
downloadgnutls-6b9818ec4a10466c871b7a99bc7b392d4a590877.tar.gz
gnutls_x509_crt_verify_data2: introduce constraints checks on the provided certificate
That is check the provided certificate for validity in time and key usage.
-rw-r--r--lib/errors.c4
-rw-r--r--lib/includes/gnutls/gnutls.h.in1
-rw-r--r--lib/x509/pkcs7.c8
-rw-r--r--lib/x509/x509.c86
-rw-r--r--lib/x509/x509_int.h9
5 files changed, 95 insertions, 13 deletions
diff --git a/lib/errors.c b/lib/errors.c
index 5e4610bf8f..9f46374978 100644
--- a/lib/errors.c
+++ b/lib/errors.c
@@ -134,8 +134,10 @@ static const gnutls_error_entry error_entries[] = {
ERROR_ENTRY(N_("Error in password file."), GNUTLS_E_SRP_PWD_ERROR),
ERROR_ENTRY(N_("Wrong padding in PKCS1 packet."),
GNUTLS_E_PKCS1_WRONG_PAD),
- ERROR_ENTRY(N_("The requested session has expired."),
+ ERROR_ENTRY(N_("The session or certificate has expired."),
GNUTLS_E_EXPIRED),
+ ERROR_ENTRY(N_("The certificate is not yet activated."),
+ GNUTLS_E_NOT_YET_ACTIVATED),
ERROR_ENTRY(N_("Hashing has failed."), GNUTLS_E_HASH_FAILED),
ERROR_ENTRY(N_("Base64 decoding error."),
GNUTLS_E_BASE64_DECODING_ERROR),
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 75673c88ad..7134e2c094 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -2813,6 +2813,7 @@ unsigned gnutls_fips140_mode_enabled(void);
#define GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE -408
#define GNUTLS_E_PK_INVALID_PUBKEY -409
#define GNUTLS_E_PK_INVALID_PRIVKEY -410
+#define GNUTLS_E_NOT_YET_ACTIVATED -411
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c
index b2de03f2d4..764fb599fd 100644
--- a/lib/x509/pkcs7.c
+++ b/lib/x509/pkcs7.c
@@ -965,6 +965,10 @@ gnutls_pkcs7_get_embedded_data_oid(gnutls_pkcs7_t pkcs7)
* provided are NULL then the data in the encapsulatedContent field
* will be used instead.
*
+ * Note that, unlike gnutls_pkcs7_verify() this function does not
+ * verify the key purpose of the signer. It is expected for the caller
+ * to verify the intended purpose of the %signer -e.g., via gnutls_x509_crt_get_key_purpose_oid().
+ *
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value. A verification error results to a
* %GNUTLS_E_PK_SIG_VERIFY_FAILED and the lack of encapsulated data
@@ -1239,8 +1243,8 @@ int gnutls_pkcs7_verify(gnutls_pkcs7_t pkcs7,
signer = find_signer(pkcs7, tl, vdata, vdata_size, &info);
if (signer) {
ret =
- gnutls_x509_crt_verify_data2(signer, info.algo, flags,
- &sigdata, &info.sig);
+ gnutls_x509_crt_verify_data3(signer, info.algo, vdata, vdata_size,
+ &sigdata, &info.sig, flags);
if (ret < 0) {
gnutls_assert();
}
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 25f1d2691a..a60d667033 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -3862,8 +3862,8 @@ gnutls_x509_crt_import_url(gnutls_x509_crt_t crt,
return ret;
}
-/**
- * gnutls_x509_crt_verify_data2:
+/*-
+ * gnutls_x509_crt_verify_data3:
* @crt: Holds the certificate to verify with
* @algo: The signature algorithm used
* @flags: Zero or an OR list of #gnutls_certificate_verify_flags
@@ -3874,16 +3874,19 @@ gnutls_x509_crt_import_url(gnutls_x509_crt_t crt,
* parameters from the certificate.
*
* Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
- * is returned, and zero or positive code on success.
+ * is returned, %GNUTLS_E_EXPIRED or %GNUTLS_E_NOT_YET_ACTIVATED on expired
+ * or not yet activated certificate and zero or positive code on success.
*
- * Since: 3.4.0
- **/
+ * Since: 3.5.6
+ -*/
int
-gnutls_x509_crt_verify_data2(gnutls_x509_crt_t crt,
- gnutls_sign_algorithm_t algo,
- unsigned int flags,
- const gnutls_datum_t * data,
- const gnutls_datum_t * signature)
+gnutls_x509_crt_verify_data3(gnutls_x509_crt_t crt,
+ gnutls_sign_algorithm_t algo,
+ gnutls_typed_vdata_st *vdata,
+ unsigned int vdata_size,
+ const gnutls_datum_t *data,
+ const gnutls_datum_t *signature,
+ unsigned int flags)
{
int ret;
gnutls_pubkey_t pubkey;
@@ -3893,6 +3896,7 @@ gnutls_x509_crt_verify_data2(gnutls_x509_crt_t crt,
return GNUTLS_E_INVALID_REQUEST;
}
+
ret = gnutls_pubkey_init(&pubkey);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -3904,5 +3908,67 @@ gnutls_x509_crt_verify_data2(gnutls_x509_crt_t crt,
ret = gnutls_pubkey_verify_data2(pubkey, algo, flags, data, signature);
gnutls_pubkey_deinit(pubkey);
+ if (ret >= 0) {
+ time_t now = gnutls_time(0);
+ int res;
+ unsigned usage, i;
+
+ if (!(flags & GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS) ||
+ !(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS)) {
+ if (now > gnutls_x509_crt_get_expiration_time(crt)) {
+ return gnutls_assert_val(GNUTLS_E_EXPIRED);
+ }
+
+ if (now < gnutls_x509_crt_get_activation_time(crt)) {
+ return gnutls_assert_val(GNUTLS_E_NOT_YET_ACTIVATED);
+ }
+ }
+
+ res = gnutls_x509_crt_get_key_usage(crt, &usage, NULL);
+ if (res >= 0) {
+ if (!(usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
+ return gnutls_assert_val(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
+ }
+ }
+
+ for (i=0;i<vdata_size;i++) {
+ if (vdata[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
+ res = _gnutls_check_key_purpose(crt, (char *)vdata[i].data, 0);
+ if (res == 0)
+ return gnutls_assert_val(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
+ break;
+ }
+ }
+ }
+
return ret;
}
+
+/**
+ * gnutls_x509_crt_verify_data2:
+ * @crt: Holds the certificate to verify with
+ * @algo: The signature algorithm used
+ * @flags: Zero or an OR list of #gnutls_certificate_verify_flags
+ * @data: holds the signed data
+ * @signature: contains the signature
+ *
+ * This function will verify the given signed data, using the
+ * parameters from the certificate.
+ *
+ * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
+ * is returned, %GNUTLS_E_EXPIRED or %GNUTLS_E_NOT_YET_ACTIVATED on expired
+ * or not yet activated certificate and zero or positive code on success.
+ *
+ * Since: 3.4.0
+ **/
+int
+gnutls_x509_crt_verify_data2(gnutls_x509_crt_t crt,
+ gnutls_sign_algorithm_t algo,
+ unsigned int flags,
+ const gnutls_datum_t *data,
+ const gnutls_datum_t *signature)
+{
+ return gnutls_x509_crt_verify_data3(crt, algo, NULL, 0,
+ data, signature, flags);
+}
+
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index b64ee31d9d..25e013f2fb 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -406,6 +406,15 @@ int _gnutls_x509_crq_set_extension(gnutls_x509_crq_t crq,
const gnutls_datum_t * ext_data,
unsigned int critical);
+int
+gnutls_x509_crt_verify_data3(gnutls_x509_crt_t crt,
+ gnutls_sign_algorithm_t algo,
+ gnutls_typed_vdata_st *vdata,
+ unsigned int vdata_size,
+ const gnutls_datum_t *data,
+ const gnutls_datum_t *signature,
+ unsigned int flags);
+
unsigned int
_gnutls_verify_crt_status(const gnutls_x509_crt_t * certificate_list,
int clist_size,