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