1/* 2 * Copyright The Mbed TLS Contributors 3 * SPDX-License-Identifier: Apache-2.0 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 * not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18#include <errno.h> 19#include <stdint.h> 20#include <stdio.h> 21#include <stdlib.h> 22#include <string.h> 23 24#include "psa/crypto.h" 25 26/* This block is present to support Visual Studio builds prior to 2015 */ 27#if defined(_MSC_VER) && _MSC_VER < 1900 28#include <stdarg.h> 29int snprintf(char *s, size_t n, const char *fmt, ...) 30{ 31 int ret; 32 va_list argp; 33 34 /* Avoid calling the invalid parameter handler by checking ourselves */ 35 if (s == NULL || n == 0 || fmt == NULL) { 36 return -1; 37 } 38 39 va_start(argp, fmt); 40#if defined(_TRUNCATE) && !defined(__MINGW32__) 41 ret = _vsnprintf_s(s, n, _TRUNCATE, fmt, argp); 42#else 43 ret = _vsnprintf(s, n, fmt, argp); 44 if (ret < 0 || (size_t) ret == n) { 45 s[n-1] = '\0'; 46 ret = -1; 47 } 48#endif 49 va_end(argp); 50 51 return ret; 52} 53#endif 54 55static void append(char **buffer, size_t buffer_size, 56 size_t *required_size, 57 const char *string, size_t length) 58{ 59 *required_size += length; 60 if (*required_size < buffer_size) { 61 memcpy(*buffer, string, length); 62 *buffer += length; 63 } 64} 65 66static void append_integer(char **buffer, size_t buffer_size, 67 size_t *required_size, 68 const char *format /*printf format for value*/, 69 unsigned long value) 70{ 71 size_t n = snprintf(*buffer, buffer_size - *required_size, format, value); 72 if (n < buffer_size - *required_size) { 73 *buffer += n; 74 } 75 *required_size += n; 76} 77 78/* The code of these function is automatically generated and included below. */ 79static const char *psa_ecc_family_name(psa_ecc_family_t curve); 80static const char *psa_dh_family_name(psa_dh_family_t group); 81static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg); 82 83static void append_with_curve(char **buffer, size_t buffer_size, 84 size_t *required_size, 85 const char *string, size_t length, 86 psa_ecc_family_t curve) 87{ 88 const char *family_name = psa_ecc_family_name(curve); 89 append(buffer, buffer_size, required_size, string, length); 90 append(buffer, buffer_size, required_size, "(", 1); 91 if (family_name != NULL) { 92 append(buffer, buffer_size, required_size, 93 family_name, strlen(family_name)); 94 } else { 95 append_integer(buffer, buffer_size, required_size, 96 "0x%02x", curve); 97 } 98 append(buffer, buffer_size, required_size, ")", 1); 99} 100 101static void append_with_group(char **buffer, size_t buffer_size, 102 size_t *required_size, 103 const char *string, size_t length, 104 psa_dh_family_t group) 105{ 106 const char *group_name = psa_dh_family_name(group); 107 append(buffer, buffer_size, required_size, string, length); 108 append(buffer, buffer_size, required_size, "(", 1); 109 if (group_name != NULL) { 110 append(buffer, buffer_size, required_size, 111 group_name, strlen(group_name)); 112 } else { 113 append_integer(buffer, buffer_size, required_size, 114 "0x%02x", group); 115 } 116 append(buffer, buffer_size, required_size, ")", 1); 117} 118 119typedef const char *(*psa_get_algorithm_name_func_ptr)(psa_algorithm_t alg); 120 121static void append_with_alg(char **buffer, size_t buffer_size, 122 size_t *required_size, 123 psa_get_algorithm_name_func_ptr get_name, 124 psa_algorithm_t alg) 125{ 126 const char *name = get_name(alg); 127 if (name != NULL) { 128 append(buffer, buffer_size, required_size, 129 name, strlen(name)); 130 } else { 131 append_integer(buffer, buffer_size, required_size, 132 "0x%08lx", alg); 133 } 134} 135 136#include "psa_constant_names_generated.c" 137 138static int psa_snprint_status(char *buffer, size_t buffer_size, 139 psa_status_t status) 140{ 141 const char *name = psa_strerror(status); 142 if (name == NULL) { 143 return snprintf(buffer, buffer_size, "%ld", (long) status); 144 } else { 145 size_t length = strlen(name); 146 if (length < buffer_size) { 147 memcpy(buffer, name, length + 1); 148 return (int) length; 149 } else { 150 return (int) buffer_size; 151 } 152 } 153} 154 155static int psa_snprint_ecc_curve(char *buffer, size_t buffer_size, 156 psa_ecc_family_t curve) 157{ 158 const char *name = psa_ecc_family_name(curve); 159 if (name == NULL) { 160 return snprintf(buffer, buffer_size, "0x%02x", (unsigned) curve); 161 } else { 162 size_t length = strlen(name); 163 if (length < buffer_size) { 164 memcpy(buffer, name, length + 1); 165 return (int) length; 166 } else { 167 return (int) buffer_size; 168 } 169 } 170} 171 172static int psa_snprint_dh_group(char *buffer, size_t buffer_size, 173 psa_dh_family_t group) 174{ 175 const char *name = psa_dh_family_name(group); 176 if (name == NULL) { 177 return snprintf(buffer, buffer_size, "0x%02x", (unsigned) group); 178 } else { 179 size_t length = strlen(name); 180 if (length < buffer_size) { 181 memcpy(buffer, name, length + 1); 182 return (int) length; 183 } else { 184 return (int) buffer_size; 185 } 186 } 187} 188 189static void usage(const char *program_name) 190{ 191 printf("Usage: %s TYPE VALUE [VALUE...]\n", 192 program_name == NULL ? "psa_constant_names" : program_name); 193 printf("Print the symbolic name whose numerical value is VALUE in TYPE.\n"); 194 printf("Supported types (with = between aliases):\n"); 195 printf(" alg=algorithm Algorithm (psa_algorithm_t)\n"); 196 printf(" curve=ecc_curve Elliptic curve identifier (psa_ecc_family_t)\n"); 197 printf(" group=dh_group Diffie-Hellman group identifier (psa_dh_family_t)\n"); 198 printf(" type=key_type Key type (psa_key_type_t)\n"); 199 printf(" usage=key_usage Key usage (psa_key_usage_t)\n"); 200 printf(" error=status Status code (psa_status_t)\n"); 201} 202 203typedef enum { 204 TYPE_STATUS, 205} signed_value_type; 206 207int process_signed(signed_value_type type, long min, long max, char **argp) 208{ 209 for (; *argp != NULL; argp++) { 210 char buffer[200]; 211 char *end; 212 long value = strtol(*argp, &end, 0); 213 if (*end) { 214 printf("Non-numeric value: %s\n", *argp); 215 return EXIT_FAILURE; 216 } 217 if (value < min || (errno == ERANGE && value < 0)) { 218 printf("Value too small: %s\n", *argp); 219 return EXIT_FAILURE; 220 } 221 if (value > max || (errno == ERANGE && value > 0)) { 222 printf("Value too large: %s\n", *argp); 223 return EXIT_FAILURE; 224 } 225 226 switch (type) { 227 case TYPE_STATUS: 228 psa_snprint_status(buffer, sizeof(buffer), 229 (psa_status_t) value); 230 break; 231 } 232 puts(buffer); 233 } 234 235 return EXIT_SUCCESS; 236} 237 238typedef enum { 239 TYPE_ALGORITHM, 240 TYPE_ECC_CURVE, 241 TYPE_DH_GROUP, 242 TYPE_KEY_TYPE, 243 TYPE_KEY_USAGE, 244} unsigned_value_type; 245 246int process_unsigned(unsigned_value_type type, unsigned long max, char **argp) 247{ 248 for (; *argp != NULL; argp++) { 249 char buffer[200]; 250 char *end; 251 unsigned long value = strtoul(*argp, &end, 0); 252 if (*end) { 253 printf("Non-numeric value: %s\n", *argp); 254 return EXIT_FAILURE; 255 } 256 if (value > max || errno == ERANGE) { 257 printf("Value out of range: %s\n", *argp); 258 return EXIT_FAILURE; 259 } 260 261 switch (type) { 262 case TYPE_ALGORITHM: 263 psa_snprint_algorithm(buffer, sizeof(buffer), 264 (psa_algorithm_t) value); 265 break; 266 case TYPE_ECC_CURVE: 267 psa_snprint_ecc_curve(buffer, sizeof(buffer), 268 (psa_ecc_family_t) value); 269 break; 270 case TYPE_DH_GROUP: 271 psa_snprint_dh_group(buffer, sizeof(buffer), 272 (psa_dh_family_t) value); 273 break; 274 case TYPE_KEY_TYPE: 275 psa_snprint_key_type(buffer, sizeof(buffer), 276 (psa_key_type_t) value); 277 break; 278 case TYPE_KEY_USAGE: 279 psa_snprint_key_usage(buffer, sizeof(buffer), 280 (psa_key_usage_t) value); 281 break; 282 } 283 puts(buffer); 284 } 285 286 return EXIT_SUCCESS; 287} 288 289int main(int argc, char *argv[]) 290{ 291 if (argc <= 1 || 292 !strcmp(argv[1], "help") || 293 !strcmp(argv[1], "--help")) { 294 usage(argv[0]); 295 return EXIT_FAILURE; 296 } 297 298 if (!strcmp(argv[1], "error") || !strcmp(argv[1], "status")) { 299 /* There's no way to obtain the actual range of a signed type, 300 * so hard-code it here: psa_status_t is int32_t. */ 301 return process_signed(TYPE_STATUS, INT32_MIN, INT32_MAX, 302 argv + 2); 303 } else if (!strcmp(argv[1], "alg") || !strcmp(argv[1], "algorithm")) { 304 return process_unsigned(TYPE_ALGORITHM, (psa_algorithm_t) (-1), 305 argv + 2); 306 } else if (!strcmp(argv[1], "curve") || !strcmp(argv[1], "ecc_curve")) { 307 return process_unsigned(TYPE_ECC_CURVE, (psa_ecc_family_t) (-1), 308 argv + 2); 309 } else if (!strcmp(argv[1], "group") || !strcmp(argv[1], "dh_group")) { 310 return process_unsigned(TYPE_DH_GROUP, (psa_dh_family_t) (-1), 311 argv + 2); 312 } else if (!strcmp(argv[1], "type") || !strcmp(argv[1], "key_type")) { 313 return process_unsigned(TYPE_KEY_TYPE, (psa_key_type_t) (-1), 314 argv + 2); 315 } else if (!strcmp(argv[1], "usage") || !strcmp(argv[1], "key_usage")) { 316 return process_unsigned(TYPE_KEY_USAGE, (psa_key_usage_t) (-1), 317 argv + 2); 318 } else { 319 printf("Unknown type: %s\n", argv[1]); 320 return EXIT_FAILURE; 321 } 322} 323