EP_STAT ep_crypto_key_write_mem(EP_CRYPTO_KEY *key, void *buf, size_t buflen, int keyform, int keyenc, const char *passwd, uint32_t flags) { EP_STAT estat; BIO *bio; if (EP_UT_BITSET(EP_CRYPTO_F_SECRET, flags)) bio = BIO_new(BIO_s_secmem()); else bio = BIO_new(BIO_s_mem()); estat = key_write_bio(key, bio, keyform, keyenc, passwd, flags); if (EP_STAT_ISOK(estat)) { // save the memory size_t len = EP_STAT_TO_INT(estat); if (len > buflen) { (void) _ep_crypto_error("external keyform too long, wants %z, needs %z", len, buflen); estat = EP_STAT_CRYPTO_CONVERT; } else { void *p; BIO_get_mem_data(bio, &p); memcpy(buf, p, len); } } BIO_free(bio); return estat; }
/** * Read in PEM-formatted data from the given BIO. * * By nature of the PEM format, all content must be printable ASCII (except * for line endings). Other characters are malformed input and will be rejected. */ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, unsigned char **data, long *len_out, unsigned int flags) { EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); const BIO_METHOD *bmeth; BIO *headerB = NULL, *dataB = NULL; char *name = NULL; int len, taillen, headerlen, ret = 0; BUF_MEM * buf_mem; if (ctx == NULL) { PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE); return 0; } *len_out = 0; *name_out = *header = NULL; *data = NULL; if ((flags & PEM_FLAG_EAY_COMPATIBLE) && (flags & PEM_FLAG_ONLY_B64)) { /* These two are mutually incompatible; bail out. */ PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_PASSED_INVALID_ARGUMENT); goto end; } bmeth = (flags & PEM_FLAG_SECURE) ? BIO_s_secmem() : BIO_s_mem(); headerB = BIO_new(bmeth); dataB = BIO_new(bmeth); if (headerB == NULL || dataB == NULL) { PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE); goto end; } if (!get_name(bp, &name, flags)) goto end; if (!get_header_and_data(bp, &headerB, &dataB, name, flags)) goto end; EVP_DecodeInit(ctx); BIO_get_mem_ptr(dataB, &buf_mem); len = buf_mem->length; if (EVP_DecodeUpdate(ctx, (unsigned char*)buf_mem->data, &len, (unsigned char*)buf_mem->data, len) < 0 || EVP_DecodeFinal(ctx, (unsigned char*)&(buf_mem->data[len]), &taillen) < 0) { PEMerr(PEM_F_PEM_READ_BIO_EX, PEM_R_BAD_BASE64_DECODE); goto end; } len += taillen; buf_mem->length = len; /* There was no data in the PEM file; avoid malloc(0). */ if (len == 0) goto end; headerlen = BIO_get_mem_data(headerB, NULL); *header = pem_malloc(headerlen + 1, flags); *data = pem_malloc(len, flags); if (*header == NULL || *data == NULL) { pem_free(*header, flags, 0); pem_free(*data, flags, 0); goto end; } BIO_read(headerB, *header, headerlen); (*header)[headerlen] = '\0'; BIO_read(dataB, *data, len); *len_out = len; *name_out = name; name = NULL; ret = 1; end: EVP_ENCODE_CTX_free(ctx); pem_free(name, flags, 0); BIO_free(headerB); BIO_free(dataB); return ret; }