Пример #1
0
static
int trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
				      const gnutls_datum_t *dn,
				      const gnutls_datum_t *spki,
				      gnutls_x509_crt_t * issuer,
				      unsigned int flags)
{
	int ret;
	unsigned int i, j;
	uint32_t hash;
	uint8_t tmp[256];
	size_t tmp_size;

	if (dn) {
		hash =
		    hash_pjw_bare(dn->data,
				  dn->size);
		hash %= list->size;

		for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
			ret = _gnutls_x509_compare_raw_dn(dn, &list->node[hash].trusted_cas[i]->raw_dn);
			if (ret != 0) {
				if (spki && spki->size > 0) {
					tmp_size = sizeof(tmp);

					ret = gnutls_x509_crt_get_subject_key_id(list->node[hash].trusted_cas[i], tmp, &tmp_size, NULL);
					if (ret < 0)
						continue;
					if (spki->size != tmp_size || memcmp(spki->data, tmp, spki->size) != 0)
						continue;
				}
				*issuer = crt_cpy(list->node[hash].trusted_cas[i]);
				return 0;
			}
		}
	} else if (spki) {
		/* search everything! */
		for (i = 0; i < list->size; i++) {
			for (j = 0; j < list->node[i].trusted_ca_size; j++) {
				tmp_size = sizeof(tmp);

				ret = gnutls_x509_crt_get_subject_key_id(list->node[i].trusted_cas[j], tmp, &tmp_size, NULL);
				if (ret < 0)
					continue;

				if (spki->size != tmp_size || memcmp(spki->data, tmp, spki->size) != 0)
					continue;

				*issuer = crt_cpy(list->node[i].trusted_cas[j]);
				return 0;
			}
		}
	}

	return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
Пример #2
0
bool
_gnutls_check_valid_key_id(gnutls_datum_t *key_id,
                           gnutls_x509_crt_t cert, time_t now)
{
	uint8_t id[MAX_KEY_ID_SIZE];
	size_t id_size;
	bool result = 0;

	if (now > gnutls_x509_crt_get_expiration_time(cert) ||
	    now < gnutls_x509_crt_get_activation_time(cert)) {
		/* don't bother, certificate is not yet activated or expired */
		gnutls_assert();
		goto out;
	}

	if (gnutls_x509_crt_get_subject_key_id(cert, id, &id_size, NULL) < 0) {
		gnutls_assert();
		goto out;
	}

	if (id_size == key_id->size && !memcmp(id, key_id->data, id_size))
		result = 1;

 out:
	return result;
}
Пример #3
0
/*!
  Adds the authority key identifier extension to the certificate. The key
  is extracted the specified certificate which must be the one later used
  to sign the certificate.
 */
bool CertificateBuilder::addAuthorityKeyIdentifier(const QSslCertificate &qcacert)
{
    gnutls_x509_crt_t cacrt = qsslcert_to_crt(qcacert, &d->errnumber);
    if (GNUTLS_E_SUCCESS != d->errnumber)
        return false;

    QByteArray ba(128, 0); // Normally 20 bytes (SHA1)
    size_t size = ba.size();

    // Try using the subject keyid
    d->errnumber = gnutls_x509_crt_get_subject_key_id(cacrt, reinterpret_cast<unsigned char *>(ba.data()), &size, NULL);

    // Or fallback to creating it
    if (GNUTLS_E_SUCCESS != d->errnumber) {
        d->errnumber = gnutls_x509_crt_get_key_id(cacrt, 0, reinterpret_cast<unsigned char *>(ba.data()), &size);

        if (GNUTLS_E_SUCCESS != d->errnumber) {
            gnutls_x509_crt_deinit(cacrt);
            return false;
        }
    }

    gnutls_x509_crt_deinit(cacrt);
    d->errnumber = gnutls_x509_crt_set_authority_key_id(d->crt, reinterpret_cast<const unsigned char *>(ba.constData()), size);

    return GNUTLS_E_SUCCESS == d->errnumber;
}
Пример #4
0
/* This function checks if cert's issuer is issuer.
 * This does a straight (DER) compare of the issuer/subject DN fields in
 * the given certificates, as well as check the authority key ID.
 *
 * Returns 1 if they match and (0) if they don't match. 
 */
