* @sc: is a #gnutls_certificate_credentials_t structure.
* @cert: is the certificate to find issuer for
* @issuer: Will hold the issuer if any. Should be treated as constant.
- * @flags: Use zero.
+ * @flags: Use zero or %GNUTLS_TL_GET_COPY
*
* This function will return the issuer of a given certificate.
+ * As with gnutls_x509_trust_list_get_issuer() this function requires
+ * the %GNUTLS_TL_GET_COPY flag in order to operate with PKCS #11 trust
+ * lists. In that case the issuer must be freed using gnutls_x509_crt_deinit().
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
gnutls_x509_crt_t *peer_certificate_list;
gnutls_datum_t resp;
int peer_certificate_list_size, i, x, ret;
- gnutls_x509_crt_t issuer;
+ gnutls_x509_crt_t issuer = NULL;
unsigned int ocsp_status = 0;
unsigned int verify_flags;
+ unsigned issuer_deinit = 0;
/* No OCSP check so far */
session->internals.ocsp_check_ok = 0;
if (ret < 0)
goto skip_ocsp;
- if (peer_certificate_list_size > 1)
+ if (peer_certificate_list_size > 1) {
issuer = peer_certificate_list[1];
- else {
+ } else {
ret =
gnutls_x509_trust_list_get_issuer(cred->tlist,
peer_certificate_list
- [0], &issuer, 0);
+ [0], &issuer, GNUTLS_TL_GET_COPY);
if (ret < 0) {
goto skip_ocsp;
}
+ issuer_deinit = 1;
}
ret =
check_ocsp_response(session, peer_certificate_list[0], issuer,
&resp, &ocsp_status);
+ if (issuer_deinit != 0)
+ gnutls_x509_crt_deinit(issuer);
+
if (ret < 0) {
CLEAR_CERTS;
return gnutls_assert_val(ret);
#define GNUTLS_TL_USE_IN_TLS (1<<1)
#define GNUTLS_TL_NO_DUPLICATES (1<<2)
#define GNUTLS_TL_NO_DUPLICATE_KEY (1<<3)
+#define GNUTLS_TL_GET_COPY (1<<4)
int
gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list,
const gnutls_x509_crt_t * clist,
unsigned int *verify, unsigned int flags)
{
gnutls_x509_crt_t signercert = NULL;
+ gnutls_x509_crt_t issuer = NULL;
int rc;
/* Algorithm:
rc = _gnutls_trustlist_inlist(trustlist, signercert);
if (rc == 0) {
/* not in trustlist, need to verify signature and bits */
- gnutls_x509_crt_t issuer;
unsigned vtmp;
gnutls_assert();
rc = gnutls_x509_trust_list_get_issuer(trustlist,
signercert, &issuer,
- 0);
+ GNUTLS_TL_GET_COPY);
if (rc != GNUTLS_E_SUCCESS) {
gnutls_assert();
*verify = GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER;
done:
gnutls_x509_crt_deinit(signercert);
+ if (issuer != NULL)
+ gnutls_x509_crt_deinit(issuer);
return rc;
}
* @list: The structure of the list
* @cert: is the certificate to find issuer for
* @issuer: Will hold the issuer if any. Should be treated as constant.
- * @flags: Use zero.
+ * @flags: Use zero or %GNUTLS_TL_GET_COPY
*
- * This function will attempt to find the issuer of the
- * given certificate.
+ * This function will find the issuer of the given certificate.
+ * If the flag %GNUTLS_TL_GET_COPY is specified a copy of the issuer
+ * will be returned which must be freed using gnutls_x509_crt_deinit().
+ * Note that the flag %GNUTLS_TL_GET_COPY is required for this function
+ * to work with PKCS #11 trust lists in a thread-safe way.
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
if (ret < 0)
return gnutls_assert_val(ret);
+ if (flags & GNUTLS_TL_GET_COPY) {
+ gnutls_x509_crt_t crt;
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0) {
+ gnutls_free(der.data);
+ return gnutls_assert_val(ret);
+ }
+
+ ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_free(der.data);
+ gnutls_x509_crt_deinit(crt);
+ return gnutls_assert_val(ret);
+ }
+ *issuer = crt;
+ return 0;
+ }
+
/* we add this CA to the trusted list in order to make it
* persistent. It will be deallocated when the trust list is.
*/
}
#endif
- return trust_list_get_issuer(list, cert, issuer, flags);
+ ret = trust_list_get_issuer(list, cert, issuer, flags);
+ if (flags & GNUTLS_TL_GET_COPY) {
+ *issuer = crt_cpy(*issuer);
+ }
+ return ret;
}
static