Skip to content

Commit ed18428

Browse files
committed
gencrypto: jose: cose: support ED25519 and ED448
1 parent 2a0eac5 commit ed18428

File tree

28 files changed

+1214
-66
lines changed

28 files changed

+1214
-66
lines changed

READMEs/README.cbor-cose.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ also supported.
1515

1616
|type|operations|algs|
1717
|---|---|---|
18-
|lws_cose_key_t|import, export, generation|EC / RSA / SYMMETRIC|
19-
|cose_sign1|sign, validate|ES256/384/512, RS256/384/512|
20-
|cose_sign|sign, validate|ES256/384/512, RS256/384/512|
18+
|lws_cose_key_t|import, export, generation|EC / RSA / SYMMETRIC / OKP|
19+
|cose_sign1|sign, validate|ES256/384/512, RS256/384/512, EdDSA|
20+
|cose_sign|sign, validate|ES256/384/512, RS256/384/512, EdDSA|
2121
|cose_mac0|sign, validate|HS256/HS256_64/384/512|
2222
|cose_mac|validate only|HS256/HS256_64/384/512|
2323

@@ -29,7 +29,7 @@ An increasing number of higher-level IETF specifications use COSE underneath.
2929
## cose_key and sets
3030

3131
Lws provides an `lws_cose_key_t` object to contain a single key's metadata and
32-
key material for EC, RSA and SYMMETRIC key types.
32+
key material for EC, RSA, SYMMETRIC and OKP key types.
3333

3434
There is a commandline tool wrapping the key dumping and generation apis
3535
available at `./minimal-examples/crypto/lws-crypto-cose-key`
@@ -77,7 +77,7 @@ it and returns a pointer to it.
7777

7878
`cose_kty` is one of `LWSCOSE_WKKTV_OKP`, `LWSCOSE_WKKTV_EC2`, `LWSCOSE_WKKTV_RSA`,
7979
or `LWSCOSE_WKKTV_SYMMETRIC`. `bits` is valid for RSA keys and for EC keys,
80-
`curve` should be a well-known curve name, one of `P-256`, `P-384` and `P-521`
80+
`curve` should be a well-known curve name, one of `P-256`, `P-384`, `P-521`, `Ed25519` or `Ed448`
8181
currently. `use_mask` is a bitfield made up of (1 << LWSCOSE_WKKO_...) set to
8282
enable the usage on the key.
8383

READMEs/README.crypto-apis.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ combinations are acceptable by querying the parsed JW structs).
6464

6565
- ECDH
6666
- ECDSA
67+
- EdDSA (requires building with OpenSSL `LWS_WITH_OPENSSL`)
6768
- P256 / P384 / P521 (sic) curves
69+
- Ed25519 / Ed448 curves (requires building with OpenSSL `LWS_WITH_OPENSSL`)
6870

6971
## Using the generic layer
7072

@@ -94,6 +96,7 @@ length of the array is defined by the cipher... it's one of
9496
|`LWS_COUNT_OCT_KEY_ELEMENTS`|1|
9597
|`LWS_COUNT_RSA_KEY_ELEMENTS`|8|
9698
|`LWS_COUNT_EC_KEY_ELEMENTS`|4|
99+
|`LWS_COUNT_OKP_KEY_ELEMENTS`|4|
97100
|`LWS_COUNT_AES_KEY_ELEMENTS`|1|
98101

99102
`struct lws_jwk_elements` is a simple pointer / length combination used to
@@ -145,6 +148,7 @@ The JOSE RFCs define specific short names for different algorithms
145148
---|---|---
146149
|RS256, RS384, RS512|SHA256/384/512|RSA
147150
|ES256, ES384, ES521|SHA256/384/512|EC
151+
|EdDSA|None|Ed25519 or Ed448 (Requires OpenSSL)
148152

149153
### JWE
150154

READMEs/README.crypto-dnssec.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ This generates:
6565

6666
*Note: You can specify other curves such as `P-384` or `P-521` using the `--curve` argument.*
6767