static unsigned is_issuer(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
{
	uint8_t id1[MAX_KEY_ID_SIZE];
	uint8_t id2[MAX_KEY_ID_SIZE];
	size_t id1_size;
	size_t id2_size;
	int ret;
	unsigned result;

	if (_gnutls_x509_compare_raw_dn
	    (&cert->raw_issuer_dn, &issuer->raw_dn) != 0)
		result = 1;
	else
		result = 0;

	if (result != 0) {
		/* check if the authority key identifier matches the subject key identifier
		 * of the issuer */
		id1_size = sizeof(id1);

		ret =
		    gnutls_x509_crt_get_authority_key_id(cert, id1,
							 &id1_size, NULL);
		if (ret < 0) {
			/* If there is no authority key identifier in the
			 * certificate, assume they match */
			result = 1;
			goto cleanup;
		}

		id2_size = sizeof(id2);
		ret =
		    gnutls_x509_crt_get_subject_key_id(issuer, id2,
						       &id2_size, NULL);
		if (ret < 0) {
			/* If there is no subject key identifier in the
			 * issuer certificate, assume they match */
			result = 1;
			gnutls_assert();
			goto cleanup;
		}

		if (id1_size == id2_size
		    && memcmp(id1, id2, id1_size) == 0)
			result = 1;
		else
			result = 0;
	}

      cleanup:
	return result;
}
Пример #5
0
void __certificate_properties_fill_cert_ext_SubjectKeyIdentifier (GtkTreeStore *store,
        GtkTreeIter *parent,
        gnutls_x509_crt_t *certificate)
{
    guint critical;
    gint result;
    const gint BUFFER_SIZE_MAX = 256;
    gchar buffer[BUFFER_SIZE_MAX];
    gsize buffer_size = BUFFER_SIZE_MAX;
    gchar *hex_buffer;
    GtkTreeIter l;

    result = gnutls_x509_crt_get_subject_key_id(*certificate, buffer, &buffer_size, &critical);
    if (result < 0) {
        fprintf(stderr, "Error: %s\n", gnutls_strerror(result));
        return;
    }
    hex_buffer = __certificate_properties_dump_raw_data((guchar *) buffer, buffer_size);
    gtk_tree_store_append(store, &l, parent);
    gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("Value"), CERTIFICATE_PROPERTIES_COL_VALUE, hex_buffer, -1);
    g_free(hex_buffer);
}
Пример #6
0
/* This function checks if 'certs' issuer is 'issuer_cert'.
 * This does a straight (DER) compare of the issuer/subject fields in
 * the given certificates.
 *
 * Returns 1 if they match and (0) if they don't match. Otherwise
 * a negative error code is returned to indicate error.
 */
static int
is_issuer (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer_cert)
{
  gnutls_datum_t dn1 = { NULL, 0 }, 
                 dn2 = { NULL, 0};
  uint8_t id1[512];
  uint8_t id2[512];
  size_t id1_size;
  size_t id2_size;
  int ret;

  ret = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn1);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  ret = gnutls_x509_crt_get_raw_dn (issuer_cert, &dn2);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  ret = _gnutls_x509_compare_raw_dn (&dn1, &dn2);
  
  if (ret != 0)
    {
      /* check if the authority key identifier matches the subject key identifier
       * of the issuer */
       id1_size = sizeof(id1);
       
       ret = gnutls_x509_crt_get_authority_key_id(cert, id1, &id1_size, NULL);
       if (ret < 0)
         {
           ret = 1;
           goto cleanup;
         }

       id2_size = sizeof(id2);
       ret = gnutls_x509_crt_get_subject_key_id(issuer_cert, id2, &id2_size, NULL);
       if (ret < 0)
         {
           ret = 1;
           gnutls_assert();
           goto cleanup;
         }
    
       if (id1_size == id2_size && memcmp(id1, id2, id1_size) == 0)
         ret = 1;
       else
         ret = 0;
    }

cleanup:
  _gnutls_free_datum (&dn1);
  _gnutls_free_datum (&dn2);
  return ret;

}
Пример #7
0
/**
 * gnutls_pkcs11_copy_x509_crt2:
 * @token_url: A PKCS #11 URL specifying a token
 * @crt: The certificate to copy
 * @label: The name to be used for the stored data
 * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy a certificate into a PKCS #11 token specified by
 * a URL. Valid flags to mark the certificate: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED,
 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE,
 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 **/
