Imported Upstream version 3.2.0
[platform/upstream/libwebsockets.git] / minimal-examples / crypto / minimal-crypto-x509 / main.c
1 /*
2  * lws-crypto-x509
3  *
4  * Written in 2010-2019 by Andy Green <andy@warmcat.com>
5  *
6  * This file is made available under the Creative Commons CC0 1.0
7  * Universal Public Domain Dedication.
8  */
9
10 #include <libwebsockets.h>
11 #include <sys/types.h>
12 #include <fcntl.h>
13 #include <errno.h>
14
15 static int
16 read_pem(const char *filename, char *pembuf, int pembuf_len)
17 {
18         int n, fd = open(filename, LWS_O_RDONLY);
19         if (fd == -1)
20                 return -1;
21
22         n = read(fd, pembuf, pembuf_len - 1);
23         close(fd);
24
25         pembuf[n++] = '\0';
26
27         return n;
28 }
29
30 static int
31 read_pem_c509_cert(struct lws_x509_cert **x509, const char *filename,
32                    char *pembuf, int pembuf_len)
33 {
34         int n;
35
36         n = read_pem(filename, pembuf, pembuf_len);
37         if (n < 0)
38                 return -1;
39
40         if (lws_x509_create(x509)) {
41                 lwsl_err("%s: failed to create x509\n", __func__);
42
43                 return -1;
44         }
45
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);
49
50                 return -1;
51         }
52
53         return 0;
54 }
55
56 int main(int argc, const char **argv)
57 {
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;
62         struct lws_jwk jwk;
63         char pembuf[6144];
64         const char *p;
65
66         memset(&jwk, 0, sizeof(jwk));
67
68         if ((p = lws_cmdline_option(argc, argv, "-d")))
69                 logs = atoi(p);
70
71         lws_set_log_level(logs, NULL);
72         lwsl_user("LWS X509 api example\n");
73
74         memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
75         info.port = CONTEXT_PORT_NO_LISTEN;
76         info.options = 0;
77
78         context = lws_create_context(&info);
79         if (!context) {
80                 lwsl_err("lws init failed\n");
81                 return 1;
82         }
83
84
85         p = lws_cmdline_option(argc, argv, "-c");
86         if (!p) {
87                 lwsl_err("%s: missing -c <cert pem file>\n", __func__);
88                 goto bail;
89         }
90         if (read_pem_c509_cert(&x509, p, pembuf, sizeof(pembuf))) {
91                 lwsl_err("%s: unable to read \"%s\": errno %d\n",
92                          __func__, p, errno);
93                 goto bail;
94         }
95
96         p = lws_cmdline_option(argc, argv, "-t");
97         if (p) {
98
99                 if (read_pem_c509_cert(&x509_trusted, p, pembuf,
100                                        sizeof(pembuf))) {
101                         lwsl_err("%s: unable to read \"%s\": errno %d\n",
102                                  __func__, p, errno);
103                         goto bail1;
104                 }
105
106                 lwsl_notice("%s: certs loaded OK\n", __func__);
107
108                 if (lws_x509_verify(x509, x509_trusted, NULL)) {
109                         lwsl_err("%s: verify failed\n", __func__);
110                         goto bail2;
111                 }
112
113                 lwsl_notice("%s: verified OK\n", __func__);
114         }
115
116         if (x509_trusted) {
117
118                 /* show the trusted cert public key as a JWK */
119
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",
123                                  __func__);
124
125                         goto bail2;
126                 }
127
128                 if ((p = lws_cmdline_option(argc, argv, "--alg")))
129                         lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p));
130
131                 lwsl_info("JWK version of trusted cert:\n");
132                 lws_jwk_dump(&jwk);
133                 lws_jwk_destroy(&jwk);
134         }
135
136         /* get the cert public key as a JWK */
137
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__);
140
141                 goto bail3;
142         }
143         lwsl_info("JWK version of cert:\n");
144
145         if ((p = lws_cmdline_option(argc, argv, "--alg")))
146                 lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p));
147
148         lws_jwk_dump(&jwk);
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");
152                 n = sizeof(pembuf);
153                 if (lws_jwk_export(&jwk, 0, pembuf, &n))
154                         puts(pembuf);
155         }
156
157         /* if we know where the cert private key is, add that to the cert JWK */
158
159         p = lws_cmdline_option(argc, argv, "-p");
160         if (p) {
161                 n = read_pem(p, pembuf, sizeof(pembuf));
162                 if (n < 0) {
163                         lwsl_err("%s: unable read privkey %s\n", __func__, p);
164
165                         goto bail3;
166                 }
167                 if (lws_x509_jwk_privkey_pem(&jwk, pembuf, n, NULL)) {
168                         lwsl_err("%s: unable to parse privkey %s\n",
169                                         __func__, p);
170
171                         goto bail3;
172                 }
173
174                 if ((p = lws_cmdline_option(argc, argv, "--alg")))
175                         lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p));
176
177                 lwsl_info("JWK version of cert + privkey:\n");
178                 lws_jwk_dump(&jwk);
179                 lwsl_notice("Issuing Cert + Private JWK on stdout\n");
180                 n = sizeof(pembuf);
181                 if (lws_jwk_export(&jwk, 1, pembuf, &n))
182                         puts(pembuf);
183         }
184
185         result = 0;
186
187 bail3:
188         lws_jwk_destroy(&jwk);
189 bail2:
190         lws_x509_destroy(&x509_trusted);
191 bail1:
192         lws_x509_destroy(&x509);
193 bail:
194         lws_context_destroy(context);
195
196         if (result)
197                 lwsl_err("%s: failed\n", __func__);
198         else
199                 lwsl_notice("%s: OK\n", __func__);
200
201         return result;
202 }