Update Files
This commit is contained in:
297
Kinc/Sources/kinc/libs/jose/jwk/jwk.c
Normal file
297
Kinc/Sources/kinc/libs/jose/jwk/jwk.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Shared JWK handling that's the same whether JOSE or COSE
|
||||
*/
|
||||
|
||||
#include "private-lib-core.h"
|
||||
#include "private-lib-jose.h"
|
||||
|
||||
static const char *meta_names[] = {
|
||||
"kty", "kid", "use", "key_ops", "x5c", "alg"
|
||||
};
|
||||
|
||||
static const char meta_b64[] = { 0, 0, 0, 0, 1, 0 };
|
||||
|
||||
static const char *oct_names[] = {
|
||||
"k"
|
||||
};
|
||||
static const char oct_b64[] = { 1 };
|
||||
|
||||
static const char *rsa_names[] = {
|
||||
"e", "n", "d", "p", "q", "dp", "dq", "qi"
|
||||
};
|
||||
static const char rsa_b64[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
static const char *ec_names[] = {
|
||||
"crv", "x", "d", "y",
|
||||
};
|
||||
static const char ec_b64[] = { 0, 1, 1, 1 };
|
||||
|
||||
int
|
||||
lws_jwk_dump(struct lws_jwk *jwk)
|
||||
{
|
||||
const char **enames, *b64;
|
||||
int elems;
|
||||
int n;
|
||||
|
||||
(void)enames;
|
||||
(void)meta_names;
|
||||
|
||||
switch (jwk->kty) {
|
||||
default:
|
||||
case LWS_GENCRYPTO_KTY_UNKNOWN:
|
||||
lwsl_err("%s: jwk %p: unknown type\n", __func__, jwk);
|
||||
|
||||
return 1;
|
||||
case LWS_GENCRYPTO_KTY_OCT:
|
||||
elems = LWS_GENCRYPTO_OCT_KEYEL_COUNT;
|
||||
enames = oct_names;
|
||||
b64 = oct_b64;
|
||||
break;
|
||||
case LWS_GENCRYPTO_KTY_RSA:
|
||||
elems = LWS_GENCRYPTO_RSA_KEYEL_COUNT;
|
||||
enames = rsa_names;
|
||||
b64 = rsa_b64;
|
||||
break;
|
||||
case LWS_GENCRYPTO_KTY_EC:
|
||||
elems = LWS_GENCRYPTO_EC_KEYEL_COUNT;
|
||||
enames = ec_names;
|
||||
b64 = ec_b64;
|
||||
break;
|
||||
}
|
||||
|
||||
lwsl_info("%s: jwk %p\n", __func__, jwk);
|
||||
|
||||
for (n = 0; n < LWS_COUNT_JWK_ELEMENTS; n++) {
|
||||
if (jwk->meta[n].buf && meta_b64[n]) {
|
||||
lwsl_info(" meta: %s\n", meta_names[n]);
|
||||
lwsl_hexdump_info(jwk->meta[n].buf, jwk->meta[n].len);
|
||||
}
|
||||
if (jwk->meta[n].buf && !meta_b64[n])
|
||||
lwsl_info(" meta: %s: '%s'\n", meta_names[n],
|
||||
jwk->meta[n].buf);
|
||||
}
|
||||
|
||||
for (n = 0; n < elems; n++) {
|
||||
if (jwk->e[n].buf && b64[n]) {
|
||||
lwsl_info(" e: %s\n", enames[n]);
|
||||
lwsl_hexdump_info(jwk->e[n].buf, jwk->e[n].len);
|
||||
}
|
||||
if (jwk->e[n].buf && !b64[n])
|
||||
lwsl_info(" e: %s: '%s'\n", enames[n], jwk->e[n].buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_lws_jwk_set_el_jwk(struct lws_gencrypto_keyelem *e, char *in, size_t len)
|
||||
{
|
||||
e->buf = lws_malloc(len + 1, "jwk");
|
||||
if (!e->buf)
|
||||
return -1;
|
||||
|
||||
memcpy(e->buf, in, len);
|
||||
e->buf[len] = '\0';
|
||||
e->len = (uint32_t)len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
lws_jwk_destroy_elements(struct lws_gencrypto_keyelem *el, int m)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < m; n++)
|
||||
if (el[n].buf) {
|
||||
/* wipe all key material when it goes out of scope */
|
||||
lws_explicit_bzero(el[n].buf, el[n].len);
|
||||
lws_free_set_NULL(el[n].buf);
|
||||
el[n].len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lws_jwk_destroy(struct lws_jwk *jwk)
|
||||
{
|
||||
lws_jwk_destroy_elements(jwk->e, LWS_ARRAY_SIZE(jwk->e));
|
||||
lws_jwk_destroy_elements(jwk->meta, LWS_ARRAY_SIZE(jwk->meta));
|
||||
}
|
||||
|
||||
void
|
||||
lws_jwk_init_jps(struct lws_jwk_parse_state *jps,
|
||||
struct lws_jwk *jwk, lws_jwk_key_import_callback cb,
|
||||
void *user)
|
||||
{
|
||||
if (jwk)
|
||||
memset(jwk, 0, sizeof(*jwk));
|
||||
|
||||
jps->jwk = jwk;
|
||||
jps->possible = F_RSA | F_EC | F_OCT;
|
||||
jps->per_key_cb = cb;
|
||||
jps->user = user;
|
||||
jps->pos = 0;
|
||||
jps->seen = 0;
|
||||
jps->cose_state = 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_jwk_dup_oct(struct lws_jwk *jwk, const void *key, int len)
|
||||
{
|
||||
unsigned int ulen = (unsigned int)len;
|
||||
|
||||
jwk->e[LWS_GENCRYPTO_KTY_OCT].buf = lws_malloc(ulen, __func__);
|
||||
if (!jwk->e[LWS_GENCRYPTO_KTY_OCT].buf)
|
||||
return -1;
|
||||
|
||||
jwk->kty = LWS_GENCRYPTO_KTY_OCT;
|
||||
jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = ulen;
|
||||
|
||||
memcpy(jwk->e[LWS_GENCRYPTO_KTY_OCT].buf, key, ulen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk,
|
||||
enum lws_gencrypto_kty kty, int bits, const char *curve)
|
||||
{
|
||||
size_t sn;
|
||||
int n;
|
||||
|
||||
memset(jwk, 0, sizeof(*jwk));
|
||||
|
||||
jwk->kty = (int)kty;
|
||||
jwk->private_key = 1;
|
||||
|
||||
switch (kty) {
|
||||
case LWS_GENCRYPTO_KTY_RSA:
|
||||
{
|
||||
struct lws_genrsa_ctx ctx;
|
||||
|
||||
lwsl_notice("%s: generating %d bit RSA key\n", __func__, bits);
|
||||
n = lws_genrsa_new_keypair(context, &ctx, LGRSAM_PKCS1_1_5,
|
||||
jwk->e, bits);
|
||||
lws_genrsa_destroy(&ctx);
|
||||
if (n) {
|
||||
lwsl_err("%s: problem generating RSA key\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LWS_GENCRYPTO_KTY_OCT:
|
||||
sn = (unsigned int)lws_gencrypto_bits_to_bytes(bits);
|
||||
jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf = lws_malloc(sn, "oct");
|
||||
if (!jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf)
|
||||
return 1;
|
||||
jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = (uint32_t)sn;
|
||||
if (lws_get_random(context,
|
||||
jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, sn) != sn) {
|
||||
lwsl_err("%s: problem getting random\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case LWS_GENCRYPTO_KTY_EC:
|
||||
{
|
||||
struct lws_genec_ctx ctx;
|
||||
|
||||
if (!curve) {
|
||||
lwsl_err("%s: must have a named curve\n", __func__);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lws_genecdsa_create(&ctx, context, NULL))
|
||||
return 1;
|
||||
|
||||
lwsl_notice("%s: generating ECDSA key on curve %s\n", __func__,
|
||||
curve);
|
||||
|
||||
n = lws_genecdsa_new_keypair(&ctx, curve, jwk->e);
|
||||
lws_genec_destroy(&ctx);
|
||||
if (n) {
|
||||
lwsl_err("%s: problem generating ECDSA key\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_GENCRYPTO_KTY_UNKNOWN:
|
||||
default:
|
||||
lwsl_err("%s: unknown kty\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32)
|
||||
{
|
||||
struct lws_genhash_ctx hash_ctx;
|
||||
size_t tmpsize = 2536;
|
||||
char *tmp;
|
||||
int n, m = (int)tmpsize;
|
||||
|
||||
tmp = lws_malloc(tmpsize, "rfc7638 tmp");
|
||||
|
||||
n = lws_jwk_export(jwk, LWSJWKF_EXPORT_NOCRLF, tmp, &m);
|
||||
if (n < 0)
|
||||
goto bail;
|
||||
|
||||
if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))
|
||||
goto bail;
|
||||
|
||||
if (lws_genhash_update(&hash_ctx, tmp, (unsigned int)n)) {
|
||||
lws_genhash_destroy(&hash_ctx, NULL);
|
||||
|
||||
goto bail;
|
||||
}
|
||||
lws_free(tmp);
|
||||
|
||||
if (lws_genhash_destroy(&hash_ctx, digest32))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
lws_free(tmp);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
lws_jwk_strdup_meta(struct lws_jwk *jwk, enum enum_jwk_meta_tok idx,
|
||||
const char *in, int len)
|
||||
{
|
||||
jwk->meta[idx].buf = lws_malloc((unsigned int)len, __func__);
|
||||
if (!jwk->meta[idx].buf)
|
||||
return 1;
|
||||
jwk->meta[idx].len = (uint32_t)(unsigned int)len;
|
||||
memcpy(jwk->meta[idx].buf, in, (unsigned int)len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user