#include "apps.h"
#include "internal/sockets.h" /* for openssl_fdset() */
+#include "internal/numbers.h" /* for LONG_MAX */
#include "internal/e_os.h"
#ifdef _WIN32
}
/*
- * Read whole contents of a BIO into an allocated memory buffer and return
- * it.
+ * Read whole contents of a BIO into an allocated memory buffer.
+ * The return value is one on success, zero on error.
+ * If `maxlen` is non-zero, at most `maxlen` bytes are returned, or else, if
+ * the input is longer than `maxlen`, an error is returned.
+ * If `maxlen` is zero, the limit is effectively `SIZE_MAX`.
*/
-
-int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
+int bio_to_mem(unsigned char **out, size_t *outlen, size_t maxlen, BIO *in)
{
+ unsigned char tbuf[4096];
BIO *mem;
- int len, ret;
- unsigned char tbuf[1024];
+ BUF_MEM *bufm;
+ size_t sz = 0;
+ int len;
mem = BIO_new(BIO_s_mem());
if (mem == NULL)
- return -1;
+ return 0;
for (;;) {
- if ((maxlen != -1) && maxlen < 1024)
- len = maxlen;
- else
- len = 1024;
- len = BIO_read(in, tbuf, len);
- if (len < 0) {
- BIO_free(mem);
- return -1;
- }
- if (len == 0)
+ if ((len = BIO_read(in, tbuf, 4096)) == 0)
break;
- if (BIO_write(mem, tbuf, len) != len) {
+ if (len < 0
+ || BIO_write(mem, tbuf, len) != len
+ || sz > SIZE_MAX - len
+ || ((sz += len) > maxlen && maxlen != 0)) {
BIO_free(mem);
- return -1;
+ return 0;
}
- if (maxlen != -1)
- maxlen -= len;
-
- if (maxlen == 0)
- break;
}
- ret = BIO_get_mem_data(mem, (char **)out);
- BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
+
+ /* So BIO_free orphans BUF_MEM */
+ (void)BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_get_mem_ptr(mem, &bufm);
BIO_free(mem);
- return ret;
+ *out = (unsigned char *)bufm->data;
+ *outlen = bufm->length;
+ /* Tell BUF_MEM to orphan data */
+ bufm->data = NULL;
+ BUF_MEM_free(bufm);
+ return 1;
}
int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
EVP_PKEY *pkey, BIO *in,
- int filesize, unsigned char *sig, int siglen,
+ int filesize, unsigned char *sig, size_t siglen,
unsigned char **out, size_t *poutlen);
static int only_nomd(EVP_PKEY *pkey)
char hexdump = 0, asn1parse = 0, rev = 0, *prog;
unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL, *secret = NULL;
OPTION_CHOICE o;
- int buf_inlen = 0, siglen = -1;
+ size_t buf_inlen = 0, siglen = 0;
int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF;
int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
int ret = 1, rv = -1;
if (sigfile != NULL) {
BIO *sigbio = BIO_new_file(sigfile, "rb");
+ size_t maxsiglen = 16 * 1024 * 1024;
if (sigbio == NULL) {
BIO_printf(bio_err, "Can't open signature file %s\n", sigfile);
goto end;
}
- siglen = bio_to_mem(&sig, keysize * 10, sigbio);
- BIO_free(sigbio);
- if (siglen < 0) {
+ if (!bio_to_mem(&sig, &siglen, maxsiglen, sigbio)) {
+ BIO_free(sigbio);
BIO_printf(bio_err, "Error reading signature data\n");
goto end;
}
+ BIO_free(sigbio);
}
/* Raw input data is handled elsewhere */
if (in != NULL && !rawin) {
/* Read the input data */
- buf_inlen = bio_to_mem(&buf_in, -1, in);
- if (buf_inlen < 0) {
+ if (!bio_to_mem(&buf_in, &buf_inlen, 0, in)) {
BIO_printf(bio_err, "Error reading input Data\n");
goto end;
}
if (rev) {
size_t i;
unsigned char ctmp;
- size_t l = (size_t)buf_inlen;
+ size_t l = buf_inlen;
for (i = 0; i < l / 2; i++) {
ctmp = buf_in[i];
&& (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY)) {
if (buf_inlen > EVP_MAX_MD_SIZE) {
BIO_printf(bio_err,
- "Error: The non-raw input data length %d is too long - max supported hashed size is %d\n",
+ "Error: The non-raw input data length %zd is too long - "
+ "max supported hashed size is %d\n",
buf_inlen, EVP_MAX_MD_SIZE);
goto end;
}
rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen,
NULL, 0);
} else {
- rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
- buf_in, (size_t)buf_inlen);
+ rv = EVP_PKEY_verify(ctx, sig, siglen, buf_in, buf_inlen);
}
if (rv == 1) {
BIO_puts(out, "Signature Verified Successfully\n");
rv = 1;
} else {
rv = do_keyop(ctx, pkey_op, NULL, &buf_outlen,
- buf_in, (size_t)buf_inlen, NULL, &secretlen);
+ buf_in, buf_inlen, NULL, &secretlen);
}
if (rv > 0
&& (secretlen > 0 || (pkey_op != EVP_PKEY_OP_ENCAPSULATE && pkey_op != EVP_PKEY_OP_DECAPSULATE))
secret = app_malloc(secretlen, "secret output");
rv = do_keyop(ctx, pkey_op,
buf_out, &buf_outlen,
- buf_in, (size_t)buf_inlen, secret, &secretlen);
+ buf_in, buf_inlen, secret, &secretlen);
}
}
if (rv <= 0) {
static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
EVP_PKEY *pkey, BIO *in,
- int filesize, unsigned char *sig, int siglen,
+ int filesize, unsigned char *sig, size_t siglen,
unsigned char **out, size_t *poutlen)
{
int rv = 0;
BIO_printf(bio_err, "Error reading raw input data\n");
goto end;
}
- rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len);
+ rv = EVP_DigestVerify(mctx, sig, siglen, mbuf, buf_len);
break;
case EVP_PKEY_OP_SIGN:
buf_len = BIO_read(in, mbuf, filesize);
goto end;
}
}
- rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
+ rv = EVP_DigestVerifyFinal(mctx, sig, siglen);
break;
case EVP_PKEY_OP_SIGN:
for (;;) {