int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
                       ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
{
    const EVP_CIPHER *cipher;
    const EVP_MD *md;
    int cipher_nid, md_nid;
    EVP_PBE_KEYGEN *keygen;

    if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
                      &cipher_nid, &md_nid, &keygen)) {
        char obj_tmp[80];
        EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_PBE_ALGORITHM);
        if (!pbe_obj)
            OPENSSL_strlcpy(obj_tmp, "NULL", sizeof obj_tmp);
        else
            i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, pbe_obj);
        ERR_add_error_data(2, "TYPE=", obj_tmp);
        return 0;
    }

    if (!pass)
        passlen = 0;
    else if (passlen == -1)
        passlen = strlen(pass);

    if (cipher_nid == -1)
        cipher = NULL;
    else {
        cipher = EVP_get_cipherbynid(cipher_nid);
        if (!cipher) {
            EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_CIPHER);
            return 0;
        }
    }

    if (md_nid == -1)
        md = NULL;
    else {
        md = EVP_get_digestbynid(md_nid);
        if (!md) {
            EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_DIGEST);
            return 0;
        }
    }

    if (!keygen(ctx, pass, passlen, param, cipher, md, en_de)) {
        EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_KEYGEN_FAILURE);
        return 0;
    }
    return 1;
}