1 /*
2 * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include "apps.h"
11 #include "app_params.h"
12
13 /* Maximum number of bytes that will be output for an octet string body */
14 #define MAX_OCTET_STRING_OUTPUT_BYTES 24
15
describe_param_type(char * buf,size_t bufsz,const OSSL_PARAM * param)16 static int describe_param_type(char *buf, size_t bufsz, const OSSL_PARAM *param)
17 {
18 const char *type_mod = "";
19 const char *type = NULL;
20 int show_type_number = 0;
21 int printed_len;
22
23 switch (param->data_type) {
24 case OSSL_PARAM_UNSIGNED_INTEGER:
25 type_mod = "unsigned ";
26 /* FALLTHRU */
27 case OSSL_PARAM_INTEGER:
28 type = "integer";
29 break;
30 case OSSL_PARAM_UTF8_PTR:
31 type_mod = "pointer to a ";
32 /* FALLTHRU */
33 case OSSL_PARAM_UTF8_STRING:
34 type = "UTF8 encoded string";
35 break;
36 case OSSL_PARAM_OCTET_PTR:
37 type_mod = "pointer to an ";
38 /* FALLTHRU */
39 case OSSL_PARAM_OCTET_STRING:
40 type = "octet string";
41 break;
42 default:
43 type = "unknown type";
44 show_type_number = 1;
45 break;
46 }
47
48 printed_len = BIO_snprintf(buf, bufsz, "%s: ", param->key);
49 if (printed_len > 0) {
50 buf += printed_len;
51 bufsz -= printed_len;
52 }
53 printed_len = BIO_snprintf(buf, bufsz, "%s%s", type_mod, type);
54 if (printed_len > 0) {
55 buf += printed_len;
56 bufsz -= printed_len;
57 }
58 if (show_type_number) {
59 printed_len = BIO_snprintf(buf, bufsz, " [%d]", param->data_type);
60 if (printed_len > 0) {
61 buf += printed_len;
62 bufsz -= printed_len;
63 }
64 }
65 if (param->data_size == 0)
66 printed_len = BIO_snprintf(buf, bufsz, " (arbitrary size)");
67 else
68 printed_len = BIO_snprintf(buf, bufsz, " (max %zu bytes large)",
69 param->data_size);
70 if (printed_len > 0) {
71 buf += printed_len;
72 bufsz -= printed_len;
73 }
74 *buf = '\0';
75 return 1;
76 }
77
print_param_types(const char * thing,const OSSL_PARAM * pdefs,int indent)78 int print_param_types(const char *thing, const OSSL_PARAM *pdefs, int indent)
79 {
80 if (pdefs == NULL) {
81 return 1;
82 } else if (pdefs->key == NULL) {
83 /*
84 * An empty list? This shouldn't happen, but let's just make sure to
85 * say something if there's a badly written provider...
86 */
87 BIO_printf(bio_out, "%*sEmpty list of %s (!!!)\n", indent, "", thing);
88 } else {
89 BIO_printf(bio_out, "%*s%s:\n", indent, "", thing);
90 for (; pdefs->key != NULL; pdefs++) {
91 char buf[200]; /* This should be ample space */
92
93 describe_param_type(buf, sizeof(buf), pdefs);
94 BIO_printf(bio_out, "%*s %s\n", indent, "", buf);
95 }
96 }
97 return 1;
98 }
99
100 /* Output the body of a UTF8 string which might not be zero terminated */
print_param_utf8(const char ** s_ptr,size_t len)101 static void print_param_utf8(const char **s_ptr, size_t len)
102 {
103 const char *s;
104
105 if (s_ptr == NULL) {
106 BIO_puts(bio_out, " ptr null\n");
107 return;
108 }
109 if ((s = *s_ptr) == NULL) {
110 BIO_puts(bio_out, " null\n");
111 return;
112 }
113 BIO_puts(bio_out, "'");
114 if (len > 0)
115 BIO_write(bio_out, s, (int)len);
116 BIO_puts(bio_out, "'\n");
117 }
118
119 /* Output the body of an OCTET string */
print_param_octet(const unsigned char ** bytes_ptr,size_t len)120 static void print_param_octet(const unsigned char **bytes_ptr, size_t len)
121 {
122 size_t i;
123 const char *tail = "\n";
124 const unsigned char *bytes;
125
126 BIO_printf(bio_out, "<%zu bytes>", len);
127 if (bytes_ptr == NULL) {
128 BIO_puts(bio_out, " ptr null\n");
129 return;
130 }
131 if ((bytes = *bytes_ptr) == NULL) {
132 BIO_puts(bio_out, " null\n");
133 return;
134 }
135 if (len == 0) {
136 BIO_puts(bio_out, "\n");
137 return;
138 }
139
140 if (len > MAX_OCTET_STRING_OUTPUT_BYTES) {
141 len = MAX_OCTET_STRING_OUTPUT_BYTES;
142 tail = "...\n";
143 }
144 BIO_puts(bio_out, " ");
145 for (i = 0; i < len; i++)
146 BIO_printf(bio_out, "%02x", bytes[i]);
147 BIO_puts(bio_out, tail);
148 }
149
print_param_value(const OSSL_PARAM * p,int indent)150 void print_param_value(const OSSL_PARAM *p, int indent)
151 {
152 int64_t i;
153 uint64_t u;
154
155 printf("%*s%s: ", indent, "", p->key);
156 switch (p->data_type) {
157 case OSSL_PARAM_UNSIGNED_INTEGER:
158 if (OSSL_PARAM_get_uint64(p, &u))
159 BIO_printf(bio_out, "%llu\n", (unsigned long long int)u);
160 else
161 BIO_printf(bio_out, "error getting value\n");
162 break;
163 case OSSL_PARAM_INTEGER:
164 if (OSSL_PARAM_get_int64(p, &i))
165 BIO_printf(bio_out, "%lld\n", (long long int)i);
166 else
167 BIO_printf(bio_out, "error getting value\n");
168 break;
169 case OSSL_PARAM_UTF8_PTR:
170 print_param_utf8((const char **)p->data, p->return_size);
171 break;
172 case OSSL_PARAM_UTF8_STRING:
173 print_param_utf8((const char **)&p->data, p->return_size);
174 break;
175 case OSSL_PARAM_OCTET_PTR:
176 print_param_octet((const unsigned char **)p->data, p->return_size);
177 break;
178 case OSSL_PARAM_OCTET_STRING:
179 print_param_octet((const unsigned char **)&p->data, p->return_size);
180 break;
181 default:
182 BIO_printf(bio_out, "unknown type (%u) of %zu bytes\n",
183 p->data_type, p->return_size);
184 break;
185 }
186 }
187
188