if (type != GNUTLS_PKCS11_OBJ_PUBKEY && type != GNUTLS_PKCS11_OBJ_X509_CRT) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (type == GNUTLS_PKCS11_OBJ_X509_CRT) { gnutls_x509_crt_t xcrt; ret = gnutls_x509_crt_init(&xcrt); if (ret < 0) { gnutls_assert() return ret; } ret = gnutls_x509_crt_import_pkcs11(xcrt, obj); if (ret < 0) { gnutls_assert(); goto cleanup_crt; } ret = gnutls_pubkey_import_x509(key, xcrt, 0); if (ret < 0) { gnutls_assert(); goto cleanup_crt; } ret = gnutls_x509_crt_get_key_usage(xcrt, &key->key_usage, NULL); if (ret < 0) key->key_usage = 0;
/** * gnutls_x509_trust_list_iter_get_ca: * @list: The structure of the list * @iter: A pointer to an iterator (initially the iterator should be %NULL) * @crt: where the certificate will be copied * * This function obtains a certificate in the trust list and advances the * iterator to the next certificate. The certificate returned in @crt must be * deallocated with gnutls_x509_crt_deinit(). * * When past the last element is accessed %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE * is returned and the iterator is reset. * * After use, the iterator must be deinitialized usin * gnutls_x509_trust_list_iter_deinit(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.4.0 **/ int gnutls_x509_trust_list_iter_get_ca(gnutls_x509_trust_list_t list, gnutls_x509_trust_list_iter_t *iter, gnutls_x509_crt_t *crt) { int ret; /* initialize iterator */ if (*iter == NULL) { *iter = gnutls_malloc(sizeof (struct gnutls_x509_trust_list_iter)); if (*iter == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); (*iter)->node_index = 0; (*iter)->ca_index = 0; #ifdef ENABLE_PKCS11 (*iter)->pkcs11_list = NULL; (*iter)->pkcs11_size = 0; (*iter)->pkcs11_index = 0; #endif /* Advance iterator to the first valid entry */ if (list->node[0].trusted_ca_size == 0) { ret = advance_iter(list, *iter); if (ret != 0) { gnutls_x509_trust_list_iter_deinit(*iter); *iter = NULL; *crt = NULL; return gnutls_assert_val(ret); } } } /* obtain the certificate at the current iterator position */ if ((*iter)->node_index < list->size) { ret = gnutls_x509_crt_init(crt); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_x509_crt_cpy(*crt, list->node[(*iter)->node_index].trusted_cas[(*iter)->ca_index]); if (ret < 0) { gnutls_x509_crt_deinit(*crt); return gnutls_assert_val(ret); } } #ifdef ENABLE_PKCS11 else if ( (*iter)->pkcs11_index < (*iter)->pkcs11_size) { ret = gnutls_x509_crt_init(crt); if (ret < 0) return gnutls_assert_val(ret); ret = gnutls_x509_crt_import_pkcs11(*crt, (*iter)->pkcs11_list[(*iter)->pkcs11_index]); if (ret < 0) { gnutls_x509_crt_deinit(*crt); return gnutls_assert_val(ret); } } #endif else { /* iterator is at end */ gnutls_x509_trust_list_iter_deinit(*iter); *iter = NULL; *crt = NULL; return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); } /* Move iterator to the next position. * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned if the iterator * has been moved to the end position. That is okay, we return the * certificate that we read and when this function is called again we * report GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE to our caller. */ ret = advance_iter(list, *iter); if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { gnutls_x509_crt_deinit(*crt); *crt = NULL; return gnutls_assert_val(ret); } return 0; }
static gnutls_pubkey_t _load_pkcs11_pubkey(const char* url) { int ret; gnutls_pkcs11_obj_t obj; gnutls_x509_crt_t xcrt; gnutls_pubkey_t pubkey; unsigned int obj_flags = 0; ret = gnutls_pubkey_init (&pubkey); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_pkcs11_obj_init (&obj); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_pkcs11_obj_import_url (obj, url, obj_flags); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s: %s\n", __func__, __LINE__, gnutls_strerror (ret), url); exit (1); } switch (gnutls_pkcs11_obj_get_type (obj)) { case GNUTLS_PKCS11_OBJ_X509_CRT: ret = gnutls_x509_crt_init (&xcrt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_x509_crt_import_pkcs11 (xcrt, obj); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_pubkey_import_x509 (pubkey, xcrt, 0); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } gnutls_x509_crt_deinit (xcrt); break; case GNUTLS_PKCS11_OBJ_PUBKEY: ret = gnutls_pubkey_import_pkcs11 (pubkey, obj, 0); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } break; default: { fprintf(stderr, "Unsupported PKCS #11 object\n"); exit (1); break; } } gnutls_pkcs11_obj_deinit (obj); return pubkey; }
void pkcs11_export_chain(FILE * outfile, const char *url, unsigned int flags, common_info_st * info) { gnutls_pkcs11_obj_t obj; gnutls_x509_crt_t xcrt; gnutls_datum_t t; int ret; unsigned int obj_flags = flags; pkcs11_common(info); FIX(url, outfile, 0, info); ret = gnutls_pkcs11_obj_init(&obj); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); } ret = gnutls_pkcs11_obj_import_url(obj, url, obj_flags); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); } /* make a crt */ ret = gnutls_x509_crt_init(&xcrt); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_import_pkcs11(xcrt, obj); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); } ret = gnutls_pkcs11_obj_export3(obj, GNUTLS_X509_FMT_PEM, &t); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); } fwrite(t.data, 1, t.size, outfile); fputs("\n\n", outfile); gnutls_free(t.data); gnutls_pkcs11_obj_deinit(obj); do { ret = gnutls_pkcs11_get_raw_issuer(url, xcrt, &t, GNUTLS_X509_FMT_PEM, 0); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) break; if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); } fwrite(t.data, 1, t.size, outfile); fputs("\n\n", outfile); gnutls_x509_crt_deinit(xcrt); ret = gnutls_x509_crt_init(&xcrt); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_import(xcrt, &t, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); } gnutls_free(t.data); ret = gnutls_x509_crt_check_issuer(xcrt, xcrt); if (ret != 0) { /* self signed */ break; } } while(1); UNFIX; return; }
/* lists certificates from a token */ void pkcs11_list (FILE * outfile, const char *url, int type, unsigned int login, unsigned int detailed, common_info_st * info) { gnutls_pkcs11_obj_t *crt_list; gnutls_x509_crt_t xcrt; unsigned int crt_list_size = 0; int ret; char *output; int i, attrs; unsigned int obj_flags = 0; if (login) obj_flags = GNUTLS_PKCS11_OBJ_FLAG_LOGIN; pkcs11_common (); if (url == NULL) url = "pkcs11:"; if (type == PKCS11_TYPE_TRUSTED) { attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED; } else if (type == PKCS11_TYPE_PK) { attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY; } else if (type == PKCS11_TYPE_CRT_ALL) { attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL; } else if (type == PKCS11_TYPE_PRIVKEY) { attrs = GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY; } else { attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL; } /* give some initial value to avoid asking for the pkcs11 pin twice. */ crt_list_size = 128; crt_list = malloc (sizeof (*crt_list) * crt_list_size); if (crt_list == NULL) { fprintf (stderr, "Memory error\n"); exit (1); } ret = gnutls_pkcs11_obj_list_import_url (crt_list, &crt_list_size, url, attrs, obj_flags); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { fprintf (stderr, "Error in crt_list_import (1): %s\n", gnutls_strerror (ret)); exit (1); } if (crt_list_size == 0) { fprintf (stderr, "No matching objects found\n"); exit (0); } if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { crt_list = realloc (crt_list, sizeof (*crt_list) * crt_list_size); if (crt_list == NULL) { fprintf (stderr, "Memory error\n"); exit (1); } ret = gnutls_pkcs11_obj_list_import_url (crt_list, &crt_list_size, url, attrs, obj_flags); if (ret < 0) { fprintf (stderr, "Error in crt_list_import: %s\n", gnutls_strerror (ret)); exit (1); } } for (i = 0; i < crt_list_size; i++) { char buf[128]; size_t size; ret = gnutls_pkcs11_obj_export_url (crt_list[i], detailed, &output); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fprintf (outfile, "Object %d:\n\tURL: %s\n", i, output); fprintf (outfile, "\tType: %s\n", gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_get_type (crt_list[i]))); size = sizeof (buf); ret = gnutls_pkcs11_obj_get_info (crt_list[i], GNUTLS_PKCS11_OBJ_LABEL, buf, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fprintf (outfile, "\tLabel: %s\n", buf); size = sizeof (buf); ret = gnutls_pkcs11_obj_get_info (crt_list[i], GNUTLS_PKCS11_OBJ_ID_HEX, buf, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fprintf (outfile, "\tID: %s\n\n", buf); if (attrs == GNUTLS_PKCS11_OBJ_ATTR_ALL || attrs == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) continue; ret = gnutls_x509_crt_init (&xcrt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_x509_crt_import_pkcs11 (xcrt, crt_list[i]); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } #if 0 size = buffer_size; ret = gnutls_x509_crt_export (xcrt, GNUTLS_X509_FMT_PEM, buffer, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fwrite (buffer, 1, size, outfile); fputs ("\n\n", outfile); #endif gnutls_x509_crt_deinit (xcrt); } return; }
void pkcs11_export (FILE * outfile, const char *url, unsigned int login, common_info_st * info) { gnutls_pkcs11_obj_t crt; gnutls_x509_crt_t xcrt; gnutls_pubkey_t pubkey; int ret; size_t size; unsigned int obj_flags = 0; if (login) obj_flags = GNUTLS_PKCS11_OBJ_FLAG_LOGIN; pkcs11_common (); if (url == NULL) url = "pkcs11:"; ret = gnutls_pkcs11_obj_init (&crt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_pkcs11_obj_import_url (crt, url, obj_flags); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } switch (gnutls_pkcs11_obj_get_type (crt)) { case GNUTLS_PKCS11_OBJ_X509_CRT: ret = gnutls_x509_crt_init (&xcrt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_x509_crt_import_pkcs11 (xcrt, crt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } size = buffer_size; ret = gnutls_x509_crt_export (xcrt, GNUTLS_X509_FMT_PEM, buffer, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fwrite (buffer, 1, size, outfile); gnutls_x509_crt_deinit (xcrt); break; case GNUTLS_PKCS11_OBJ_PUBKEY: ret = gnutls_pubkey_init (&pubkey); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_pubkey_import_pkcs11 (pubkey, crt, 0); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } size = buffer_size; ret = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_PEM, buffer, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fwrite (buffer, 1, size, outfile); gnutls_pubkey_deinit (pubkey); break; default: { gnutls_datum_t data, enc; size = buffer_size; ret = gnutls_pkcs11_obj_export (crt, buffer, &size); if (ret < 0) { break; } data.data = buffer; data.size = size; ret = gnutls_pem_base64_encode_alloc ("DATA", &data, &enc); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fwrite (enc.data, 1, enc.size, outfile); gnutls_free (enc.data); break; } } fputs ("\n\n", outfile); gnutls_pkcs11_obj_deinit (crt); return; }