static int p11_list_keys(hx509_context context, struct p11_module *p, struct p11_slot *slot, CK_SESSION_HANDLE session, hx509_lock lock, hx509_certs *certs) { struct hx509_collector *collector; CK_OBJECT_CLASS key_class; CK_ATTRIBUTE search_data[] = { {CKA_CLASS, NULL, 0}, }; CK_ATTRIBUTE query_data[3] = { {CKA_ID, NULL, 0}, {CKA_VALUE, NULL, 0}, {CKA_LABEL, NULL, 0} }; int ret; search_data[0].pValue = &key_class; search_data[0].ulValueLen = sizeof(key_class); if (lock == NULL) lock = _hx509_empty_lock; ret = _hx509_collector_alloc(context, lock, &collector); if (ret) return ret; key_class = CKO_PRIVATE_KEY; ret = iterate_entries(context, p, slot, session, search_data, 1, query_data, 1, collect_private_key, collector); if (ret) goto out; key_class = CKO_CERTIFICATE; ret = iterate_entries(context, p, slot, session, search_data, 1, query_data, 3, collect_cert, collector); if (ret) goto out; ret = _hx509_collector_collect_certs(context, collector, &slot->certs); out: _hx509_collector_free(collector); return ret; }
static int file_init_common(hx509_context context, hx509_certs certs, void **data, int flags, const char *residue, hx509_lock lock, outformat format) { char *p, *pnext; struct ks_file *f = NULL; hx509_private_key *keys = NULL; int ret; struct pem_ctx pem_ctx; pem_ctx.flags = flags; pem_ctx.c = NULL; *data = NULL; if (lock == NULL) lock = _hx509_empty_lock; f = calloc(1, sizeof(*f)); if (f == NULL) { hx509_clear_error_string(context); return ENOMEM; } f->format = format; f->fn = strdup(residue); if (f->fn == NULL) { hx509_clear_error_string(context); ret = ENOMEM; goto out; } /* * XXX this is broken, the function should parse the file before * overwriting it */ if (flags & HX509_CERTS_CREATE) { ret = hx509_certs_init(context, "MEMORY:ks-file-create", 0, lock, &f->certs); if (ret) goto out; *data = f; return 0; } ret = _hx509_collector_alloc(context, lock, &pem_ctx.c); if (ret) goto out; for (p = f->fn; p != NULL; p = pnext) { FILE *f; pnext = strchr(p, ','); if (pnext) *pnext++ = '\0'; if ((f = fopen(p, "r")) == NULL) { ret = ENOENT; hx509_set_error_string(context, 0, ret, "Failed to open PEM file \"%s\": %s", p, strerror(errno)); goto out; } rk_cloexec_file(f); ret = hx509_pem_read(context, f, pem_func, &pem_ctx); fclose(f); if (ret != 0 && ret != HX509_PARSING_KEY_FAILED) goto out; else if (ret == HX509_PARSING_KEY_FAILED) { size_t length; void *ptr; int i; ret = rk_undumpdata(p, &ptr, &length); if (ret) { hx509_clear_error_string(context); goto out; } for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length); if (ret == 0) break; } rk_xfree(ptr); if (ret) goto out; } } ret = _hx509_collector_collect_certs(context, pem_ctx.c, &f->certs); if (ret) goto out; ret = _hx509_collector_collect_private_keys(context, pem_ctx.c, &keys); if (ret == 0) { int i; for (i = 0; keys[i]; i++) _hx509_certs_keys_add(context, f->certs, keys[i]); _hx509_certs_keys_free(context, keys); } out: if (ret == 0) *data = f; else { if (f->fn) free(f->fn); free(f); } if (pem_ctx.c) _hx509_collector_free(pem_ctx.c); return ret; }
static int p12_init(hx509_context context, hx509_certs certs, void **data, int flags, const char *residue, hx509_lock lock) { struct ks_pkcs12 *p12; size_t len; void *buf; PKCS12_PFX pfx; PKCS12_AuthenticatedSafe as; int ret; size_t i; struct hx509_collector *c; *data = NULL; if (lock == NULL) lock = _hx509_empty_lock; ret = _hx509_collector_alloc(context, lock, &c); if (ret) return ret; p12 = calloc(1, sizeof(*p12)); if (p12 == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "out of memory"); goto out; } p12->fn = strdup(residue); if (p12->fn == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "out of memory"); goto out; } if (flags & HX509_CERTS_CREATE) { ret = hx509_certs_init(context, "MEMORY:ks-file-create", 0, lock, &p12->certs); if (ret == 0) *data = p12; goto out; } ret = rk_undumpdata(residue, &buf, &len); if (ret) { hx509_clear_error_string(context); goto out; } ret = decode_PKCS12_PFX(buf, len, &pfx, NULL); rk_xfree(buf); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode the PFX in %s", residue); goto out; } if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) { free_PKCS12_PFX(&pfx); ret = EINVAL; hx509_set_error_string(context, 0, ret, "PKCS PFX isn't a pkcs7-data container"); goto out; } if (pfx.authSafe.content == NULL) { free_PKCS12_PFX(&pfx); ret = EINVAL; hx509_set_error_string(context, 0, ret, "PKCS PFX missing data"); goto out; } { heim_octet_string asdata; ret = decode_PKCS12_OctetString(pfx.authSafe.content->data, pfx.authSafe.content->length, &asdata, NULL); free_PKCS12_PFX(&pfx); if (ret) { hx509_clear_error_string(context); goto out; } ret = decode_PKCS12_AuthenticatedSafe(asdata.data, asdata.length, &as, NULL); der_free_octet_string(&asdata); if (ret) { hx509_clear_error_string(context); goto out; } } for (i = 0; i < as.len; i++) parse_pkcs12_type(context, c, &as.val[i].contentType, as.val[i].content->data, as.val[i].content->length, NULL); free_PKCS12_AuthenticatedSafe(&as); ret = _hx509_collector_collect_certs(context, c, &p12->certs); if (ret == 0) *data = p12; out: _hx509_collector_free(c); if (ret && p12) { if (p12->fn) free(p12->fn); if (p12->certs) hx509_certs_free(&p12->certs); free(p12); } return ret; }