1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * lws-minimal-crypto-cose-key 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Written in 2010-2021 by Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * This file is made available under the Creative Commons CC0 1.0 7d4afb5ceSopenharmony_ci * Universal Public Domain Dedication. 8d4afb5ceSopenharmony_ci */ 9d4afb5ceSopenharmony_ci 10d4afb5ceSopenharmony_ci#include <libwebsockets.h> 11d4afb5ceSopenharmony_ci#include <sys/select.h> 12d4afb5ceSopenharmony_ci#include <sys/types.h> 13d4afb5ceSopenharmony_ci#include <stdlib.h> 14d4afb5ceSopenharmony_ci#include <fcntl.h> 15d4afb5ceSopenharmony_ci 16d4afb5ceSopenharmony_cistatic int fdin = 0, fdout = 1; 17d4afb5ceSopenharmony_ci 18d4afb5ceSopenharmony_cistatic const char *meta_names[] = { 19d4afb5ceSopenharmony_ci "kty", "kid", "use", "key_ops", "base_iv", "alg" 20d4afb5ceSopenharmony_ci}; 21d4afb5ceSopenharmony_ci 22d4afb5ceSopenharmony_cistatic const char *oct_names[] = { 23d4afb5ceSopenharmony_ci "k" 24d4afb5ceSopenharmony_ci}; 25d4afb5ceSopenharmony_ci 26d4afb5ceSopenharmony_cistatic const char *rsa_names[] = { 27d4afb5ceSopenharmony_ci "e", "n", "d", "p", "q", "dp", "dq", "qi", "other", "ri", "di", "ti" 28d4afb5ceSopenharmony_ci}; 29d4afb5ceSopenharmony_ci 30d4afb5ceSopenharmony_cistatic const char *ec_names[] = { 31d4afb5ceSopenharmony_ci "crv", "x", "d", "y", 32d4afb5ceSopenharmony_ci}; 33d4afb5ceSopenharmony_ci 34d4afb5ceSopenharmony_cistatic void 35d4afb5ceSopenharmony_cicose_key_dump(const struct lws_cose_key *ck) 36d4afb5ceSopenharmony_ci{ 37d4afb5ceSopenharmony_ci const char **enames; 38d4afb5ceSopenharmony_ci char hex[2048], dump[3072]; 39d4afb5ceSopenharmony_ci int elems; 40d4afb5ceSopenharmony_ci size_t l; 41d4afb5ceSopenharmony_ci int n; 42d4afb5ceSopenharmony_ci 43d4afb5ceSopenharmony_ci (void)enames; 44d4afb5ceSopenharmony_ci (void)meta_names; 45d4afb5ceSopenharmony_ci 46d4afb5ceSopenharmony_ci switch (ck->gencrypto_kty) { 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci case LWS_GENCRYPTO_KTY_OCT: 49d4afb5ceSopenharmony_ci elems = LWS_GENCRYPTO_OCT_KEYEL_COUNT; 50d4afb5ceSopenharmony_ci enames = oct_names; 51d4afb5ceSopenharmony_ci break; 52d4afb5ceSopenharmony_ci case LWS_GENCRYPTO_KTY_RSA: 53d4afb5ceSopenharmony_ci elems = LWS_GENCRYPTO_RSA_KEYEL_COUNT; 54d4afb5ceSopenharmony_ci enames = rsa_names; 55d4afb5ceSopenharmony_ci break; 56d4afb5ceSopenharmony_ci case LWS_GENCRYPTO_KTY_EC: 57d4afb5ceSopenharmony_ci elems = LWS_GENCRYPTO_EC_KEYEL_COUNT; 58d4afb5ceSopenharmony_ci enames = ec_names; 59d4afb5ceSopenharmony_ci break; 60d4afb5ceSopenharmony_ci 61d4afb5ceSopenharmony_ci default: 62d4afb5ceSopenharmony_ci lwsl_err("%s: jwk %p: unknown type\n", __func__, ck); 63d4afb5ceSopenharmony_ci 64d4afb5ceSopenharmony_ci return; 65d4afb5ceSopenharmony_ci } 66d4afb5ceSopenharmony_ci 67d4afb5ceSopenharmony_ci for (n = 0; n < LWS_COUNT_COSE_KEY_ELEMENTS; n++) { 68d4afb5ceSopenharmony_ci if (ck->meta[n].buf) { 69d4afb5ceSopenharmony_ci if (n < 2) { 70d4afb5ceSopenharmony_ci l = (size_t)lws_snprintf(dump, sizeof(dump), 71d4afb5ceSopenharmony_ci " %s: %.*s\n", meta_names[n], 72d4afb5ceSopenharmony_ci (int)ck->meta[n].len, 73d4afb5ceSopenharmony_ci ck->meta[n].buf); 74d4afb5ceSopenharmony_ci write(fdout, dump, l); 75d4afb5ceSopenharmony_ci } else { 76d4afb5ceSopenharmony_ci l = (size_t)lws_snprintf(dump, sizeof(dump), 77d4afb5ceSopenharmony_ci " %s: ", meta_names[n]); 78d4afb5ceSopenharmony_ci write(fdout, dump, l); 79d4afb5ceSopenharmony_ci lws_hex_from_byte_array(ck->meta[n].buf, 80d4afb5ceSopenharmony_ci ck->meta[n].len, 81d4afb5ceSopenharmony_ci hex, sizeof(hex)); 82d4afb5ceSopenharmony_ci write(fdout, hex, strlen(hex)); 83d4afb5ceSopenharmony_ci write(fdout, "\n", 1); 84d4afb5ceSopenharmony_ci } 85d4afb5ceSopenharmony_ci } 86d4afb5ceSopenharmony_ci } 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci for (n = 0; n < elems; n++) { 89d4afb5ceSopenharmony_ci if (ck->e[n].buf) { 90d4afb5ceSopenharmony_ci if (!n && ck->gencrypto_kty == LWS_GENCRYPTO_KTY_EC) { 91d4afb5ceSopenharmony_ci l = (size_t)lws_snprintf(dump, sizeof(dump), 92d4afb5ceSopenharmony_ci " %s: %.*s\n", enames[n], 93d4afb5ceSopenharmony_ci (int)ck->e[n].len, 94d4afb5ceSopenharmony_ci ck->e[n].buf); 95d4afb5ceSopenharmony_ci write(fdout, dump, l); 96d4afb5ceSopenharmony_ci } else { 97d4afb5ceSopenharmony_ci l = (size_t)lws_snprintf(dump, sizeof(dump), 98d4afb5ceSopenharmony_ci " %s: ", enames[n]); 99d4afb5ceSopenharmony_ci write(fdout, dump, l); 100d4afb5ceSopenharmony_ci lws_hex_from_byte_array(ck->e[n].buf, 101d4afb5ceSopenharmony_ci ck->e[n].len, 102d4afb5ceSopenharmony_ci hex, sizeof(hex)); 103d4afb5ceSopenharmony_ci write(fdout, hex, strlen(hex)); 104d4afb5ceSopenharmony_ci write(fdout, "\n", 1); 105d4afb5ceSopenharmony_ci } 106d4afb5ceSopenharmony_ci } 107d4afb5ceSopenharmony_ci } 108d4afb5ceSopenharmony_ci} 109d4afb5ceSopenharmony_ci 110d4afb5ceSopenharmony_ciint main(int argc, const char **argv) 111d4afb5ceSopenharmony_ci{ 112d4afb5ceSopenharmony_ci uint8_t *kid = NULL, ktmp[4096], set_temp[32 * 1024], temp[256]; 113d4afb5ceSopenharmony_ci int result = 1, bits = 0, 114d4afb5ceSopenharmony_ci logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; 115d4afb5ceSopenharmony_ci struct lws_context_creation_info info; 116d4afb5ceSopenharmony_ci size_t kid_len = 0, stp = 0; 117d4afb5ceSopenharmony_ci struct lws_context *context; 118d4afb5ceSopenharmony_ci lws_cose_key_t *ck = NULL; 119d4afb5ceSopenharmony_ci cose_param_t cose_kty = 0; 120d4afb5ceSopenharmony_ci lws_dll2_owner_t set; 121d4afb5ceSopenharmony_ci const char *p, *crv; 122d4afb5ceSopenharmony_ci lws_lec_pctx_t lec; 123d4afb5ceSopenharmony_ci 124d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-d"))) 125d4afb5ceSopenharmony_ci logs = atoi(p); 126d4afb5ceSopenharmony_ci 127d4afb5ceSopenharmony_ci lws_set_log_level(logs, NULL); 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ci lwsl_user("LWS cose-key example tool -k keyset [-s alg-name kid ]\n"); 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_ci memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 132d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK) 133d4afb5ceSopenharmony_ci info.port = CONTEXT_PORT_NO_LISTEN; 134d4afb5ceSopenharmony_ci#endif 135d4afb5ceSopenharmony_ci 136d4afb5ceSopenharmony_ci context = lws_create_context(&info); 137d4afb5ceSopenharmony_ci if (!context) { 138d4afb5ceSopenharmony_ci lwsl_err("lws init failed\n"); 139d4afb5ceSopenharmony_ci return 1; 140d4afb5ceSopenharmony_ci } 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "--stdin"))) { 143d4afb5ceSopenharmony_ci fdin = open(p, LWS_O_RDONLY, 0); 144d4afb5ceSopenharmony_ci if (fdin < 0) { 145d4afb5ceSopenharmony_ci lwsl_err("%s: unable to open stdin file\n", __func__); 146d4afb5ceSopenharmony_ci return 1; 147d4afb5ceSopenharmony_ci } 148d4afb5ceSopenharmony_ci } 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "--stdout"))) { 151d4afb5ceSopenharmony_ci fdout = open(p, LWS_O_WRONLY | LWS_O_CREAT | LWS_O_TRUNC, 0600); 152d4afb5ceSopenharmony_ci if (fdout < 0) { 153d4afb5ceSopenharmony_ci lwsl_err("%s: unable to open stdout file\n", __func__); 154d4afb5ceSopenharmony_ci goto bail_early; 155d4afb5ceSopenharmony_ci } 156d4afb5ceSopenharmony_ci } 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "--kid"))) { 159d4afb5ceSopenharmony_ci kid = (uint8_t *)p; 160d4afb5ceSopenharmony_ci kid_len = strlen(p); 161d4afb5ceSopenharmony_ci //lwsl_hexdump_notice(kid, kid_len); 162d4afb5ceSopenharmony_ci } 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "--kid-hex"))) { 165d4afb5ceSopenharmony_ci kid_len = (size_t)lws_hex_to_byte_array(p, ktmp, sizeof(ktmp)); 166d4afb5ceSopenharmony_ci kid = (uint8_t *)ktmp; 167d4afb5ceSopenharmony_ci } 168d4afb5ceSopenharmony_ci 169d4afb5ceSopenharmony_ci /* 170d4afb5ceSopenharmony_ci * If we have some stdin queued up, we understand we are dumping 171d4afb5ceSopenharmony_ci * an existing cose_key or key_set from stdin 172d4afb5ceSopenharmony_ci */ 173d4afb5ceSopenharmony_ci 174d4afb5ceSopenharmony_ci if (!fdin) { 175d4afb5ceSopenharmony_ci struct timeval timeout; 176d4afb5ceSopenharmony_ci fd_set fds; 177d4afb5ceSopenharmony_ci 178d4afb5ceSopenharmony_ci FD_ZERO(&fds); 179d4afb5ceSopenharmony_ci FD_SET(0, &fds); 180d4afb5ceSopenharmony_ci 181d4afb5ceSopenharmony_ci timeout.tv_sec = 0; 182d4afb5ceSopenharmony_ci timeout.tv_usec = 1000; 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci if (select(fdin + 1, &fds, NULL, NULL, &timeout) < 0) 185d4afb5ceSopenharmony_ci goto no_stdin; 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci if (!FD_ISSET(0, &fds)) 188d4afb5ceSopenharmony_ci goto no_stdin; 189d4afb5ceSopenharmony_ci } 190d4afb5ceSopenharmony_ci 191d4afb5ceSopenharmony_ci do { 192d4afb5ceSopenharmony_ci int n = (int)read(fdin, temp, sizeof(temp)); 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_ci if (n < 0) 195d4afb5ceSopenharmony_ci goto bail; 196d4afb5ceSopenharmony_ci if (!n) { 197d4afb5ceSopenharmony_ci int kc = 0; 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci if (!stp) 200d4afb5ceSopenharmony_ci /* there was no stdin */ 201d4afb5ceSopenharmony_ci break; 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci lwsl_notice("%s: importing\n", __func__); 204d4afb5ceSopenharmony_ci 205d4afb5ceSopenharmony_ci lws_dll2_owner_clear(&set); 206d4afb5ceSopenharmony_ci ck = lws_cose_key_import(&set, NULL, NULL, set_temp, stp); 207d4afb5ceSopenharmony_ci if (!ck) { 208d4afb5ceSopenharmony_ci lwsl_err("%s: import failed\n", __func__); 209d4afb5ceSopenharmony_ci goto bail; 210d4afb5ceSopenharmony_ci } 211d4afb5ceSopenharmony_ci 212d4afb5ceSopenharmony_ci lws_start_foreach_dll(struct lws_dll2 *, p, 213d4afb5ceSopenharmony_ci lws_dll2_get_head(&set)) { 214d4afb5ceSopenharmony_ci lws_cose_key_t *ck = lws_container_of(p, 215d4afb5ceSopenharmony_ci lws_cose_key_t, list); 216d4afb5ceSopenharmony_ci struct lws_gencrypto_keyelem *ke = 217d4afb5ceSopenharmony_ci &ck->meta[COSEKEY_META_KID]; 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ci kc++; 220d4afb5ceSopenharmony_ci 221d4afb5ceSopenharmony_ci if (!kid_len || (ke->len && 222d4afb5ceSopenharmony_ci ke->len == (uint32_t)kid_len && 223d4afb5ceSopenharmony_ci !memcmp(ke->buf, kid, kid_len))) { 224d4afb5ceSopenharmony_ci printf("Cose key #%d\n", kc); 225d4afb5ceSopenharmony_ci cose_key_dump(ck); 226d4afb5ceSopenharmony_ci } 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci } lws_end_foreach_dll(p); 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci lws_cose_key_set_destroy(&set); 231d4afb5ceSopenharmony_ci result = 0; 232d4afb5ceSopenharmony_ci goto bail; 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci } 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ci if (stp + (size_t)n > sizeof(set_temp)) { 237d4afb5ceSopenharmony_ci lwsl_err("%s: stdin bigger than our buffer\n", __func__); 238d4afb5ceSopenharmony_ci goto bail; 239d4afb5ceSopenharmony_ci } 240d4afb5ceSopenharmony_ci memcpy(set_temp + stp, temp, (size_t)n); 241d4afb5ceSopenharmony_ci stp += (size_t)n; 242d4afb5ceSopenharmony_ci } while (1); 243d4afb5ceSopenharmony_ci 244d4afb5ceSopenharmony_cino_stdin: 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci /* 247d4afb5ceSopenharmony_ci * 248d4afb5ceSopenharmony_ci */ 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci p = lws_cmdline_option(argc, argv, "--kty"); 251d4afb5ceSopenharmony_ci if (!p) { 252d4afb5ceSopenharmony_ci lwsl_err("%s: use --kty OKP|EC2|RSA|SYMMETRIC\n", 253d4afb5ceSopenharmony_ci __func__); 254d4afb5ceSopenharmony_ci goto bail; 255d4afb5ceSopenharmony_ci } 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci if (!strcmp(p, "OKP")) 258d4afb5ceSopenharmony_ci cose_kty = LWSCOSE_WKKTV_OKP; 259d4afb5ceSopenharmony_ci if (!strcmp(p, "EC2")) 260d4afb5ceSopenharmony_ci cose_kty = LWSCOSE_WKKTV_EC2; 261d4afb5ceSopenharmony_ci if (!strcmp(p, "RSA")) 262d4afb5ceSopenharmony_ci cose_kty = LWSCOSE_WKKTV_RSA; 263d4afb5ceSopenharmony_ci if (!strcmp(p, "SYMMETRIC") || !strcmp(p, "SYM")) 264d4afb5ceSopenharmony_ci cose_kty = LWSCOSE_WKKTV_SYMMETRIC; 265d4afb5ceSopenharmony_ci 266d4afb5ceSopenharmony_ci if (!cose_kty) { 267d4afb5ceSopenharmony_ci lwsl_err("%s: use --kty OKP|EC2|RSA|SYMMETRIC\n", 268d4afb5ceSopenharmony_ci __func__); 269d4afb5ceSopenharmony_ci goto bail; 270d4afb5ceSopenharmony_ci } 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ci crv = NULL; 273d4afb5ceSopenharmony_ci if (cose_kty == LWSCOSE_WKKTV_OKP || 274d4afb5ceSopenharmony_ci cose_kty == LWSCOSE_WKKTV_EC2) { 275d4afb5ceSopenharmony_ci crv = lws_cmdline_option(argc, argv, "--curve"); 276d4afb5ceSopenharmony_ci if (!crv) { 277d4afb5ceSopenharmony_ci lwsl_err("%s: use --curve P-256 etc\n", __func__); 278d4afb5ceSopenharmony_ci goto bail; 279d4afb5ceSopenharmony_ci } 280d4afb5ceSopenharmony_ci } 281d4afb5ceSopenharmony_ci 282d4afb5ceSopenharmony_ci p = lws_cmdline_option(argc, argv, "--bits"); 283d4afb5ceSopenharmony_ci if (p) 284d4afb5ceSopenharmony_ci bits = atoi(p); 285d4afb5ceSopenharmony_ci 286d4afb5ceSopenharmony_ci ck = lws_cose_key_generate(context, cose_kty, 0, bits, crv, 287d4afb5ceSopenharmony_ci kid, kid_len); 288d4afb5ceSopenharmony_ci if (!ck) 289d4afb5ceSopenharmony_ci goto bail; 290d4afb5ceSopenharmony_ci 291d4afb5ceSopenharmony_ci lws_lec_init(&lec, ktmp, sizeof(ktmp)); 292d4afb5ceSopenharmony_ci lws_cose_key_export(ck, &lec, LWSJWKF_EXPORT_PRIVATE); 293d4afb5ceSopenharmony_ci write(fdout, ktmp, lec.used); 294d4afb5ceSopenharmony_ci 295d4afb5ceSopenharmony_ci lws_cose_key_destroy(&ck); 296d4afb5ceSopenharmony_ci result = 0; 297d4afb5ceSopenharmony_ci 298d4afb5ceSopenharmony_cibail: 299d4afb5ceSopenharmony_ci lws_context_destroy(context); 300d4afb5ceSopenharmony_ci 301d4afb5ceSopenharmony_ci if (result) 302d4afb5ceSopenharmony_ci lwsl_err("%s: FAIL: %d\n", __func__, result); 303d4afb5ceSopenharmony_ci else 304d4afb5ceSopenharmony_ci lwsl_notice("%s: PASS\n", __func__); 305d4afb5ceSopenharmony_ci 306d4afb5ceSopenharmony_cibail_early: 307d4afb5ceSopenharmony_ci if (fdin > 0) 308d4afb5ceSopenharmony_ci close(fdin); 309d4afb5ceSopenharmony_ci if (fdout != 1 && fdout >= 0) 310d4afb5ceSopenharmony_ci close(fdout); 311d4afb5ceSopenharmony_ci 312d4afb5ceSopenharmony_ci return result; 313d4afb5ceSopenharmony_ci} 314