int
gnutls_pkcs11_copy_x509_crt2(const char *token_url,
			    gnutls_x509_crt_t crt, const char *label,
			    const gnutls_datum_t *cid,
			    unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	size_t der_size, id_size, serial_size;
	gnutls_datum_t serial_der = {NULL, 0};
	uint8_t *der = NULL;
	uint8_t serial[128];
	uint8_t id[20];
	struct ck_attribute a[MAX_ASIZE];
	ck_object_class_t class = CKO_CERTIFICATE;
	ck_certificate_type_t type = CKC_X_509;
	ck_object_handle_t ctx;
	unsigned a_val;
	struct pkcs11_session_info sinfo;
	
	PKCS11_CHECK_INIT;

	ret = pkcs11_url_to_info(token_url, &info, 0);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	der_size = 0;
	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL,
				   &der_size);
	if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
		gnutls_assert();
		goto cleanup;
	}

	der = gnutls_malloc(der_size);
	if (der == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der,
				   &der_size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof(class);

	a[1].type = CKA_ID;
	if (cid == NULL || cid->size == 0) {
		id_size = sizeof(id);
		ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL);
		if (ret < 0) {
			id_size = sizeof(id);
			ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
			if (ret < 0) {
			  gnutls_assert();
			  goto cleanup;
			}
		}

		a[1].value = id;
		a[1].value_len = id_size;
	} else {
		a[1].value = cid->data;
		a[1].value_len = cid->size;
	}

	a[2].type = CKA_VALUE;
	a[2].value = der;
	a[2].value_len = der_size;
	a[3].type = CKA_TOKEN;
	a[3].value = (void *) &tval;
	a[3].value_len = sizeof(tval);
	a[4].type = CKA_CERTIFICATE_TYPE;
	a[4].value = &type;
	a[4].value_len = sizeof(type);
	/* FIXME: copy key usage flags */

	a_val = 5;

	a[a_val].type = CKA_SUBJECT;
	a[a_val].value = crt->raw_dn.data;
	a[a_val].value_len = crt->raw_dn.size;
	a_val++;

	a[a_val].type = CKA_ISSUER;
	a[a_val].value = crt->raw_issuer_dn.data;
	a[a_val].value_len = crt->raw_issuer_dn.size;
	a_val++;

	serial_size = sizeof(serial);
	if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) {
		ret = _gnutls_x509_ext_gen_number(serial, serial_size, &serial_der);
		if (ret >= 0) {
			a[a_val].type = CKA_SERIAL_NUMBER;
			a[a_val].value = (void *) serial_der.data;
			a[a_val].value_len = serial_der.size;
			a_val++;
		}
	}

	if (label) {
		a[a_val].type = CKA_LABEL;
		a[a_val].value = (void *) label;
		a[a_val].value_len = strlen(label);
		a_val++;
	}

	mark_flags(flags, a, &a_val, sinfo.trusted);

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* generated! 
	 */

	ret = 0;

      cleanup:
	gnutls_free(der);
	gnutls_free(serial_der.data);
	pkcs11_close_session(&sinfo);
	return ret;

}
Пример #8
0
/**
 * gnutls_pkcs11_copy_x509_crt:
 * @token_url: A PKCS #11 URL specifying a token
 * @crt: A certificate
 * @label: A name to be used for the stored data
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy a certificate into a PKCS #11 token specified by
 * a URL. The certificate can be marked as trusted or not.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_pkcs11_copy_x509_crt(const char *token_url,
			    gnutls_x509_crt_t crt, const char *label,
			    unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	size_t der_size, id_size;
	uint8_t *der = NULL;
	uint8_t id[20];
	struct ck_attribute a[16];
	ck_object_class_t class = CKO_CERTIFICATE;
	ck_certificate_type_t type = CKC_X_509;
	ck_object_handle_t obj;
	int a_val;
	unsigned long category;
	struct pkcs11_session_info sinfo;
	
	PKCS11_CHECK_INIT;

	memset(&sinfo, 0, sizeof(sinfo));

	ret = pkcs11_url_to_info(token_url, &info);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	der_size = 0;
	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL,
				   &der_size);
	if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
		gnutls_assert();
		goto cleanup;
	}

	der = gnutls_malloc(der_size);
	if (der == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der,
				   &der_size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	id_size = sizeof(id);
	ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL);
	if (ret < 0) {
	        id_size = sizeof(id);
		ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
		if (ret < 0) {
		  gnutls_assert();
		  goto cleanup;
                }
	}

	/* FIXME: copy key usage flags */

	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof(class);
	a[1].type = CKA_ID;
	a[1].value = id;
	a[1].value_len = id_size;
	a[2].type = CKA_VALUE;
	a[2].value = der;
	a[2].value_len = der_size;
	a[3].type = CKA_TOKEN;
	a[3].value = (void *) &tval;
	a[3].value_len = sizeof(tval);
	a[4].type = CKA_CERTIFICATE_TYPE;
	a[4].value = &type;
	a[4].value_len = sizeof(type);

	a_val = 5;

	a[a_val].type = CKA_SUBJECT;
	a[a_val].value = crt->raw_dn.data;
	a[a_val].value_len = crt->raw_dn.size;
	a_val++;

	if (label) {
		a[a_val].type = CKA_LABEL;
		a[a_val].value = (void *) label;
		a[a_val].value_len = strlen(label);
		a_val++;
	}

	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
		category = 2;
		a[a_val].type = CKA_CERTIFICATE_CATEGORY;
		a[a_val].value = (void *) &category;
		a[a_val].value_len = sizeof(category);
		a_val++;
	}

	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
		a[a_val].type = CKA_TRUSTED;
		a[a_val].value = (void *) &tval;
		a[a_val].value_len = sizeof(tval);
		a_val++;

		a[a_val].type = CKA_PRIVATE;
		a[a_val].value = (void *) &fval;
		a[a_val].value_len = sizeof(fval);
		a_val++;
	} else {
		if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE) {
			a[a_val].type = CKA_PRIVATE;
			a[a_val].value = (void *) &tval;
			a[a_val].value_len = sizeof(tval);
			a_val++;
		} else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
			a[a_val].type = CKA_PRIVATE;
			a[a_val].value = (void *) &fval;
			a[a_val].value_len = sizeof(fval);
			a_val++;
		}
	}

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &obj);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* generated! 
	 */

	ret = 0;

      cleanup:
	gnutls_free(der);
	pkcs11_close_session(&sinfo);
	return ret;

}