4 * Written in 2010-2019 by Andy Green <andy@warmcat.com>
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
10 #include <libwebsockets.h>
11 #include <sys/types.h>
16 read_pem(const char *filename, char *pembuf, int pembuf_len)
18 int n, fd = open(filename, LWS_O_RDONLY);
22 n = read(fd, pembuf, pembuf_len - 1);
31 read_pem_c509_cert(struct lws_x509_cert **x509, const char *filename,
32 char *pembuf, int pembuf_len)
36 n = read_pem(filename, pembuf, pembuf_len);
40 if (lws_x509_create(x509)) {
41 lwsl_err("%s: failed to create x509\n", __func__);
46 if (lws_x509_parse_from_pem(*x509, pembuf, n) < 0) {
47 lwsl_err("%s: unable to parse PEM %s\n", __func__, filename);
48 lws_x509_destroy(x509);
56 int main(int argc, const char **argv)
58 int n, result = 1, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
59 struct lws_x509_cert *x509 = NULL, *x509_trusted = NULL;
60 struct lws_context_creation_info info;
61 struct lws_context *context;
66 memset(&jwk, 0, sizeof(jwk));
68 if ((p = lws_cmdline_option(argc, argv, "-d")))
71 lws_set_log_level(logs, NULL);
72 lwsl_user("LWS X509 api example\n");
74 memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
75 info.port = CONTEXT_PORT_NO_LISTEN;
78 context = lws_create_context(&info);
80 lwsl_err("lws init failed\n");
85 p = lws_cmdline_option(argc, argv, "-c");
87 lwsl_err("%s: missing -c <cert pem file>\n", __func__);
90 if (read_pem_c509_cert(&x509, p, pembuf, sizeof(pembuf))) {
91 lwsl_err("%s: unable to read \"%s\": errno %d\n",
96 p = lws_cmdline_option(argc, argv, "-t");
99 if (read_pem_c509_cert(&x509_trusted, p, pembuf,
101 lwsl_err("%s: unable to read \"%s\": errno %d\n",
106 lwsl_notice("%s: certs loaded OK\n", __func__);
108 if (lws_x509_verify(x509, x509_trusted, NULL)) {
109 lwsl_err("%s: verify failed\n", __func__);
113 lwsl_notice("%s: verified OK\n", __func__);
118 /* show the trusted cert public key as a JWK */
120 if (lws_x509_public_to_jwk(&jwk, x509_trusted,
121 "P-256,P-384,P-521", 4096)) {
122 lwsl_err("%s: unable to get trusted cert pubkey as JWK\n",
128 if ((p = lws_cmdline_option(argc, argv, "--alg")))
129 lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p));
131 lwsl_info("JWK version of trusted cert:\n");
133 lws_jwk_destroy(&jwk);
136 /* get the cert public key as a JWK */
138 if (lws_x509_public_to_jwk(&jwk, x509, "P-256,P-384,P-521", 4096)) {
139 lwsl_err("%s: unable to get cert pubkey as JWK\n", __func__);
143 lwsl_info("JWK version of cert:\n");
145 if ((p = lws_cmdline_option(argc, argv, "--alg")))
146 lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p));
149 /* only print public if he doesn't provide private */
150 if (!lws_cmdline_option(argc, argv, "-p")) {
151 lwsl_notice("Issuing Cert Public JWK on stdout\n");
153 if (lws_jwk_export(&jwk, 0, pembuf, &n))
157 /* if we know where the cert private key is, add that to the cert JWK */
159 p = lws_cmdline_option(argc, argv, "-p");
161 n = read_pem(p, pembuf, sizeof(pembuf));
163 lwsl_err("%s: unable read privkey %s\n", __func__, p);
167 if (lws_x509_jwk_privkey_pem(&jwk, pembuf, n, NULL)) {
168 lwsl_err("%s: unable to parse privkey %s\n",
174 if ((p = lws_cmdline_option(argc, argv, "--alg")))
175 lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p));
177 lwsl_info("JWK version of cert + privkey:\n");
179 lwsl_notice("Issuing Cert + Private JWK on stdout\n");
181 if (lws_jwk_export(&jwk, 1, pembuf, &n))
188 lws_jwk_destroy(&jwk);
190 lws_x509_destroy(&x509_trusted);
192 lws_x509_destroy(&x509);
194 lws_context_destroy(context);
197 lwsl_err("%s: failed\n", __func__);
199 lwsl_notice("%s: OK\n", __func__);