int pem_check_suffix(const char *pem_str, const char *suffix)
{
    int pem_len = strlen(pem_str);
    int suffix_len = strlen(suffix);
    const char *p;
    if (suffix_len + 1 >= pem_len)
        return 0;
    p = pem_str + pem_len - suffix_len;
    if (strcmp(p, suffix))
        return 0;
    p--;
    if (*p != ' ')
        return 0;
    return p - pem_str;
}
['EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,\n                                  void *u)\n{\n    char *nm = NULL;\n    const unsigned char *p = NULL;\n    unsigned char *data = NULL;\n    long len;\n    int slen;\n    EVP_PKEY *ret = NULL;\n    if (!PEM_bytes_read_bio_secmem(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp,\n\t\t\t\t   cb, u))\n        return NULL;\n    p = data;\n    if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) {\n        PKCS8_PRIV_KEY_INFO *p8inf;\n        p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);\n        if (!p8inf)\n            goto p8err;\n        ret = EVP_PKCS82PKEY(p8inf);\n        if (x) {\n            EVP_PKEY_free((EVP_PKEY *)*x);\n            *x = ret;\n        }\n        PKCS8_PRIV_KEY_INFO_free(p8inf);\n    } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) {\n        PKCS8_PRIV_KEY_INFO *p8inf;\n        X509_SIG *p8;\n        int klen;\n        char psbuf[PEM_BUFSIZE];\n        p8 = d2i_X509_SIG(NULL, &p, len);\n        if (!p8)\n            goto p8err;\n        if (cb)\n            klen = cb(psbuf, PEM_BUFSIZE, 0, u);\n        else\n            klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);\n        if (klen <= 0) {\n            PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ);\n            X509_SIG_free(p8);\n            goto err;\n        }\n        p8inf = PKCS8_decrypt(p8, psbuf, klen);\n        X509_SIG_free(p8);\n        if (!p8inf)\n            goto p8err;\n        ret = EVP_PKCS82PKEY(p8inf);\n        if (x) {\n            EVP_PKEY_free((EVP_PKEY *)*x);\n            *x = ret;\n        }\n        PKCS8_PRIV_KEY_INFO_free(p8inf);\n    } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) {\n        const EVP_PKEY_ASN1_METHOD *ameth;\n        ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);\n        if (!ameth || !ameth->old_priv_decode)\n            goto p8err;\n        ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len);\n    }\n p8err:\n    if (ret == NULL)\n        PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, ERR_R_ASN1_LIB);\n err:\n    OPENSSL_secure_free(nm);\n    OPENSSL_secure_free(data);\n    return (ret);\n}', 'int PEM_bytes_read_bio_secmem(unsigned char **pdata, long *plen, char **pnm,\n                              const char *name, BIO *bp, pem_password_cb *cb,\n                              void *u) {\n    return pem_bytes_read_bio_flags(pdata, plen, pnm, name, bp, cb, u,\n                                    PEM_FLAG_SECURE | PEM_FLAG_EAY_COMPATIBLE);\n}', 'static int pem_bytes_read_bio_flags(unsigned char **pdata, long *plen,\n                                    char **pnm, const char *name, BIO *bp,\n                                    pem_password_cb *cb, void *u,\n                                    unsigned int flags)\n{\n    EVP_CIPHER_INFO cipher;\n    char *nm = NULL, *header = NULL;\n    unsigned char *data = NULL;\n    long len;\n    int ret = 0;\n    do {\n        pem_free(nm, flags);\n        pem_free(header, flags);\n        pem_free(data, flags);\n        if (!PEM_read_bio_ex(bp, &nm, &header, &data, &len, flags)) {\n            if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)\n                ERR_add_error_data(2, "Expecting: ", name);\n            return 0;\n        }\n    } while (!check_pem(nm, name));\n    if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))\n        goto err;\n    if (!PEM_do_header(&cipher, data, &len, cb, u))\n        goto err;\n    *pdata = data;\n    *plen = len;\n    if (pnm != NULL)\n        *pnm = nm;\n    ret = 1;\n err:\n    if (!ret || pnm == NULL)\n        pem_free(nm, flags);\n    pem_free(header, flags);\n    if (!ret)\n        pem_free(data, flags);\n    return ret;\n}', "int PEM_read_bio_ex(BIO *bp, char **name_out, char **header,\n                    unsigned char **data, long *len_out, unsigned int flags)\n{\n    EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();\n    const BIO_METHOD *bmeth;\n    BIO *headerB = NULL, *dataB = NULL;\n    char *name = NULL;\n    int len, taillen, headerlen, ret = 0;\n    BUF_MEM * buf_mem;\n    if (ctx == NULL) {\n        PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE);\n        return 0;\n    }\n    *len_out = 0;\n    *name_out = *header = NULL;\n    *data = NULL;\n    if ((flags & PEM_FLAG_EAY_COMPATIBLE) && (flags & PEM_FLAG_ONLY_B64)) {\n        PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_PASSED_INVALID_ARGUMENT);\n        goto end;\n    }\n    bmeth = (flags & PEM_FLAG_SECURE) ? BIO_s_secmem() : BIO_s_mem();\n    headerB = BIO_new(bmeth);\n    dataB = BIO_new(bmeth);\n    if (headerB == NULL || dataB == NULL) {\n        PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE);\n        goto end;\n    }\n    if (!get_name(bp, &name, flags))\n        goto end;\n    if (!get_header_and_data(bp, &headerB, &dataB, name, flags))\n        goto end;\n    EVP_DecodeInit(ctx);\n    BIO_get_mem_ptr(dataB, &buf_mem);\n    len = buf_mem->length;\n    if (EVP_DecodeUpdate(ctx, (unsigned char*)buf_mem->data, &len,\n                         (unsigned char*)buf_mem->data, len) < 0\n            || EVP_DecodeFinal(ctx, (unsigned char*)&(buf_mem->data[len]),\n                               &taillen) < 0) {\n        PEMerr(PEM_F_PEM_READ_BIO_EX, PEM_R_BAD_BASE64_DECODE);\n        goto end;\n    }\n    len += taillen;\n    buf_mem->length = len;\n    if (len == 0)\n        goto end;\n    headerlen = BIO_get_mem_data(headerB, NULL);\n    *header = pem_malloc(headerlen + 1, flags);\n    *data = pem_malloc(len, flags);\n    if (*header == NULL || *data == NULL) {\n        pem_free(*header, flags);\n        pem_free(*data, flags);\n        goto end;\n    }\n    BIO_read(headerB, *header, headerlen);\n    (*header)[headerlen] = '\\0';\n    BIO_read(dataB, *data, len);\n    *len_out = len;\n    *name_out = name;\n    name = NULL;\n    ret = 1;\nend:\n    EVP_ENCODE_CTX_free(ctx);\n    pem_free(name, flags);\n    BIO_free(headerB);\n    BIO_free(dataB);\n    return ret;\n}", "int pem_check_suffix(const char *pem_str, const char *suffix)\n{\n    int pem_len = strlen(pem_str);\n    int suffix_len = strlen(suffix);\n    const char *p;\n    if (suffix_len + 1 >= pem_len)\n        return 0;\n    p = pem_str + pem_len - suffix_len;\n    if (strcmp(p, suffix))\n        return 0;\n    p--;\n    if (*p != ' ')\n        return 0;\n    return p - pem_str;\n}"]