blob: 55141002191c4413d2ea5def1bebd34d1d1a0a6d [file] [log] [blame]
Gilles Peskine3f775262019-02-13 18:42:06 +01001#include <errno.h>
2#include <stdint.h>
Gilles Peskine029b5d62018-07-16 23:13:37 +02003#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7#include "psa/crypto.h"
8
Darryl Green608e0912018-10-17 14:48:27 +01009/* This block is present to support Visual Studio builds prior to 2015 */
10#if defined(_MSC_VER) && _MSC_VER < 1900
11#include <stdarg.h>
12int snprintf( char *s, size_t n, const char *fmt, ... )
13{
14 int ret;
15 va_list argp;
16
17 /* Avoid calling the invalid parameter handler by checking ourselves */
18 if( s == NULL || n == 0 || fmt == NULL )
19 return( -1 );
20
21 va_start( argp, fmt );
22#if defined(_TRUNCATE) && !defined(__MINGW32__)
23 ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp );
24#else
25 ret = _vsnprintf( s, n, fmt, argp );
26 if( ret < 0 || (size_t) ret == n )
27 {
28 s[n-1] = '\0';
29 ret = -1;
30 }
31#endif
32 va_end( argp );
33
34 return( ret );
35}
36#endif
37
Gilles Peskine029b5d62018-07-16 23:13:37 +020038/* There are different GET_HASH macros for different kinds of algorithms
39 * built from hashes, but the values are all constructed on the
40 * same model. */
41#define PSA_ALG_GET_HASH(alg) \
42 (((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH)
43
44static void append(char **buffer, size_t buffer_size,
45 size_t *required_size,
46 const char *string, size_t length)
47{
48 *required_size += length;
49 if (*required_size < buffer_size) {
50 memcpy(*buffer, string, length);
51 *buffer += length;
52 }
53}
54
Gilles Peskine0deaf3d2018-08-20 15:06:39 +020055static void append_integer(char **buffer, size_t buffer_size,
56 size_t *required_size,
57 const char *format /*printf format for value*/,
58 unsigned long value)
59{
60 size_t n = snprintf(*buffer, buffer_size - *required_size, format, value);
61 if (n < buffer_size - *required_size) *buffer += n;
62 *required_size += n;
63}
64
Gilles Peskine029b5d62018-07-16 23:13:37 +020065/* The code of these function is automatically generated and included below. */
66static const char *psa_ecc_curve_name(psa_ecc_curve_t curve);
67static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg);
68
69static void append_with_curve(char **buffer, size_t buffer_size,
70 size_t *required_size,
71 const char *string, size_t length,
72 psa_ecc_curve_t curve)
73{
74 const char *curve_name = psa_ecc_curve_name(curve);
75 append(buffer, buffer_size, required_size, string, length);
76 append(buffer, buffer_size, required_size, "(", 1);
77 if (curve_name != NULL) {
78 append(buffer, buffer_size, required_size,
79 curve_name, strlen(curve_name));
80 } else {
Gilles Peskine0deaf3d2018-08-20 15:06:39 +020081 append_integer(buffer, buffer_size, required_size,
82 "0x%04x", curve);
Gilles Peskine029b5d62018-07-16 23:13:37 +020083 }
84 append(buffer, buffer_size, required_size, ")", 1);
85}
86
87static void append_with_hash(char **buffer, size_t buffer_size,
88 size_t *required_size,
89 const char *string, size_t length,
90 psa_algorithm_t hash_alg)
91{
92 const char *hash_name = psa_hash_algorithm_name(hash_alg);
93 append(buffer, buffer_size, required_size, string, length);
94 append(buffer, buffer_size, required_size, "(", 1);
95 if (hash_name != NULL) {
96 append(buffer, buffer_size, required_size,
97 hash_name, strlen(hash_name));
98 } else {
Gilles Peskine0deaf3d2018-08-20 15:06:39 +020099 append_integer(buffer, buffer_size, required_size,
100 "0x%08lx", hash_alg);
Gilles Peskine029b5d62018-07-16 23:13:37 +0200101 }
102 append(buffer, buffer_size, required_size, ")", 1);
103}
104
105#include "psa_constant_names_generated.c"
106
107static int psa_snprint_status(char *buffer, size_t buffer_size,
108 psa_status_t status)
109{
110 const char *name = psa_strerror(status);
111 if (name == NULL) {
112 return snprintf(buffer, buffer_size, "%ld", (long) status);
113 } else {
114 size_t length = strlen(name);
115 if (length < buffer_size) {
116 memcpy(buffer, name, length + 1);
Darryl Green18246962018-10-17 15:01:45 +0100117 return (int) length;
Gilles Peskine029b5d62018-07-16 23:13:37 +0200118 } else {
Darryl Green18246962018-10-17 15:01:45 +0100119 return (int) buffer_size;
Gilles Peskine029b5d62018-07-16 23:13:37 +0200120 }
121 }
122}
123
124static int psa_snprint_ecc_curve(char *buffer, size_t buffer_size,
125 psa_ecc_curve_t curve)
126{
127 const char *name = psa_ecc_curve_name(curve);
128 if (name == NULL) {
129 return snprintf(buffer, buffer_size, "0x%04x", (unsigned) curve);
130 } else {
131 size_t length = strlen(name);
132 if (length < buffer_size) {
133 memcpy(buffer, name, length + 1);
Darryl Green18246962018-10-17 15:01:45 +0100134 return (int) length;
Gilles Peskine029b5d62018-07-16 23:13:37 +0200135 } else {
Darryl Green18246962018-10-17 15:01:45 +0100136 return (int) buffer_size;
Gilles Peskine029b5d62018-07-16 23:13:37 +0200137 }
138 }
139}
140
141static void usage(const char *program_name)
142{
Gilles Peskine567840e2018-09-25 18:27:53 +0200143 printf("Usage: %s TYPE VALUE [VALUE...]\n",
Gilles Peskine029b5d62018-07-16 23:13:37 +0200144 program_name == NULL ? "psa_constant_names" : program_name);
145 printf("Print the symbolic name whose numerical value is VALUE in TYPE.\n");
146 printf("Supported types (with = between aliases):\n");
Gilles Peskine38808fa2018-08-20 15:07:37 +0200147 printf(" alg=algorithm Algorithm (psa_algorithm_t)\n");
Gilles Peskine029b5d62018-07-16 23:13:37 +0200148 printf(" curve=ecc_curve Elliptic curve identifier (psa_ecc_curve_t)\n");
Gilles Peskine38808fa2018-08-20 15:07:37 +0200149 printf(" type=key_type Key type (psa_key_type_t)\n");
Gilles Peskine029b5d62018-07-16 23:13:37 +0200150 printf(" usage=key_usage Key usage (psa_key_usage_t)\n");
151 printf(" error=status Status code (psa_status_t)\n");
152}
153
Gilles Peskine567840e2018-09-25 18:27:53 +0200154typedef enum {
155 TYPE_STATUS,
Gilles Peskine3f775262019-02-13 18:42:06 +0100156} signed_value_type;
157
158int process_signed(signed_value_type type, long min, long max, char **argp)
159{
160 for (; *argp != NULL; argp++) {
161 char buffer[200];
162 char *end;
163 long value = strtol(*argp, &end, 0);
164 if (*end) {
165 printf("Non-numeric value: %s\n", *argp);
166 return EXIT_FAILURE;
167 }
168 if (value < min || (errno == ERANGE && value < 0)) {
169 printf("Value too small: %s\n", *argp);
170 return EXIT_FAILURE;
171 }
172 if (value > max || (errno == ERANGE && value > 0)) {
173 printf("Value too large: %s\n", *argp);
174 return EXIT_FAILURE;
175 }
176
177 switch (type) {
178 case TYPE_STATUS:
179 psa_snprint_status(buffer, sizeof(buffer),
180 (psa_status_t) value);
181 break;
182 }
183 puts(buffer);
184 }
185
186 return EXIT_SUCCESS;
187}
188
189typedef enum {
Gilles Peskine567840e2018-09-25 18:27:53 +0200190 TYPE_ALGORITHM,
191 TYPE_ECC_CURVE,
192 TYPE_KEY_TYPE,
193 TYPE_KEY_USAGE,
Gilles Peskine1b879842019-02-13 18:40:50 +0100194} unsigned_value_type;
Gilles Peskine567840e2018-09-25 18:27:53 +0200195
Gilles Peskine1b879842019-02-13 18:40:50 +0100196int process_unsigned(unsigned_value_type type, unsigned long max, char **argp)
Gilles Peskine029b5d62018-07-16 23:13:37 +0200197{
Gilles Peskine1b879842019-02-13 18:40:50 +0100198 for (; *argp != NULL; argp++) {
Gilles Peskine567840e2018-09-25 18:27:53 +0200199 char buffer[200];
200 char *end;
Gilles Peskine1b879842019-02-13 18:40:50 +0100201 unsigned long value = strtoul(*argp, &end, 0);
Gilles Peskine567840e2018-09-25 18:27:53 +0200202 if (*end) {
Gilles Peskine1b879842019-02-13 18:40:50 +0100203 printf("Non-numeric value: %s\n", *argp);
Gilles Peskine567840e2018-09-25 18:27:53 +0200204 return EXIT_FAILURE;
205 }
Gilles Peskine3f775262019-02-13 18:42:06 +0100206 if (value > max || errno == ERANGE) {
Gilles Peskine1b879842019-02-13 18:40:50 +0100207 printf("Value out of range: %s\n", *argp);
Gilles Peskine265a1712018-10-31 14:52:28 +0100208 return EXIT_FAILURE;
209 }
Gilles Peskine567840e2018-09-25 18:27:53 +0200210
211 switch (type) {
Gilles Peskine567840e2018-09-25 18:27:53 +0200212 case TYPE_ALGORITHM:
213 psa_snprint_algorithm(buffer, sizeof(buffer),
214 (psa_algorithm_t) value);
215 break;
216 case TYPE_ECC_CURVE:
217 psa_snprint_ecc_curve(buffer, sizeof(buffer),
218 (psa_ecc_curve_t) value);
219 break;
220 case TYPE_KEY_TYPE:
221 psa_snprint_key_type(buffer, sizeof(buffer),
222 (psa_key_type_t) value);
223 break;
224 case TYPE_KEY_USAGE:
225 psa_snprint_key_usage(buffer, sizeof(buffer),
226 (psa_key_usage_t) value);
227 break;
228 }
229 puts(buffer);
230 }
231
Gilles Peskine029b5d62018-07-16 23:13:37 +0200232 return EXIT_SUCCESS;
233}
Gilles Peskine1b879842019-02-13 18:40:50 +0100234
235int main(int argc, char *argv[])
236{
237 if (argc <= 1 ||
238 !strcmp(argv[1], "help") ||
239 !strcmp(argv[1], "--help"))
240 {
241 usage(argv[0]);
242 return EXIT_FAILURE;
243 }
244
245 if (!strcmp(argv[1], "error") || !strcmp(argv[1], "status")) {
Gilles Peskine3f775262019-02-13 18:42:06 +0100246 /* There's no way to obtain the actual range of a signed type,
247 * so hard-code it here: psa_status_t is int32_t. */
248 return process_signed(TYPE_STATUS, INT32_MIN, INT32_MAX,
249 argv + 2);
Gilles Peskine1b879842019-02-13 18:40:50 +0100250 } else if (!strcmp(argv[1], "alg") || !strcmp(argv[1], "algorithm")) {
251 return process_unsigned(TYPE_ALGORITHM, (psa_algorithm_t) (-1),
252 argv + 2);
253 } else if (!strcmp(argv[1], "curve") || !strcmp(argv[1], "ecc_curve")) {
254 return process_unsigned(TYPE_ECC_CURVE, (psa_ecc_curve_t) (-1),
255 argv + 2);
256 } else if (!strcmp(argv[1], "type") || !strcmp(argv[1], "key_type")) {
257 return process_unsigned(TYPE_KEY_TYPE, (psa_key_type_t) (-1),
258 argv + 2);
259 } else if (!strcmp(argv[1], "usage") || !strcmp(argv[1], "key_usage")) {
260 return process_unsigned(TYPE_KEY_USAGE, (psa_key_usage_t) (-1),
261 argv + 2);
262 } else {
263 printf("Unknown type: %s\n", argv[1]);
264 return EXIT_FAILURE;
265 }
266}