From e1cf534775561c408a1bbb2490e7cec277b8e437 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 3 Nov 2019 09:25:32 +0000 Subject: [PATCH] jwk: add export option to suppress final CRLF https://github.com/warmcat/libwebsockets/issues/1746 Adding the final CRLF is a NOP at JSON level, but can disrupt hashing the JSON if it isn't expecting it. Add flags to the jwk export so it can be controlled... operation remains unchanged for old values 0 and 1 but a second flag can be OR-ed to control issue of final CRLF. --- include/libwebsockets/lws-jwk.h | 15 ++++++++++++-- lib/jose/jwk/jwk.c | 20 ++++++++++--------- .../crypto/minimal-crypto-jwk/main.c | 2 +- .../crypto/minimal-crypto-x509/main.c | 2 +- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/include/libwebsockets/lws-jwk.h b/include/libwebsockets/lws-jwk.h index 0c4bcac92..ab4aff594 100644 --- a/include/libwebsockets/lws-jwk.h +++ b/include/libwebsockets/lws-jwk.h @@ -115,19 +115,30 @@ lws_jwk_destroy(struct lws_jwk *jwk); LWS_VISIBLE LWS_EXTERN int lws_jwk_dup_oct(struct lws_jwk *jwk, const void *key, int len); +#define LWSJWKF_EXPORT_PRIVATE (1 << 0) +#define LWSJWKF_EXPORT_NOCRLF (1 << 1) + /** lws_jwk_export() - Export a JSON Web key to a textual representation * * \param jwk: the JWK object to export - * \param _private: 0 = just export public parts, 1 = export everything + * \param flags: control export options * \param p: the buffer to write the exported JWK to * \param len: the length of the buffer \p p in bytes... reduced by used amount * * Returns length of the used part of the buffer if OK, or -1 for error. * + * \p flags can be OR-ed together + * + * LWSJWKF_EXPORT_PRIVATE: default is only public part, set this to also export + * the private part + * + * LWSJWKF_EXPORT_NOCRLF: normally adds a CRLF at the end of the export, if + * you need to suppress it, set this flag + * * Serializes the content of the JWK into a char buffer. */ LWS_VISIBLE LWS_EXTERN int -lws_jwk_export(struct lws_jwk *jwk, int _private, char *p, int *len); +lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len); /** lws_jwk_load() - Import a JSON Web key from a file * diff --git a/lib/jose/jwk/jwk.c b/lib/jose/jwk/jwk.c index 4c0c5a2e0..61190a021 100644 --- a/lib/jose/jwk/jwk.c +++ b/lib/jose/jwk/jwk.c @@ -667,7 +667,7 @@ lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user, LWS_VISIBLE int -lws_jwk_export(struct lws_jwk *jwk, int private, char *p, int *len) +lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len) { char *start = p, *end = &p[*len - 1]; int n, m, limit, first = 1, asym = 0; @@ -740,9 +740,9 @@ lws_jwk_export(struct lws_jwk *jwk, int private, char *p, int *len) } tok[pos] = '\0'; pos = 0; - if (private || !asym || - (strcmp(tok, "sign") && - strcmp(tok, "encrypt"))) { + if ((flags & LWSJWKF_EXPORT_PRIVATE) || + !asym || (strcmp(tok, "sign") && + strcmp(tok, "encrypt"))) { if (!f) *p++ = ','; f = 0; @@ -758,7 +758,8 @@ lws_jwk_export(struct lws_jwk *jwk, int private, char *p, int *len) default: /* both sig and enc require asym private key */ - if (!private && asym && l->idx == (int)JWK_META_USE) + if (!(flags & LWSJWKF_EXPORT_PRIVATE) && + asym && l->idx == (int)JWK_META_USE) break; if (!first) *p++ = ','; @@ -771,7 +772,7 @@ lws_jwk_export(struct lws_jwk *jwk, int private, char *p, int *len) } if ((!(l->meta & 1)) && jwk->e[l->idx].buf && - (private || !(l->meta & 2))) { + ((flags & LWSJWKF_EXPORT_PRIVATE) || !(l->meta & 2))) { if (!first) *p++ = ','; first = 0; @@ -798,7 +799,8 @@ lws_jwk_export(struct lws_jwk *jwk, int private, char *p, int *len) l++; } - p += lws_snprintf(p, end - p, "}\n"); + p += lws_snprintf(p, end - p, + (flags & LWSJWKF_EXPORT_NOCRLF) ? "}" : "}\n"); *len -= p - start; @@ -814,7 +816,7 @@ lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32) tmp = lws_malloc(tmpsize, "rfc7638 tmp"); - n = lws_jwk_export(jwk, 0, tmp, &tmpsize); + n = lws_jwk_export(jwk, LWSJWKF_EXPORT_NOCRLF, tmp, &tmpsize); if (n < 0) goto bail; @@ -887,7 +889,7 @@ lws_jwk_save(struct lws_jwk *jwk, const char *filename) if (!buf) return -1; - n = lws_jwk_export(jwk, 1, buf, &buflen); + n = lws_jwk_export(jwk, LWSJWKF_EXPORT_PRIVATE, buf, &buflen); if (n < 0) goto bail; diff --git a/minimal-examples/crypto/minimal-crypto-jwk/main.c b/minimal-examples/crypto/minimal-crypto-jwk/main.c index f96213619..5298c8128 100644 --- a/minimal-examples/crypto/minimal-crypto-jwk/main.c +++ b/minimal-examples/crypto/minimal-crypto-jwk/main.c @@ -167,7 +167,7 @@ int main(int argc, const char **argv) /* private version */ - if (lws_jwk_export(&jwk, 1, key, &vl) < 0) { + if (lws_jwk_export(&jwk, LWSJWKF_EXPORT_PRIVATE, key, &vl) < 0) { lwsl_err("lws_jwk_export failed\n"); return 1; diff --git a/minimal-examples/crypto/minimal-crypto-x509/main.c b/minimal-examples/crypto/minimal-crypto-x509/main.c index 64875fbab..74aade746 100644 --- a/minimal-examples/crypto/minimal-crypto-x509/main.c +++ b/minimal-examples/crypto/minimal-crypto-x509/main.c @@ -178,7 +178,7 @@ int main(int argc, const char **argv) lws_jwk_dump(&jwk); lwsl_notice("Issuing Cert + Private JWK on stdout\n"); n = sizeof(pembuf); - if (lws_jwk_export(&jwk, 1, pembuf, &n)) + if (lws_jwk_export(&jwk, LWSJWKF_EXPORT_PRIVATE, pembuf, &n)) puts(pembuf); }