static int ShroudedKeyBag_parser(hx509_context context, struct hx509_collector *c, const void *data, size_t length, const PKCS12_Attributes *attrs) { PKCS8EncryptedPrivateKeyInfo pk; heim_octet_string content; int ret; memset(&pk, 0, sizeof(pk)); ret = decode_PKCS8EncryptedPrivateKeyInfo(data, length, &pk, NULL); if (ret) return ret; ret = _hx509_pbe_decrypt(context, _hx509_collector_get_lock(c), &pk.encryptionAlgorithm, &pk.encryptedData, &content); free_PKCS8EncryptedPrivateKeyInfo(&pk); if (ret) return ret; ret = keyBag_parser(context, c, content.data, content.length, attrs); der_free_octet_string(&content); return ret; }
static int encryptedData_parser(hx509_context context, struct hx509_collector *c, const void *data, size_t length, const PKCS12_Attributes *attrs) { heim_octet_string content; heim_oid contentType; int ret; memset(&contentType, 0, sizeof(contentType)); ret = hx509_cms_decrypt_encrypted(context, _hx509_collector_get_lock(c), data, length, &contentType, &content); if (ret) return ret; if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) ret = parse_safe_content(context, c, content.data, content.length); der_free_octet_string(&content); der_free_oid(&contentType); return ret; }
static int envelopedData_parser(hx509_context context, struct hx509_collector *c, const void *data, size_t length, const PKCS12_Attributes *attrs) { heim_octet_string content; heim_oid contentType; hx509_lock lock; int ret; memset(&contentType, 0, sizeof(contentType)); lock = _hx509_collector_get_lock(c); ret = hx509_cms_unenvelope(context, _hx509_lock_unlock_certs(lock), 0, data, length, NULL, 0, &contentType, &content); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "PKCS12 failed to unenvelope"); return ret; } if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) ret = parse_safe_content(context, c, content.data, content.length); der_free_octet_string(&content); der_free_oid(&contentType); return ret; }
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; }