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