68+
### Step 2.5: Importing Existing NSD/BIND Keys (Optional)
69+
70+
If you are migrating an existing domain from standard BIND or NSD setups, you can import your existing DNSSEC keys directly into the `lws` JWK format without generating new ones.
71+
72+
The `importnsd` command takes your domain and the file prefixes of your existing `.private` and `.key` files (usually named like `Kmydomain.com.+013+12345`).
73+
74+
```bash
75+
lws-crypto-dnssec importnsd mydomain.com Kmydomain.com.+013+12345 Kmydomain.com.+013+67890
76+
```
77+
78+
The utility automatically parses the `DNSKEY` flags (256 for ZSK, 257 for KSK) to assign the correct roles, extracts the cryptographic parameters, and exports standard `mydomain.com.ksk.private.jwk` and `mydomain.com.zsk.private.jwk` files. It also generates a `mydomain.com.dnssec.txt` summarizing your DS records.
79+
6880
### Step 3: Extract DS Information for the Registrar
6981

7082
To establish the chain of trust, the parent zone (e.g., the `.com` registry) must publish a Delegation Signer (DS) record containing a cryptographic hash of your public KSK.

include/libwebsockets/lws-dht-dnssec.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ struct lws_dht_dnssec_signzone_args {
4444
uint32_t sign_validity_duration;
4545
};
4646

47+
struct lws_dht_dnssec_importnsd_args {
48+
const char *domain;
49+
const char *key1_prefix;
50+
const char *key2_prefix; /* optional if only importing 1 key */
51+
};
52+
4753
typedef void (*lws_dht_dnssec_fetch_cb_t)(void *opaque, const char *domain, int status);
4854

