[openssl] master update
Richard Levitte
levitte at openssl.org
Wed Dec 18 18:42:50 UTC 2019
The branch master has been updated
via 51a7c4b5f2a0b2d0f6bc0c87ec2ee44b9697dc78 (commit)
via f1299839b7763d293925d57b28f533ab24c084ad (commit)
via 0e79d20f1e9f9e32bfe45eb3760cb233fa8dfa5e (commit)
via e79ae962fbed99cf80feb32b326f701778ca7434 (commit)
via 319cee9e2fc6fcf6ad865564eccdac4c55e92c0a (commit)
via a0848daee50b30f441813ecc90042c6af14c62aa (commit)
from 8913378a552e470c66277c47b19699f20b84aa3b (commit)
- Log -----------------------------------------------------------------
commit 51a7c4b5f2a0b2d0f6bc0c87ec2ee44b9697dc78
Author: Richard Levitte <levitte at openssl.org>
Date: Thu Dec 12 14:51:59 2019 +0100
TEST: Add test recipe and help program to test BIO_f_prefix()
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10531)
commit f1299839b7763d293925d57b28f533ab24c084ad
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Nov 27 18:35:48 2019 +0100
EVP: Adapt EVP_PKEY_print_ routines to use BIO_f_prefix()
We take the opportunity to refactor EVP_PKEY_print_public,
EVP_PKEY_print_private, EVP_PKEY_print_params to lessen the amount of
code copying.
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10531)
commit 0e79d20f1e9f9e32bfe45eb3760cb233fa8dfa5e
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Nov 27 17:58:01 2019 +0100
ASN1: Adapt ASN.1 output routines to use BIO_f_prefix()
We modify asn1_print_info() to print the full line. It pushes a
BIO_f_prefix() BIO to the given |bp| if it can't detect that it's
already present, then uses both the prefix and indent settings to get
formatting right.
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10531)
commit e79ae962fbed99cf80feb32b326f701778ca7434
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Nov 27 16:13:12 2019 +0100
APPS & TEST: Adapt to use the new BIO_f_prefix()
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10531)
commit 319cee9e2fc6fcf6ad865564eccdac4c55e92c0a
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Nov 27 16:02:33 2019 +0100
BIO: Add BIO_f_prefix(), a text line prefixing filter
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10531)
commit a0848daee50b30f441813ecc90042c6af14c62aa
Author: Richard Levitte <levitte at openssl.org>
Date: Wed Nov 27 16:01:32 2019 +0100
crypto/bio/build.info: split the source files in categories
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10531)
-----------------------------------------------------------------------
Summary of changes:
apps/include/apps.h | 14 --
apps/lib/apps.c | 15 +-
apps/lib/build.info | 2 +-
apps/openssl.c | 15 +-
crypto/asn1/asn1_par.c | 62 +++---
{apps/lib => crypto/bio}/bf_prefix.c | 106 ++++++----
crypto/bio/build.info | 20 +-
crypto/evp/p_lib.c | 110 +++++++----
doc/man3/BIO_f_prefix.pod | 70 +++++++
include/openssl/bio.h | 11 ++
test/README | 5 +-
test/bio_prefix_text.c | 267 ++++++++++++++++++++++++++
test/build.info | 7 +-
test/recipes/61-test_bio_prefix.t | 55 ++++++
test/recipes/61-test_bio_prefix_data/args1.pl | 6 +
test/recipes/61-test_bio_prefix_data/args2.pl | 3 +
test/recipes/61-test_bio_prefix_data/in1.txt | 1 +
test/recipes/61-test_bio_prefix_data/in2.txt | 1 +
test/recipes/61-test_bio_prefix_data/out1.txt | 1 +
test/recipes/61-test_bio_prefix_data/out2.txt | 1 +
util/libcrypto.num | 1 +
util/other.syms | 3 +
22 files changed, 626 insertions(+), 150 deletions(-)
rename {apps/lib => crypto/bio}/bf_prefix.c (61%)
create mode 100644 doc/man3/BIO_f_prefix.pod
create mode 100644 test/bio_prefix_text.c
create mode 100644 test/recipes/61-test_bio_prefix.t
create mode 100644 test/recipes/61-test_bio_prefix_data/args1.pl
create mode 100644 test/recipes/61-test_bio_prefix_data/args2.pl
create mode 100644 test/recipes/61-test_bio_prefix_data/in1.txt
create mode 100644 test/recipes/61-test_bio_prefix_data/in2.txt
create mode 100644 test/recipes/61-test_bio_prefix_data/out1.txt
create mode 100644 test/recipes/61-test_bio_prefix_data/out2.txt
diff --git a/apps/include/apps.h b/apps/include/apps.h
index 21a2a90544..c33a98772b 100644
--- a/apps/include/apps.h
+++ b/apps/include/apps.h
@@ -58,20 +58,6 @@ extern const unsigned char tls13_aes128gcmsha256_id[];
extern const unsigned char tls13_aes256gcmsha384_id[];
extern BIO_ADDR *ourpeer;
-BIO_METHOD *apps_bf_prefix(void);
-/*
- * The control used to set the prefix with BIO_ctrl()
- * We make it high enough so the chance of ever clashing with the BIO library
- * remains unlikely for the foreseeable future and beyond.
- */
-#define PREFIX_CTRL_SET_PREFIX (1 << 15)
-/*
- * apps_bf_prefix() returns a dynamically created BIO_METHOD, which we
- * need to destroy at some point. When created internally, it's stored
- * in an internal pointer which can be freed with the following function
- */
-void destroy_prefix_method(void);
-
BIO *dup_bio_in(int format);
BIO *dup_bio_out(int format);
BIO *dup_bio_err(int format);
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index 8b840bb2a1..3a18cd007c 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -2324,8 +2324,8 @@ BIO *dup_bio_out(int format)
if (FMT_istext(format)
&& (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
- b = BIO_push(BIO_new(apps_bf_prefix()), b);
- BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix);
+ b = BIO_push(BIO_new(BIO_f_prefix()), b);
+ BIO_set_prefix(b, prefix);
}
return b;
@@ -2342,17 +2342,6 @@ BIO *dup_bio_err(int format)
return b;
}
-/*
- * Because the prefix method is created dynamically, we must also be able
- * to destroy it.
- */
-void destroy_prefix_method(void)
-{
- BIO_METHOD *prefix_method = apps_bf_prefix();
- BIO_meth_free(prefix_method);
- prefix_method = NULL;
-}
-
void unbuffer(FILE *fp)
{
/*
diff --git a/apps/lib/build.info b/apps/lib/build.info
index 7a2536af24..3f68a2ed35 100644
--- a/apps/lib/build.info
+++ b/apps/lib/build.info
@@ -9,7 +9,7 @@ ENDIF
# Source for libapps
$LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \
- bf_prefix.c columns.c app_params.c names.c
+ columns.c app_params.c names.c
IF[{- !$disabled{apps} -}]
LIBS{noinst}=../libapps.a
diff --git a/apps/openssl.c b/apps/openssl.c
index d60267d742..00ad9ca0bd 100644
--- a/apps/openssl.c
+++ b/apps/openssl.c
@@ -116,8 +116,7 @@ static size_t internal_trace_cb(const char *buf, size_t cnt,
hex == NULL ? "<null>" : hex,
OSSL_trace_get_category_name(category));
OPENSSL_free(hex);
- BIO_ctrl(trace_data->bio, PREFIX_CTRL_SET_PREFIX,
- strlen(buffer), buffer);
+ BIO_set_prefix(trace_data->bio, buffer);
break;
case OSSL_TRACE_CTRL_WRITE:
if (!ossl_assert(trace_data->ingroup))
@@ -130,7 +129,7 @@ static size_t internal_trace_cb(const char *buf, size_t cnt,
return 0;
trace_data->ingroup = 0;
- BIO_ctrl(trace_data->bio, PREFIX_CTRL_SET_PREFIX, 0, NULL);
+ BIO_set_prefix(trace_data->bio, NULL);
break;
}
@@ -162,8 +161,7 @@ static void setup_trace_category(int category)
if (OSSL_trace_enabled(category))
return;
- channel = BIO_push(BIO_new(apps_bf_prefix()),
- dup_bio_err(FORMAT_TEXT));
+ channel = BIO_push(BIO_new(BIO_f_prefix()), dup_bio_err(FORMAT_TEXT));
trace_data = OPENSSL_zalloc(sizeof(*trace_data));
if (trace_data == NULL
@@ -247,13 +245,6 @@ int main(int argc, char *argv[])
win32_utf8argv(&argc, &argv);
#endif
- /*
- * We use the prefix method to get the trace output we want. Since some
- * trace outputs happen with OPENSSL_cleanup(), which is run automatically
- * after exit(), we need to destroy the prefix method as late as possible.
- */
- atexit(destroy_prefix_method);
-
#ifndef OPENSSL_NO_TRACE
setup_trace(getenv("OPENSSL_TRACE"));
#endif
diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c
index f722bed0b5..eaba666cf2 100644
--- a/crypto/asn1/asn1_par.c
+++ b/crypto/asn1/asn1_par.c
@@ -17,25 +17,44 @@
#define ASN1_PARSE_MAXDEPTH 128
#endif
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
- int indent);
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
int offset, int depth, int indent, int dump);
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
- int indent)
+static int asn1_print_info(BIO *bp, long offset, int depth, int hl, long len,
+ int tag, int xclass, int constructed, int indent)
{
- static const char fmt[] = "%-18s";
char str[128];
const char *p;
+ int pop_f_prefix = 0;
+ long saved_indent = -1;
+ int i = 0;
if (constructed & V_ASN1_CONSTRUCTED)
p = "cons: ";
else
p = "prim: ";
- if (BIO_write(bp, p, 6) < 6)
+ if (constructed != (V_ASN1_CONSTRUCTED | 1)) {
+ if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=%4ld %s",
+ offset, depth, (long)hl, len, p) <= 0)
+ goto err;
+ } else {
+ if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=inf %s",
+ offset, depth, (long)hl, p) <= 0)
+ goto err;
+ }
+ if (BIO_set_prefix(bp, str) <= 0) {
+ if ((bp = BIO_push(BIO_new(BIO_f_prefix()), bp)) == NULL)
+ goto err;
+ pop_f_prefix = 1;
+ }
+ saved_indent = BIO_get_indent(bp);
+ if (BIO_set_prefix(bp, str) <= 0
+ || BIO_set_indent(bp, indent) < 0)
goto err;
- BIO_indent(bp, indent, 128);
+ /*
+ * BIO_set_prefix made a copy of |str|, so we can safely use it for
+ * something else, ASN.1 tag printout.
+ */
p = str;
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
@@ -48,11 +67,17 @@ static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
else
p = ASN1_tag2str(tag);
- if (BIO_printf(bp, fmt, p) <= 0)
- goto err;
- return 1;
+ i = (BIO_printf(bp, "%-18s", p) > 0);
err:
- return 0;
+ if (saved_indent >= 0)
+ BIO_set_indent(bp, saved_indent);
+ if (pop_f_prefix) {
+ BIO *next = BIO_pop(bp);
+
+ BIO_free(bp);
+ bp = next;
+ }
+ return i;
}
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
@@ -100,19 +125,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
/*
* if j == 0x21 it is a constructed indefinite length object
*/
- if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
- <= 0)
- goto end;
-
- if (j != (V_ASN1_CONSTRUCTED | 1)) {
- if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
- depth, (long)hl, len) <= 0)
- goto end;
- } else {
- if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0)
- goto end;
- }
- if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
+ if (!asn1_print_info(bp, (long)offset + (long)(op - *pp), depth,
+ hl, len, tag, xclass, j, (indent) ? depth : 0))
goto end;
if (j & V_ASN1_CONSTRUCTED) {
const unsigned char *sp = p;
diff --git a/apps/lib/bf_prefix.c b/crypto/bio/bf_prefix.c
similarity index 61%
rename from apps/lib/bf_prefix.c
rename to crypto/bio/bf_prefix.c
index 8cedca90ce..5727c14950 100644
--- a/apps/lib/bf_prefix.c
+++ b/crypto/bio/bf_prefix.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -10,8 +10,7 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
-#include <openssl/bio.h>
-#include "apps.h"
+#include "bio_local.h"
static int prefix_write(BIO *b, const char *out, size_t outl,
size_t *numwritten);
@@ -23,31 +22,31 @@ static int prefix_create(BIO *b);
static int prefix_destroy(BIO *b);
static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
-static BIO_METHOD *prefix_meth = NULL;
-
-BIO_METHOD *apps_bf_prefix(void)
+static const BIO_METHOD prefix_meth = {
+ BIO_TYPE_BUFFER,
+ "prefix",
+ prefix_write,
+ NULL,
+ prefix_read,
+ NULL,
+ prefix_puts,
+ prefix_gets,
+ prefix_ctrl,
+ prefix_create,
+ prefix_destroy,
+ prefix_callback_ctrl,
+};
+
+const BIO_METHOD *BIO_f_prefix(void)
{
- if (prefix_meth == NULL) {
- if ((prefix_meth =
- BIO_meth_new(BIO_TYPE_FILTER, "Prefix filter")) == NULL
- || !BIO_meth_set_create(prefix_meth, prefix_create)
- || !BIO_meth_set_destroy(prefix_meth, prefix_destroy)
- || !BIO_meth_set_write_ex(prefix_meth, prefix_write)
- || !BIO_meth_set_read_ex(prefix_meth, prefix_read)
- || !BIO_meth_set_puts(prefix_meth, prefix_puts)
- || !BIO_meth_set_gets(prefix_meth, prefix_gets)
- || !BIO_meth_set_ctrl(prefix_meth, prefix_ctrl)
- || !BIO_meth_set_callback_ctrl(prefix_meth, prefix_callback_ctrl)) {
- BIO_meth_free(prefix_meth);
- prefix_meth = NULL;
- }
- }
- return prefix_meth;
+ return &prefix_meth;
}
typedef struct prefix_ctx_st {
- char *prefix;
- int linestart; /* flag to indicate we're at the line start */
+ char *prefix; /* Text prefix, given by user */
+ unsigned int indent; /* Indentation amount, given by user */
+
+ int linestart; /* flag to indicate we're at the line start */
} PREFIX_CTX;
static int prefix_create(BIO *b)
@@ -58,6 +57,7 @@ static int prefix_create(BIO *b)
return 0;
ctx->prefix = NULL;
+ ctx->indent = 0;
ctx->linestart = 1;
BIO_set_data(b, ctx);
BIO_set_init(b, 1);
@@ -86,9 +86,16 @@ static int prefix_write(BIO *b, const char *out, size_t outl,
if (ctx == NULL)
return 0;
- /* If no prefix is set or if it's empty, we've got nothing to do here */
- if (ctx->prefix == NULL || *ctx->prefix == '\0') {
- /* We do note if what comes next will be a new line, though */
+ /*
+ * If no prefix is set or if it's empty, and no indentation amount is set,
+ * we've got nothing to do here
+ */
+ if ((ctx->prefix == NULL || *ctx->prefix == '\0')
+ && ctx->indent == 0) {
+ /*
+ * We do note if what comes next will be a new line, though, so we're
+ * prepared to handle prefix and indentation the next time around.
+ */
if (outl > 0)
ctx->linestart = (out[outl-1] == '\n');
return BIO_write_ex(BIO_next(b), out, outl, numwritten);
@@ -100,13 +107,18 @@ static int prefix_write(BIO *b, const char *out, size_t outl,
size_t i;
char c;
- /* If we know that we're at the start of the line, output the prefix */
+ /*
+ * If we know that we're at the start of the line, output prefix and
+ * indentation.
+ */
if (ctx->linestart) {
size_t dontcare;
- if (!BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix),
- &dontcare))
+ if (ctx->prefix != NULL
+ && !BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix),
+ &dontcare))
return 0;
+ BIO_printf(BIO_next(b), "%*s", ctx->indent, "");
ctx->linestart = 0;
}
@@ -139,21 +151,39 @@ static int prefix_write(BIO *b, const char *out, size_t outl,
static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret = 0;
+ PREFIX_CTX *ctx = BIO_get_data(b);
- switch (cmd) {
- case PREFIX_CTRL_SET_PREFIX:
- {
- PREFIX_CTX *ctx = BIO_get_data(b);
-
- if (ctx == NULL)
- break;
+ if (ctx == NULL)
+ return -1;
- OPENSSL_free(ctx->prefix);
+ switch (cmd) {
+ case BIO_CTRL_SET_PREFIX:
+ OPENSSL_free(ctx->prefix);
+ if (ptr == NULL) {
+ ctx->prefix = NULL;
+ ret = 1;
+ } else {
ctx->prefix = OPENSSL_strdup((const char *)ptr);
ret = ctx->prefix != NULL;
}
break;
+ case BIO_CTRL_SET_INDENT:
+ if (num >= 0) {
+ ctx->indent = (unsigned int)num;
+ ret = 1;
+ }
+ break;
+ case BIO_CTRL_GET_INDENT:
+ ret = (long)ctx->indent;
+ break;
default:
+ /* Commands that we intercept before passing them along */
+ switch (cmd) {
+ case BIO_C_FILE_SEEK:
+ case BIO_CTRL_RESET:
+ ctx->linestart = 1;
+ break;
+ }
if (BIO_next(b) != NULL)
ret = BIO_ctrl(BIO_next(b), cmd, num, ptr);
break;
diff --git a/crypto/bio/build.info b/crypto/bio/build.info
index d1e7d73c55..8e3f530f88 100644
--- a/crypto/bio/build.info
+++ b/crypto/bio/build.info
@@ -1,8 +1,18 @@
LIBS=../../libcrypto
+
+# Base library
SOURCE[../../libcrypto]=\
bio_lib.c bio_cb.c bio_err.c \
- bss_mem.c bss_null.c bss_fd.c \
- bss_file.c bss_sock.c bss_conn.c \
- bf_null.c bf_buff.c b_print.c b_dump.c b_addr.c \
- b_sock.c b_sock2.c bss_acpt.c bf_nbio.c bss_log.c bss_bio.c \
- bss_dgram.c bio_meth.c bf_lbuf.c
+ b_print.c b_dump.c b_addr.c \
+ b_sock.c b_sock2.c \
+ bio_meth.c
+
+# Source / sink implementations
+SOURCE[../../libcrypto]=\
+ bss_null.c bss_mem.c bss_bio.c bss_fd.c bss_file.c \
+ bss_sock.c bss_conn.c bss_acpt.c bss_dgram.c \
+ bss_log.c
+
+# Filters
+SOURCE[../../libcrypto]=\
+ bf_null.c bf_buff.c bf_lbuf.c bf_nbio.c bf_prefix.c
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 99d6063e3e..9999636cfd 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -657,6 +657,40 @@ static void EVP_PKEY_free_it(EVP_PKEY *x)
#endif
}
+static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent)
+{
+ BIO_set_indent(*out, saved_indent);
+ if (pop_f_prefix) {
+ BIO *next = BIO_pop(*out);
+
+ BIO_free(*out);
+ *out = next;
+ }
+ return 1;
+}
+
+static int print_set_indent(BIO **out, int *pop_f_prefix, long *saved_indent,
+ long indent)
+{
+ *pop_f_prefix = 0;
+ *saved_indent = 0;
+ if (indent > 0) {
+ long i = BIO_get_indent(*out);
+
+ *saved_indent = (i < 0 ? 0 : i);
+ if (BIO_set_indent(*out, indent) <= 0) {
+ if ((*out = BIO_push(BIO_new(BIO_f_prefix()), *out)) == NULL)
+ return 0;
+ *pop_f_prefix = 1;
+ }
+ if (BIO_set_indent(*out, indent) <= 0) {
+ print_reset_indent(out, *pop_f_prefix, *saved_indent);
+ return 0;
+ }
+ }
+ return 1;
+}
+
static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
const char *kstr)
{
@@ -666,67 +700,61 @@ static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
return 1;
}
-int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
- int indent, ASN1_PCTX *pctx)
+static int print_pkey(const EVP_PKEY *pkey, BIO *out, int indent,
+ const char *propquery /* For provided serialization */,
+ int (*legacy_print)(BIO *out, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx),
+ ASN1_PCTX *legacy_pctx /* For legacy print */)
{
- const char *pq = OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ;
- OSSL_SERIALIZER_CTX *ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, pq);
- int ret = -2; /* mark as unsupported */
+ int pop_f_prefix;
+ long saved_indent;
+ OSSL_SERIALIZER_CTX *ctx = NULL;
+ int ret = -2; /* default to unsupported */
+
+ if (!print_set_indent(&out, &pop_f_prefix, &saved_indent, indent))
+ return 0;
+ ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, propquery);
if (OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL)
ret = OSSL_SERIALIZER_to_bio(ctx, out);
OSSL_SERIALIZER_CTX_free(ctx);
if (ret != -2)
- return ret;
+ goto end;
/* legacy fallback */
- if (pkey->ameth && pkey->ameth->pub_print)
- return pkey->ameth->pub_print(out, pkey, indent, pctx);
+ if (legacy_print != NULL)
+ ret = legacy_print(out, pkey, 0, legacy_pctx);
+ else
+ ret = unsup_alg(out, pkey, 0, "Public Key");
- return unsup_alg(out, pkey, indent, "Public Key");
+ end:
+ print_reset_indent(&out, pop_f_prefix, saved_indent);
+ return ret;
+}
+
+int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx)
+{
+ return print_pkey(pkey, out, indent, OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ,
+ (pkey->ameth != NULL ? pkey->ameth->pub_print : NULL),
+ pctx);
}
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
- const char *pq = OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ;
- OSSL_SERIALIZER_CTX *ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, pq);
- int ret = -2; /* mark as unsupported */
-
- if (OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL)
- ret = OSSL_SERIALIZER_to_bio(ctx, out);
- OSSL_SERIALIZER_CTX_free(ctx);
-
- if (ret != -2)
- return ret;
-
- /* legacy fallback */
- if (pkey->ameth && pkey->ameth->priv_print)
- return pkey->ameth->priv_print(out, pkey, indent, pctx);
-
- return unsup_alg(out, pkey, indent, "Private Key");
+ return print_pkey(pkey, out, indent, OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ,
+ (pkey->ameth != NULL ? pkey->ameth->priv_print : NULL),
+ pctx);
}
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
- const char *pq = OSSL_SERIALIZER_Parameters_TO_TEXT_PQ;
- OSSL_SERIALIZER_CTX *ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, pq);
- int ret = -2; /* mark as unsupported */
-
- if (OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL)
- ret = OSSL_SERIALIZER_to_bio(ctx, out);
- OSSL_SERIALIZER_CTX_free(ctx);
-
- if (ret != -2)
- return ret;
-
- /* legacy fallback */
- if (pkey->ameth && pkey->ameth->param_print)
- return pkey->ameth->param_print(out, pkey, indent, pctx);
-
- return unsup_alg(out, pkey, indent, "Parameters");
+ return print_pkey(pkey, out, indent, OSSL_SERIALIZER_Parameters_TO_TEXT_PQ,
+ (pkey->ameth != NULL ? pkey->ameth->param_print : NULL),
+ pctx);
}
static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2)
diff --git a/doc/man3/BIO_f_prefix.pod b/doc/man3/BIO_f_prefix.pod
new file mode 100644
index 0000000000..b4d0298b2a
--- /dev/null
+++ b/doc/man3/BIO_f_prefix.pod
@@ -0,0 +1,70 @@
+=pod
+
+=head1 NAME
+
+BIO_f_prefix, BIO_set_prefix, BIO_set_indent, BIO_get_indent
+- prefix BIO filter
+
+=head1 SYNOPSIS
+
+ #include <openssl/bio.h>
+
+ const BIO_METHOD *BIO_f_prefix(void);
+ long BIO_set_prefix(BIO *b, const char *prefix);
+ long BIO_set_indent(BIO *b, long indent);
+ long BIO_get_indent(BIO *b);
+
+=head1 DESCRIPTION
+
+BIO_f_cipher() returns the prefix BIO method. This is a filter for
+text output, where each line gets automatically prefixed and indented
+according to user input.
+
+The prefix and the indentation are combined. For each line of output
+going through this filter, the prefix is output first, then the amount
+of additional spaces indicated by the indentation, and then the line
+itself.
+
+By default, there is no prefix, and indentation is set to 0.
+
+BIO_set_prefix() sets the prefix to be used for future lines of
+text, using I<prefix>. I<prefix> may be NULL, signifying that there
+should be no prefix. If I<prefix> isn't NULL, this function makes a
+copy of it.
+
+BIO_set_indent() sets the indentation to be used for future lines of
+text, using I<indent>. Negative values are not allowed.
+
+BIO_get_indent() gets the current indentation.
+
+=head1 NOTES
+
+BIO_set_prefix(), BIO_set_indent() and BIO_get_indent() are
+implemented as macros.
+
+=head1 RETURN VALUES
+
+BIO_f_prefix() returns the prefix BIO method.
+
+BIO_set_prefix() returns 1 if the prefix was correctly set, or 0 on
+failure.
+
+BIO_set_indent() returns 1 if the prefix was correctly set, or 0 on
+failure.
+
+BIO_get_indent() returns the current indentation.
+
+=head1 SEE ALSO
+
+L<bio(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index ed9ecc6cca..50ac82cc31 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -160,6 +160,11 @@ extern "C" {
# define BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY 77
# define BIO_CTRL_DGRAM_SCTP_MSG_WAITING 78
+/* BIO_f_prefix controls */
+# define BIO_CTRL_SET_PREFIX 79
+# define BIO_CTRL_SET_INDENT 80
+# define BIO_CTRL_GET_INDENT 81
+
# ifndef OPENSSL_NO_KTLS
# define BIO_get_ktls_send(b) \
BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL)
@@ -552,6 +557,11 @@ int BIO_ctrl_reset_read_request(BIO *b);
# define BIO_dgram_get_mtu_overhead(b) \
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
+/* ctrl macros for BIO_f_prefix */
+# define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p))
+# define BIO_set_indent(b,i) BIO_ctrl((b), BIO_CTRL_SET_INDENT, (i), NULL)
+# define BIO_get_indent(b) BIO_ctrl((b), BIO_CTRL_GET_INDENT, 0, NULL)
+
#define BIO_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef)
int BIO_set_ex_data(BIO *bio, int idx, void *data);
@@ -630,6 +640,7 @@ const BIO_METHOD *BIO_f_null(void);
const BIO_METHOD *BIO_f_buffer(void);
const BIO_METHOD *BIO_f_linebuffer(void);
const BIO_METHOD *BIO_f_nbio_test(void);
+const BIO_METHOD *BIO_f_prefix(void);
# ifndef OPENSSL_NO_DGRAM
const BIO_METHOD *BIO_s_datagram(void);
int BIO_dgram_non_fatal_error(int error);
diff --git a/test/README b/test/README
index 9a0938146e..17dffa0e7f 100644
--- a/test/README
+++ b/test/README
@@ -27,7 +27,10 @@ The number {nn} is (somewhat loosely) grouped as follows:
20-24 openssl commands (some otherwise not tested)
25-29 certificate forms, generation and verification
30-35 engine and evp
-60-79 APIs
+60-79 APIs:
+ 60 X509 subsystem
+ 61 BIO subsystem
+ 65 CMP subsystem
70 PACKET layer
80-89 "larger" protocols (CA, CMS, OCSP, SSL, TSA)
90-98 misc
diff --git a/test/bio_prefix_text.c b/test/bio_prefix_text.c
new file mode 100644
index 0000000000..4fc468a976
--- /dev/null
+++ b/test/bio_prefix_text.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include <openssl/bio.h>
+#include <openssl/safestack.h>
+#include "opt.h"
+
+static BIO *bio_in = NULL;
+static BIO *bio_out = NULL;
+static BIO *bio_err = NULL;
+
+/*-
+ * This program sets up a chain of BIO_f_filter() on top of bio_out, how
+ * many is governed by the user through -n. It allows the user to set the
+ * indentation for each individual filter using -i and -p. Then it reads
+ * text from bio_in and prints it out through the BIO chain.
+ *
+ * The filter index is counted from the source/sink, i.e. index 0 is closest
+ * to it.
+ *
+ * Example:
+ *
+ * $ echo foo | ./bio_prefix_text -n 2 -i 1:32 -p 1:FOO -i 0:3
+ * FOO foo
+ * ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * | |
+ * | +------ 32 spaces from filter 1
+ * +-------------------------- 3 spaces from filter 0
+ */
+
+static size_t amount = 0;
+static BIO **chain = NULL;
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1,
+ OPT_EOF = 0,
+ OPT_AMOUNT,
+ OPT_INDENT,
+ OPT_PREFIX
+} OPTION_CHOICE;
+
+static const OPTIONS options[] = {
+ { "n", OPT_AMOUNT, 'p', "Amount of BIO_f_prefix() filters" },
+ /*
+ * idx is the index to the BIO_f_filter chain(), where 0 is closest
+ * to the source/sink BIO. If idx isn't given, 0 is assumed
+ */
+ { "i", OPT_INDENT, 's', "Indentation in form '[idx:]indent'" },
+ { "p", OPT_PREFIX, 's', "Prefix in form '[idx:]prefix'" },
+ { NULL }
+};
+
+int opt_printf_stderr(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = BIO_vprintf(bio_err, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+static int run_pipe(void)
+{
+ char buf[4096];
+
+ while (!BIO_eof(bio_in)) {
+ size_t bytes_in;
+ size_t bytes_out;
+
+ if (!BIO_read_ex(bio_in, buf, sizeof(buf), &bytes_in))
+ return 0;
+ bytes_out = 0;
+ while (bytes_out < bytes_in) {
+ size_t bytes;
+
+ if (!BIO_write_ex(chain[amount - 1], buf, bytes_in, &bytes))
+ return 0;
+ bytes_out += bytes;
+ }
+ }
+ return 1;
+}
+
+static int setup_bio_chain(const char *progname)
+{
+ BIO *next = NULL;
+ size_t n = amount;
+
+ chain = OPENSSL_zalloc(sizeof(*chain) * n);
+
+ if (chain != NULL) {
+ size_t i;
+
+ next = bio_out;
+ BIO_up_ref(next); /* Protection against freeing */
+
+ for (i = 0; n > 0; i++, n--) {
+ BIO *curr = BIO_new(BIO_f_prefix());
+
+ if (curr == NULL)
+ goto err;
+ chain[i] = BIO_push(curr, next);
+ if (chain[i] == NULL)
+ goto err;
+ next = chain[i];
+ }
+ }
+ return chain != NULL;
+ err:
+ /* Free the chain we built up */
+ BIO_free_all(next);
+ OPENSSL_free(chain);
+ return 0;
+}
+
+static void cleanup(void)
+{
+ if (chain != NULL) {
+ BIO_free_all(chain[amount - 1]);
+ OPENSSL_free(chain);
+ }
+
+ BIO_free_all(bio_in);
+ BIO_free_all(bio_out);
+ BIO_free_all(bio_err);
+}
+
+static int setup(void)
+{
+ OPTION_CHOICE o;
+ char *arg;
+ char *colon;
+ char *endptr;
+ size_t idx, indent;
+ const char *progname = opt_getprog();
+
+ bio_in = BIO_new_fp(stdin, BIO_NOCLOSE | BIO_FP_TEXT);
+ bio_out = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT);
+ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+#ifdef __VMS
+ bio_out = BIO_push(BIO_new(BIO_f_linebuffer()), bio_out);
+ bio_err = BIO_push(BIO_new(BIO_f_linebuffer()), bio_err);
+#endif
+
+ OPENSSL_assert(bio_in != NULL);
+ OPENSSL_assert(bio_out != NULL);
+ OPENSSL_assert(bio_err != NULL);
+
+
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_AMOUNT:
+ arg = opt_arg();
+ amount = strtoul(arg, &endptr, 10);
+ if (endptr[0] != '\0') {
+ BIO_printf(bio_err,
+ "%s: -n argument isn't a decimal number: %s",
+ progname, arg);
+ return 0;
+ }
+ if (amount < 1) {
+ BIO_printf(bio_err, "%s: must set up at least one filter",
+ progname);
+ return 0;
+ }
+ if (!setup_bio_chain(progname)) {
+ BIO_printf(bio_err, "%s: failed setting up filter chain",
+ progname);
+ return 0;
+ }
+ break;
+ case OPT_INDENT:
+ if (chain == NULL) {
+ BIO_printf(bio_err, "%s: -i given before -n", progname);
+ return 0;
+ }
+ arg = opt_arg();
+ colon = strchr(arg, ':');
+ idx = 0;
+ if (colon != NULL) {
+ idx = strtoul(arg, &endptr, 10);
+ if (endptr[0] != ':') {
+ BIO_printf(bio_err,
+ "%s: -i index isn't a decimal number: %s",
+ progname, arg);
+ return 0;
+ }
+ colon++;
+ } else {
+ colon = arg;
+ }
+ indent = strtoul(colon, &endptr, 10);
+ if (endptr[0] != '\0') {
+ BIO_printf(bio_err,
+ "%s: -i value isn't a decimal number: %s",
+ progname, arg);
+ return 0;
+ }
+ if (idx >= amount) {
+ BIO_printf(bio_err, "%s: index (%zu) not within range 0..%zu",
+ progname, idx, amount - 1);
+ return 0;
+ }
+ if (!BIO_set_indent(chain[idx], (long)indent)) {
+ BIO_printf(bio_err, "%s: failed setting indentation: %s",
+ progname, arg);
+ return 0;
+ }
+ break;
+ case OPT_PREFIX:
+ if (chain == NULL) {
+ BIO_printf(bio_err, "%s: -p given before -n", progname);
+ return 0;
+ }
+ arg = opt_arg();
+ colon = strchr(arg, ':');
+ idx = 0;
+ if (colon != NULL) {
+ idx = strtoul(arg, &endptr, 10);
+ if (endptr[0] != ':') {
+ BIO_printf(bio_err,
+ "%s: -p index isn't a decimal number: %s",
+ progname, arg);
+ return 0;
+ }
+ colon++;
+ } else {
+ colon = arg;
+ }
+ if (idx >= amount) {
+ BIO_printf(bio_err, "%s: index (%zu) not within range 0..%zu",
+ progname, idx, amount - 1);
+ return 0;
+ }
+ if (!BIO_set_prefix(chain[idx], colon)) {
+ BIO_printf(bio_err, "%s: failed setting prefix: %s",
+ progname, arg);
+ return 0;
+ }
+ break;
+ default:
+ case OPT_ERR:
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ int rv = EXIT_SUCCESS;
+
+ opt_init(argc, argv, options);
+ rv = (setup() && run_pipe()) ? EXIT_SUCCESS : EXIT_FAILURE;
+ cleanup();
+ return rv;
+}
diff --git a/test/build.info b/test/build.info
index 0be3ee078c..2b429d304c 100644
--- a/test/build.info
+++ b/test/build.info
@@ -14,7 +14,7 @@ ENDIF
IF[{- $config{target} =~ /^vms-/ -}]
$AUXLIBAPPSSRC=../apps/lib/vms_term_sock.c ../apps/lib/vms_decc_argv.c
ENDIF
-$LIBAPPSSRC=../apps/lib/opt.c ../apps/lib/bf_prefix.c $AUXLIBAPPSSRC
+$LIBAPPSSRC=../apps/lib/opt.c $AUXLIBAPPSSRC
IF[{- !$disabled{tests} -}]
LIBS{noinst,has_main}=libtestutil.a
@@ -706,6 +706,11 @@ IF[{- !$disabled{tests} -}]
SOURCE[namemap_internal_test]=namemap_internal_test.c
INCLUDE[namemap_internal_test]=.. ../include ../apps/include
DEPEND[namemap_internal_test]=../libcrypto.a libtestutil.a
+
+ PROGRAMS{noinst}=bio_prefix_text
+ SOURCE[bio_prefix_text]=bio_prefix_text.c $LIBAPPSSRC
+ INCLUDE[bio_prefix_text]=.. ../include ../apps/include
+ DEPEND[bio_prefix_text]=../libcrypto
ENDIF
SOURCE[ssl_ctx_test]=ssl_ctx_test.c
diff --git a/test/recipes/61-test_bio_prefix.t b/test/recipes/61-test_bio_prefix.t
new file mode 100644
index 0000000000..c77bdbfa32
--- /dev/null
+++ b/test/recipes/61-test_bio_prefix.t
@@ -0,0 +1,55 @@
+#! /usr/bin/env perl
+# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use warnings;
+
+use OpenSSL::Test qw(:DEFAULT data_file);
+use File::Compare qw(compare_text);
+
+setup('test_bio_prefix');
+
+my %input_result = (
+ 'in1.txt' => [ 'args1.pl', 'out1.txt' ],
+ 'in2.txt' => [ 'args2.pl', 'out2.txt' ],
+);
+
+plan tests => 2 * scalar(keys %input_result);
+
+foreach (sort keys %input_result) {
+ SKIP: {
+ my $input_path = data_file($_);
+ my $args_path = data_file($input_result{$_}->[0]);
+ my $expected_path = data_file($input_result{$_}->[1]);
+ my $result_path = "test_bio_prefix-$_-stdout";
+ my @args = do $args_path;
+
+ skip "Problem prefixing $_", 1
+ unless ok(run(test([ 'bio_prefix_text', @args ],
+ stdin => $input_path, stdout => $result_path)),
+ "prefixing $_ with args " . join(' ', @args));
+ is(compare_text($result_path, $expected_path, \&cmp_line), 0,
+ "comparing the dump of $_ with $expected_path");
+ }
+}
+
+sub cmp_line {
+ return 0 if scalar @_ == 0;
+
+ if (scalar @_ != 2) {
+ diag "Lines to compare less than 2: ", scalar @_;
+ return -1;
+ }
+
+ $_[0] =~ s|\R$||;
+ $_[1] =~ s|\R$||;
+ my $r = $_[0] cmp $_[1];
+
+ diag "Lines differ:\n<: $_[0]\n>: $_[1]\n" unless $r == 0;
+ return $r;
+}
diff --git a/test/recipes/61-test_bio_prefix_data/args1.pl b/test/recipes/61-test_bio_prefix_data/args1.pl
new file mode 100644
index 0000000000..e7038dc50d
--- /dev/null
+++ b/test/recipes/61-test_bio_prefix_data/args1.pl
@@ -0,0 +1,6 @@
+(
+ -n => 2,
+ -i => '1:32',
+ -p => '1:FOO',
+ -i => '0:3'
+);
diff --git a/test/recipes/61-test_bio_prefix_data/args2.pl b/test/recipes/61-test_bio_prefix_data/args2.pl
new file mode 100644
index 0000000000..2fe2b7bb63
--- /dev/null
+++ b/test/recipes/61-test_bio_prefix_data/args2.pl
@@ -0,0 +1,3 @@
+(
+ -n => 1,
+);
diff --git a/test/recipes/61-test_bio_prefix_data/in1.txt b/test/recipes/61-test_bio_prefix_data/in1.txt
new file mode 100644
index 0000000000..257cc5642c
--- /dev/null
+++ b/test/recipes/61-test_bio_prefix_data/in1.txt
@@ -0,0 +1 @@
+foo
diff --git a/test/recipes/61-test_bio_prefix_data/in2.txt b/test/recipes/61-test_bio_prefix_data/in2.txt
new file mode 100644
index 0000000000..5716ca5987
--- /dev/null
+++ b/test/recipes/61-test_bio_prefix_data/in2.txt
@@ -0,0 +1 @@
+bar
diff --git a/test/recipes/61-test_bio_prefix_data/out1.txt b/test/recipes/61-test_bio_prefix_data/out1.txt
new file mode 100644
index 0000000000..484e514ba4
--- /dev/null
+++ b/test/recipes/61-test_bio_prefix_data/out1.txt
@@ -0,0 +1 @@
+ FOO foo
diff --git a/test/recipes/61-test_bio_prefix_data/out2.txt b/test/recipes/61-test_bio_prefix_data/out2.txt
new file mode 100644
index 0000000000..5716ca5987
--- /dev/null
+++ b/test/recipes/61-test_bio_prefix_data/out2.txt
@@ -0,0 +1 @@
+bar
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 9c17fc5e25..963181eb37 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4911,3 +4911,4 @@ i2d_X509_PUBKEY_bio ? 3_0_0 EXIST::FUNCTION:
RSA_get0_pss_params ? 3_0_0 EXIST::FUNCTION:RSA
X509_cmp_timeframe ? 3_0_0 EXIST::FUNCTION:
OSSL_CMP_MSG_get0_header ? 3_0_0 EXIST::FUNCTION:CMP
+BIO_f_prefix ? 3_0_0 EXIST::FUNCTION:
diff --git a/util/other.syms b/util/other.syms
index 51b4dfa255..3a8d284e97 100644
--- a/util/other.syms
+++ b/util/other.syms
@@ -127,6 +127,7 @@ BIO_get_conn_port define
BIO_get_conn_ip_family define
BIO_get_fd define
BIO_get_fp define
+BIO_get_indent define
BIO_get_info_callback define
BIO_get_md define
BIO_get_md_ctx define
@@ -158,12 +159,14 @@ BIO_set_conn_port define
BIO_set_conn_ip_family define
BIO_set_fd define
BIO_set_fp define
+BIO_set_indent define
BIO_set_info_callback define
BIO_set_md define
BIO_set_mem_buf define
BIO_set_mem_eof_return define
BIO_set_nbio define
BIO_set_nbio_accept define
+BIO_set_prefix define
BIO_set_read_buffer_size define
BIO_set_ssl define
BIO_set_ssl_mode define
More information about the openssl-commits
mailing list