/* loads a the corresponding to the private key public key either from * a public key object or from a certificate. */ static int load_pubkey_obj(gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t pub) { int ret, iret; gnutls_x509_crt_t crt; ret = gnutls_pubkey_import_url(pub, pkey->url, pkey->flags); if (ret >= 0) { return ret; } iret = ret; /* else try certificate */ ret = gnutls_x509_crt_init(&crt); if (ret < 0) { gnutls_assert(); return ret; } gnutls_x509_crt_set_pin_function(crt, pkey->pin.cb, pkey->pin.data); ret = gnutls_x509_crt_import_url(crt, pkey->url, pkey->flags); if (ret < 0) { ret = iret; goto cleanup; } ret = gnutls_pubkey_import_x509(pub, crt, 0); cleanup: gnutls_x509_crt_deinit(crt); return ret; }
/* Reads a certificate key from a token. */ static int read_cert_url(gnutls_certificate_credentials_t res, gnutls_privkey_t key, const char *url) { int ret; gnutls_x509_crt_t crt = NULL; gnutls_pcert_st *ccert = NULL; gnutls_str_array_t names; gnutls_datum_t t = {NULL, 0}; unsigned i, count = 0; _gnutls_str_array_init(&names); ccert = gnutls_malloc(sizeof(*ccert)*MAX_PKCS11_CERT_CHAIN); if (ccert == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } ret = gnutls_x509_crt_init(&crt); if (ret < 0) { gnutls_assert(); goto cleanup; } if (res->pin.cb) gnutls_x509_crt_set_pin_function(crt, res->pin.cb, res->pin.data); ret = gnutls_x509_crt_import_url(crt, url, 0); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) ret = gnutls_x509_crt_import_url(crt, url, GNUTLS_PKCS11_OBJ_FLAG_LOGIN); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_get_x509_name(crt, &names); if (ret < 0) { gnutls_assert(); goto cleanup; } /* Try to load the whole certificate chain from the PKCS #11 token */ for (i=0;i<MAX_PKCS11_CERT_CHAIN;i++) { ret = gnutls_x509_crt_check_issuer(crt, crt); if (i > 0 && ret != 0) { /* self signed */ break; } ret = gnutls_pcert_import_x509(&ccert[i], crt, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } count++; ret = _gnutls_get_raw_issuer(url, crt, &t, 0); if (ret < 0) break; gnutls_x509_crt_deinit(crt); crt = NULL; ret = gnutls_x509_crt_init(&crt); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_x509_crt_import(crt, &t, GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert(); goto cleanup; } gnutls_free(t.data); } ret = _gnutls_certificate_credential_append_keypair(res, key, names, ccert, count); if (ret < 0) { gnutls_assert(); goto cleanup; } if (crt != NULL) gnutls_x509_crt_deinit(crt); return 0; cleanup: if (crt != NULL) gnutls_x509_crt_deinit(crt); gnutls_free(t.data); _gnutls_str_array_clear(&names); gnutls_free(ccert); return ret; }
void doit(void) { int ret; gnutls_x509_crt_t crt, ocrt; unsigned keyusage; const char *lib; ret = global_init(); if (ret != 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } lib = getenv("P11MOCKLIB1"); if (lib == NULL) lib = P11LIB; gnutls_global_set_time_function(mytime); if (debug) { gnutls_global_set_log_level(4711); success("loading lib %s\n", lib); } ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL); if (ret != 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } ret = gnutls_pkcs11_add_provider(lib, "trusted"); if (ret != 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } assert(gnutls_x509_crt_init(&crt)>=0); assert(gnutls_x509_crt_init(&ocrt)>=0); /* check high level certificate functions */ ret = gnutls_x509_crt_import_url(crt, "pkcs11:type=cert;object=cert1", 0); if (ret < 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_import_url(ocrt, "pkcs11:type=cert;object=cert1", GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT); if (ret < 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_equals(crt, ocrt); if (ret != 0) { fail("exported certificates are equal!\n"); } ret = gnutls_x509_crt_get_ca_status(ocrt, NULL); if (ret < 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } if (ret == 0) { fail("overriden cert is not a CA!\n"); exit(1); } ret = gnutls_x509_crt_get_key_usage(ocrt, &keyusage, NULL); if (ret < 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } if (keyusage != (GNUTLS_KEY_KEY_ENCIPHERMENT|GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_KEY_CERT_SIGN)) { fail("Extension does not have the expected key usage!\n"); } gnutls_x509_crt_deinit(crt); gnutls_x509_crt_deinit(ocrt); if (debug) printf("done\n\n\n"); gnutls_global_deinit(); }