* @GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE: marked as not private.
* @GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY: When retrieving an object, do not set any requirements.
* GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED: When retrieving an object, only retrieve the marked as trusted.
- * In gnutls_pkcs11_crt_is_known() it implies GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_COMPARE.
+ * In gnutls_pkcs11_crt_is_known() it implies %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_COMPARE if %GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY is not given.
* @GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED: When retrieving an object, only retrieve the marked as distrusted.
- * @GNUTLS_PKCS11_OBJ_FLAG_COMPARE: When checking an object's presence, full compare it before returning any result.
+ * @GNUTLS_PKCS11_OBJ_FLAG_COMPARE: When checking an object's presence, fully compare it before returning any result.
+ * @GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY: When checking an object's presence, compare the key before returning any result.
* @GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE: The object must be present in a marked as trusted module.
* @GNUTLS_PKCS11_OBJ_FLAG_MARK_CA: Mark the object as a CA.
* @GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP: Mark the generated key pair as wrapping and unwrapping keys.
GNUTLS_PKCS11_OBJ_FLAG_COMPARE = (1<<9),
GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE = (1<<10),
GNUTLS_PKCS11_OBJ_FLAG_MARK_CA = (1<<11),
- GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP = (1<<12)
+ GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP = (1<<12),
+ GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY = (1<<13)
} gnutls_pkcs11_obj_flags;
/**
}
}
+ if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY) {
+ if (priv->crt == NULL) {
+ gnutls_assert();
+ break;
+ }
+
+ if (_gnutls_check_if_same_key2(priv->crt, &data) == 0) {
+ /* doesn't match */
+ break;
+ }
+ }
+
found = 1;
break;
} else {
/* when looking for a trusted certificate, we always fully compare
* with the given */
- if (flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED)
+ if (flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED && !(flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY))
flags |= GNUTLS_PKCS11_OBJ_FLAG_COMPARE;
priv.flags = flags;
/* returns a constant string in @dn pointing to @raw */
int
-_gnutls_x509_get_raw_dn2(ASN1_TYPE c2, gnutls_datum_t * raw,
+_gnutls_x509_get_raw_field2(ASN1_TYPE c2, gnutls_datum_t * raw,
const char *whom, gnutls_datum_t * dn)
{
int result, len1;
const char *part2);
int
-_gnutls_x509_get_raw_dn2(ASN1_TYPE c2, gnutls_datum_t * raw,
+_gnutls_x509_get_raw_field2(ASN1_TYPE c2, gnutls_datum_t * raw,
const char *whom, gnutls_datum_t * dn);
+bool
+_gnutls_check_if_same_key2(gnutls_x509_crt_t cert1,
+ gnutls_datum_t * cert2bin);
+
bool
_gnutls_check_if_same_cert(gnutls_x509_crt_t cert1,
gnutls_x509_crt_t cert2);
goto cleanup;
}
- result = _gnutls_x509_get_raw_dn2(crl->crl, &crl->der,
+ result = _gnutls_x509_get_raw_field2(crl->crl, &crl->der,
"tbsCertList.issuer.rdnSequence",
&crl->raw_issuer_dn);
if (result < 0) {
#include <gnutls_pk.h>
#include <stdbool.h>
-/* Checks if two certs are identical. Return 1 on match. */
+/* Checks if two certs have the same name and the same key. Return 1 on match. */
+static bool
+_gnutls_check_if_same_key(gnutls_x509_crt_t cert1,
+ gnutls_x509_crt_t cert2)
+{
+ int ret;
+ bool result;
+
+ ret = _gnutls_is_same_dn(cert1, cert2);
+ if (ret == 0)
+ return 0;
+
+ if (cert1->raw_spki.size > 0 && (cert1->raw_spki.size == cert2->raw_spki.size) &&
+ (memcmp(cert1->raw_spki.data, cert2->raw_spki.data, cert1->raw_spki.size) == 0))
+ result = 1;
+ else
+ result = 0;
+
+ fail:
+ return result;
+}
+
+bool
+_gnutls_check_if_same_key2(gnutls_x509_crt_t cert1,
+ gnutls_datum_t * cert2bin)
+{
+ int ret;
+ gnutls_x509_crt_t cert2;
+
+ ret = gnutls_x509_crt_init(&cert2);
+ if (ret < 0)
+ return gnutls_assert_val(0);
+
+ ret = gnutls_x509_crt_import(cert2, cert2bin, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_x509_crt_deinit(cert2);
+ return gnutls_assert_val(0);
+ }
+
+ ret = _gnutls_check_if_same_key(cert1, cert2);
+
+ gnutls_x509_crt_deinit(cert2);
+ return ret;
+}
+
bool
_gnutls_check_if_same_cert(gnutls_x509_crt_t cert1,
gnutls_x509_crt_t cert2)
int j;
for (j = 0; j < tcas_size; j++) {
- if (_gnutls_check_if_same_cert
+ /* we check for a certificate that may not be identical with the one
+ * sent by the client, but will have the same name and key. That is
+ * because it can happen that a CA certificate is upgraded from intermediate
+ * CA to self-signed CA at some point. */
+ if (_gnutls_check_if_same_key
(certificate_list[i], trusted_cas[j]) != 0) {
/* explicit time check for trusted CA that we remove from
* list. GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS
for (; i < clist_size; i++) {
if (gnutls_pkcs11_crt_is_known (url, certificate_list[i],
GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE|
- GNUTLS_PKCS11_OBJ_FLAG_COMPARE|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED) != 0) {
+ GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED) != 0) {
if (!(flags & GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS) &&
!(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS)) {
goto cleanup;
}
- result = _gnutls_x509_get_raw_dn2(cert->cert, &cert->der,
+ result = _gnutls_x509_get_raw_field2(cert->cert, &cert->der,
"tbsCertificate.issuer.rdnSequence",
&cert->raw_issuer_dn);
if (result < 0) {
goto cleanup;
}
- result = _gnutls_x509_get_raw_dn2(cert->cert, &cert->der,
+ result = _gnutls_x509_get_raw_field2(cert->cert, &cert->der,
"tbsCertificate.subject.rdnSequence",
&cert->raw_dn);
if (result < 0) {
goto cleanup;
}
+ result = _gnutls_x509_get_raw_field2(cert->cert, &cert->der,
+ "tbsCertificate.subjectPublicKeyInfo",
+ &cert->raw_spki);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
/* Since we do not want to disable any extension
*/
cert->use_extensions = 1;
* get_raw_*_dn(). */
gnutls_datum_t raw_dn;
gnutls_datum_t raw_issuer_dn;
+ gnutls_datum_t raw_spki;
gnutls_datum_t der;
struct pin_info_st pin;