static int parse_rsa_private_key(hx509_context context, const char *fn, struct hx509_collector *c, const hx509_pem_header *headers, const void *data, size_t len) { int ret = 0; const char *enc; enc = hx509_pem_find_header(headers, "Proc-Type"); if (enc) { const char *dek; char *type, *iv; ssize_t ssize, size; void *ivdata; const EVP_CIPHER *cipher; const struct _hx509_password *pw; hx509_lock lock; int i, decrypted = 0; lock = _hx509_collector_get_lock(c); if (lock == NULL) { hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, "Failed to get password for " "password protected file %s", fn); return HX509_ALG_NOT_SUPP; } if (strcmp(enc, "4,ENCRYPTED") != 0) { hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, "RSA key encrypted in unknown method %s " "in file", enc, fn); hx509_clear_error_string(context); return HX509_PARSING_KEY_FAILED; } dek = hx509_pem_find_header(headers, "DEK-Info"); if (dek == NULL) { hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, "Encrypted RSA missing DEK-Info"); return HX509_PARSING_KEY_FAILED; } type = strdup(dek); if (type == NULL) { hx509_clear_error_string(context); return ENOMEM; } iv = strchr(type, ','); if (iv == NULL) { free(type); hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, "IV missing"); return HX509_PARSING_KEY_FAILED; } *iv++ = '\0'; size = strlen(iv); ivdata = malloc(size); if (ivdata == NULL) { hx509_clear_error_string(context); free(type); return ENOMEM; } cipher = EVP_get_cipherbyname(type); if (cipher == NULL) { free(ivdata); hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, "RSA key encrypted with " "unsupported cipher: %s", type); free(type); return HX509_ALG_NOT_SUPP; } #define PKCS5_SALT_LEN 8 ssize = hex_decode(iv, ivdata, size); free(type); type = NULL; iv = NULL; if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) { free(ivdata); hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, "Salt have wrong length in RSA key file"); return HX509_PARSING_KEY_FAILED; } pw = _hx509_lock_get_passwords(lock); if (pw != NULL) { const void *password; size_t passwordlen; for (i = 0; i < pw->len; i++) { password = pw->val[i]; passwordlen = strlen(password); ret = try_decrypt(context, c, hx509_signature_rsa(), cipher, ivdata, password, passwordlen, data, len); if (ret == 0) { decrypted = 1; break; } } } if (!decrypted) { hx509_prompt prompt; char password[128]; memset(&prompt, 0, sizeof(prompt)); prompt.prompt = "Password for keyfile: "; prompt.type = HX509_PROMPT_TYPE_PASSWORD; prompt.reply.data = password; prompt.reply.length = sizeof(password); ret = hx509_lock_prompt(lock, &prompt); if (ret == 0) ret = try_decrypt(context, c, hx509_signature_rsa(), cipher, ivdata, password, strlen(password), data, len); /* XXX add password to lock password collection ? */ memset(password, 0, sizeof(password)); } free(ivdata); } else { heim_octet_string keydata; keydata.data = rk_UNCONST(data); keydata.length = len; ret = _hx509_collector_private_key_add(context, c, hx509_signature_rsa(), NULL, &keydata, NULL); } return ret; }
static int p12_store(hx509_context context, hx509_certs certs, void *data, int flags, hx509_lock lock) { struct ks_pkcs12 *p12 = data; PKCS12_PFX pfx; PKCS12_AuthenticatedSafe as; PKCS12_OctetString asdata; size_t size; int ret; memset(&as, 0, sizeof(as)); memset(&pfx, 0, sizeof(pfx)); ret = hx509_certs_iter_f(context, p12->certs, store_func, &as); if (ret) goto out; ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe, asdata.data, asdata.length, &as, &size, ret); free_PKCS12_AuthenticatedSafe(&as); if (ret) return ret; ret = der_parse_hex_heim_integer("03", &pfx.version); if (ret) { free(asdata.data); goto out; } pfx.authSafe.content = calloc(1, sizeof(*pfx.authSafe.content)); ASN1_MALLOC_ENCODE(PKCS12_OctetString, pfx.authSafe.content->data, pfx.authSafe.content->length, &asdata, &size, ret); free(asdata.data); if (ret) goto out; ret = der_copy_oid(&asn1_oid_id_pkcs7_data, &pfx.authSafe.contentType); if (ret) goto out; ASN1_MALLOC_ENCODE(PKCS12_PFX, asdata.data, asdata.length, &pfx, &size, ret); if (ret) goto out; #if 0 const struct _hx509_password *pw; pw = _hx509_lock_get_passwords(lock); if (pw != NULL) { pfx.macData = calloc(1, sizeof(*pfx.macData)); if (pfx.macData == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "malloc out of memory"); return ret; } if (pfx.macData == NULL) { free(asdata.data); goto out; } } ret = calculate_hash(&aspath, pw, pfx.macData); #endif rk_dumpdata(p12->fn, asdata.data, asdata.length); free(asdata.data); out: free_PKCS12_AuthenticatedSafe(&as); free_PKCS12_PFX(&pfx); return ret; }