4955
struct lws_dht_dnssec_fetch_zone_args {
@@ -59,6 +65,7 @@ struct lws_dht_dnssec_ops {
5965
int (*keygen)(struct lws_context *context, struct lws_dht_dnssec_keygen_args *args);
6066
int (*dsfromkey)(struct lws_context *context, struct lws_dht_dnssec_dsfromkey_args *args);
6167
int (*signzone)(struct lws_context *context, struct lws_dht_dnssec_signzone_args *args);
68+
int (*importnsd)(struct lws_context *context, struct lws_dht_dnssec_importnsd_args *args);
6269

6370
int (*add_temp_zone)(struct lws_context *context, const char *domain, const char *zone_str, int ttl_secs);
6471
int (*publish_jws)(struct lws_context *context, const char *jws_filepath);

include/libwebsockets/lws-gencrypto.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ enum lws_gencrypto_kty {
3333

3434
LWS_GENCRYPTO_KTY_OCT,
3535
LWS_GENCRYPTO_KTY_RSA,
36-
LWS_GENCRYPTO_KTY_EC
36+
LWS_GENCRYPTO_KTY_EC,
37+
LWS_GENCRYPTO_KTY_OKP
3738
};
3839

3940
/*
@@ -86,6 +87,15 @@ enum lws_gencrypto_aes_tok {
8687
LWS_GENCRYPTO_AES_KEYEL_COUNT
8788
};
8889

90+
enum lws_gencrypto_okp_tok {
91+
LWS_GENCRYPTO_OKP_KEYEL_CRV,
92+
LWS_GENCRYPTO_OKP_KEYEL_X,
93+
/* note... same offset as RSA D */
94+
LWS_GENCRYPTO_OKP_KEYEL_D = LWS_GENCRYPTO_RSA_KEYEL_D,
95+
96+
LWS_GENCRYPTO_OKP_KEYEL_COUNT
97+
};
98+
8999
/* largest number of key elements for any algorithm */
90100
#define LWS_GENCRYPTO_MAX_KEYEL_COUNT LWS_GENCRYPTO_RSA_KEYEL_COUNT
91101

include/libwebsockets/lws-genec.h

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ enum enum_genec_alg {
2626
LEGENEC_UNKNOWN,
2727

2828
LEGENEC_ECDH,
29-
LEGENEC_ECDSA
29+
LEGENEC_ECDSA,
30+
LEGENEC_EDDSA
3031
};
3132

3233
struct lws_genec_ctx {
@@ -208,7 +209,74 @@ lws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
208209
uint8_t *sig, size_t sig_len);
209210

210211

211-
/* Apis that apply to both ECDH and ECDSA */
212+
/* EdDSA-specific apis */
213+
214+
/** lws_geneddsa_create() - Create a geneddsa
215+
*
216+
* \param ctx: your genec context
217+
* \param context: your lws_context (for RNG access)
218+
* \param curve_table: NULL, enabling ED25519 and ED448, or a replacement
219+
* struct lws_ec_curves array, terminated by an entry with
220+
* .name = NULL, of curves you want to allow
221+
*
222+
* Initializes a geneddsa
223+
*/
224+
LWS_VISIBLE int
225+
lws_geneddsa_create(struct lws_genec_ctx *ctx, struct lws_context *context,
226+
const struct lws_ec_curves *curve_table);
227+
228+
/** lws_geneddsa_new_keypair() - Create a geneddsa with a new public / private key
229+
*
230+
* \param ctx: your genec context
231+
* \param curve_name: an EdDSA curve name, like "ED25519"
232+
* \param el: array pf LWS_GENCRYPTO_OKP_KEYEL_COUNT key elements to take the new key
233+
*
234+
* Creates a geneddsa with a newly minted EdDSA public / private key
235+
*/
236+
LWS_VISIBLE LWS_EXTERN int
237+
lws_geneddsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name,
238+
struct lws_gencrypto_keyelem *el);
239+
240+
/** lws_geneddsa_set_key() - Apply an OKP key to an eddsa context
241+
*
242+
* \param ctx: your geneddsa context
243+
* \param el: your key elements
244+
*
245+
* Applies an OKP key to an eddsa context
246+
*/
247+
LWS_VISIBLE LWS_EXTERN int
248+
lws_geneddsa_set_key(struct lws_genec_ctx *ctx,
249+
const struct lws_gencrypto_keyelem *el);
250+
251+
/** lws_geneddsa_hash_sig_verify_jws() - Verifies a JWS EdDSA signature on a given payload
252+
*
253+
* \param ctx: your struct lws_genrsa_ctx
254+
* \param in: raw payload
255+
* \param in_len: raw payload length
256+
* \param sig: pointer to the signature we received with the payload
257+
* \param sig_len: length of the signature we are checking in bytes
258+
*
259+
* Returns <0 for error, or 0 if signature matches the payload + key..
260+
*/
261+
LWS_VISIBLE LWS_EXTERN int
262+
lws_geneddsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
263+
size_t in_len, const uint8_t *sig, size_t sig_len);
264+
265+
/** lws_geneddsa_hash_sign_jws() - Creates a JWS EdDSA signature for a payload you provide
266+
*
267+
* \param ctx: your struct lws_genrsa_ctx
268+
* \param in: raw payload to sign
269+
* \param in_len: length of the payload
270+
* \param sig: pointer to buffer to take signature
271+
* \param sig_len: length of the buffer
272+
*
273+
* Returns <0 for error, or >=0 for success.
274+
*/
275+
LWS_VISIBLE LWS_EXTERN int
276+
lws_geneddsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
277+
size_t in_len, uint8_t *sig, size_t sig_len);
278+
279+
/* Apis that apply to ECDH, ECDSA and EdDSA */
212280

213281
LWS_VISIBLE LWS_EXTERN void
214282
lws_genec_destroy(struct lws_genec_ctx *ctx);

include/libwebsockets/lws-jose.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ enum lws_jose_algtype {
6565
LWS_JOSE_ENCTYPE_ECDSA,
6666
LWS_JOSE_ENCTYPE_ECDHES,
6767

68+
LWS_JOSE_ENCTYPE_EDDSA,
69+
6870
LWS_JOSE_ENCTYPE_AES_CBC,
6971
LWS_JOSE_ENCTYPE_AES_CFB128,
7072
LWS_JOSE_ENCTYPE_AES_CFB8,

include/libwebsockets/lws-jwk.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct lws_jwk_parse_state {
6666
int pos;
6767
int cose_state;
6868
int seen;
69-
unsigned short possible;
69+
unsigned int possible;
7070
};
7171

7272
/** lws_jwk_import() - Create a JSON Web key from the textual representation

0 commit comments

Comments
 (0)