1 /* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25 /** \defgroup cose COSE apis 26 * ##COSE related functions 27 * \ingroup lwsaoi 28 * 29 * COSE RFC 8152 relates to signed and encrypted CBOR 30 */ 31 //@{ 32 33 enum { 34 /* RFC8152: Table 2: Common Header Parameters 35 * https://www.iana.org/assignments/cose/cose.xhtml#header-parameters 36 */ 37 38 LWSCOSE_WKL_ALG = 1, /* int / tstr */ 39 LWSCOSE_WKL_CRIT, /* [+ label ] */ 40 LWSCOSE_WKL_CONTENT_TYPE, /* tstr / uint */ 41 LWSCOSE_WKL_KID, /* bstr */ 42 LWSCOSE_WKL_IV, /* bstr */ 43 LWSCOSE_WKL_IV_PARTIAL, /* bstr */ 44 LWSCOSE_WKL_COUNTERSIG, /* COSE sig(s) */ 45 LWSCOSE_WKL_COUNTERSIG0 = 9, /* bstr */ 46 LWSCOSE_WKL_KID_CONTEXT, /* bstr */ 47 LWSCOSE_WKL_CUPH_NONCE = 256, /* bstr */ 48 LWSCOSE_WKL_CUPH_OWNER_PUBKEY = 257, /* array */ 49 50 /* RFC8152: Table 3: key map labels */ 51 52 LWSCOSE_WKK_KTY = 1, /* int / tstr */ 53 LWSCOSE_WKK_KID, /* bstr */ 54 LWSCOSE_WKK_ALG, /* int / tstr */ 55 LWSCOSE_WKK_KEY_OPS, /* [ + (int / tstr) ] */ 56 LWSCOSE_WKK_BASE_IV, /* bstr */ 57 58 /* RFC8152: Table 4: Key Operation Values */ 59 60 LWSCOSE_WKKO_SIGN = 1, 61 LWSCOSE_WKKO_VERIFY, 62 LWSCOSE_WKKO_ENCRYPT, 63 LWSCOSE_WKKO_DECRYPT, 64 LWSCOSE_WKKO_WRAP_KEY, 65 LWSCOSE_WKKO_UNWRAP_KEY, 66 LWSCOSE_WKKO_DERIVE_KEY, 67 LWSCOSE_WKKO_DERIVE_BITS, 68 LWSCOSE_WKKO_MAC_CREATE, 69 LWSCOSE_WKKO_MAC_VERIFY, 70 71 /* RFC8152: Table 5: ECDSA algs */ 72 73 LWSCOSE_WKAECDSA_ALG_ES256 = -7, 74 LWSCOSE_WKAECDSA_ALG_ES384 = -35, 75 LWSCOSE_WKAECDSA_ALG_ES512 = -36, 76 77 /* RFC8152: Table 6: EDDSA algs */ 78 79 LWSCOSE_WKAEDDSA_ALG_EDDSA = -8, 80 81 /* RFC8152: Table 7: HMAC algs */ 82 83 LWSCOSE_WKAHMAC_256_64 = 4, 84 LWSCOSE_WKAHMAC_256_256, 85 LWSCOSE_WKAHMAC_384_384, 86 LWSCOSE_WKAHMAC_512_512, 87 88 /* RFC8152: Table 8: AES algs */ 89 90 LWSCOSE_WKAAES_128_64 = 14, 91 LWSCOSE_WKAAES_256_64, 92 LWSCOSE_WKAAES_128_128 = 25, 93 LWSCOSE_WKAAES_256_128, 94 95 /* RFC8152: Table 9: AES GCM algs */ 96 97 LWSCOSE_WKAAESGCM_128 = 1, 98 LWSCOSE_WKAAESGCM_192, 99 LWSCOSE_WKAAESGCM_256, 100 101 /* RFC8152: Table 10: AES CCM algs */ 102 103 LWSCOSE_WKAAESCCM_16_64_128 = 10, 104 LWSCOSE_WKAAESCCM_16_64_256, 105 LWSCOSE_WKAAESCCM_64_64_128, 106 LWSCOSE_WKAAESCCM_64_64_256, 107 LWSCOSE_WKAAESCCM_16_128_128, 108 LWSCOSE_WKAAESCCM_16_128_256, 109 LWSCOSE_WKAAESCCM_64_128_128, 110 LWSCOSE_WKAAESCCM_64_128_256, 111 112 /* RFC8152: Table 11: CHACHA20 / Poly1305 */ 113 114 LWSCOSE_WKACHACHA_POLY1305 = 24, 115 116 /* RFC8152: Table 13: HKDF param */ 117 118 LWSCOSE_WKAPHKDF_SALT = -20, 119 120 /* RFC8152: Table 14: Context Algorithm Parameters */ 121 122 LWSCOSE_WKAPCTX_PARTY_U_IDENTITY = -21, 123 LWSCOSE_WKAPCTX_PARTY_U_NONCE = -22, 124 LWSCOSE_WKAPCTX_PARTY_U_OTHER = -23, 125 LWSCOSE_WKAPCTX_PARTY_V_IDENTITY = -24, 126 LWSCOSE_WKAPCTX_PARTY_V_NONCE = -25, 127 LWSCOSE_WKAPCTX_PARTY_V_OTHER = -26, 128 129 /* RFC8152: Table 15: Direct key */ 130 131 LWSCOSE_WKK_DIRECT_CEK = -6, 132 133 /* RFC8152: Table 16: Direct key with KDF */ 134 135 LWSCOSE_WKK_DIRECT_HKDF_SHA_256 = -10, 136 LWSCOSE_WKK_DIRECT_HKDF_SHA_512 = -11, 137 LWSCOSE_WKK_DIRECT_HKDF_AES_128 = -12, 138 LWSCOSE_WKK_DIRECT_HKDF_AES_256 = -13, 139 140 /* RFC8152: Table 17: AES Key Wrap Algorithm Values */ 141 142 LWSCOSE_WKK_DIRECT_HKDFKW_SHA_256 = -3, 143 LWSCOSE_WKK_DIRECT_HKDFKW_SHA_512 = -4, 144 LWSCOSE_WKK_DIRECT_HKDFKW_AES_128 = -5, 145 146 /* RFC8152: Table 18: ECDH Algorithm Values */ 147 148 LWSCOSE_WKAECDH_ALG_ES_HKDF_256 = -25, 149 LWSCOSE_WKAECDH_ALG_ES_HKDF_512 = -26, 150 LWSCOSE_WKAECDH_ALG_SS_HKDF_256 = -27, 151 LWSCOSE_WKAECDH_ALG_SS_HKDF_512 = -28, 152 153 /* RFC8152: Table 19: ECDH Algorithm Parameters */ 154 155 LWSCOSE_WKAPECDH_EPHEMERAL_KEY = -1, 156 LWSCOSE_WKAPECDH_STATIC_KEY = -2, 157 LWSCOSE_WKAPECDH_STATIC_KEY_ID = -3, 158 159 /* RFC8152: Table 20: ECDH Algorithm Parameters with key wrap */ 160 161 LWSCOSE_WKAPECDH_ES_A128KW = -29, 162 LWSCOSE_WKAPECDH_ES_A192KW = -30, 163 LWSCOSE_WKAPECDH_ES_A256KW = -31, 164 LWSCOSE_WKAPECDH_SS_A128KW = -32, 165 LWSCOSE_WKAPECDH_SS_A192KW = -33, 166 LWSCOSE_WKAPECDH_SS_A256KW = -34, 167 168 /* RFC8152: Table 21: Key Type Values 169 * https://www.iana.org/assignments/cose/cose.xhtml#key-type 170 */ 171 172 LWSCOSE_WKKTV_OKP = 1, 173 LWSCOSE_WKKTV_EC2 = 2, 174 LWSCOSE_WKKTV_RSA = 3, 175 LWSCOSE_WKKTV_SYMMETRIC = 4, 176 LWSCOSE_WKKTV_HSS_LMS = 5, 177 LWSCOSE_WKKTV_WALNUTDSA = 6, 178 179 180 /* RFC8152: Table 22: Elliptic Curves 181 * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves 182 */ 183 184 LWSCOSE_WKEC_P256 = 1, 185 LWSCOSE_WKEC_P384, 186 LWSCOSE_WKEC_P521, 187 LWSCOSE_WKEC_X25519, 188 LWSCOSE_WKEC_X448, 189 LWSCOSE_WKEC_ED25519, 190 LWSCOSE_WKEC_ED448, 191 LWSCOSE_WKEC_SECP256K1, 192 193 /* RFC8152: Table 23: EC Key Parameters */ 194 195 LWSCOSE_WKECKP_CRV = -1, 196 LWSCOSE_WKECKP_X = -2, 197 LWSCOSE_WKECKP_Y = -3, 198 LWSCOSE_WKECKP_D = -4, 199 200 /* RFC8152: Table 24: Octet Key Pair (OKP) Parameters */ 201 202 LWSCOSE_WKOKP_CRV = -1, 203 LWSCOSE_WKOKP_X = -2, 204 LWSCOSE_WKOKP_D = -4, 205 206 /* Additional from 207 * https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters 208 */ 209 210 LWSCOSE_WKKPRSA_N = -1, 211 LWSCOSE_WKKPRSA_E = -2, 212 LWSCOSE_WKKPRSA_D = -3, 213 LWSCOSE_WKKPRSA_P = -4, 214 LWSCOSE_WKKPRSA_Q = -5, 215 LWSCOSE_WKKPRSA_DP = -6, 216 LWSCOSE_WKKPRSA_DQ = -7, 217 LWSCOSE_WKKPRSA_QINV = -8, 218 LWSCOSE_WKKPRSA_OTHER = -9, 219 LWSCOSE_WKKPRSA_RI = -10, 220 LWSCOSE_WKKPRSA_DI = -11, 221 LWSCOSE_WKKPRSA_TI = -12, 222 223 /* RFC8152: Table 25: Symmetric Key Parameters */ 224 225 LWSCOSE_WKSYMKP_KEY_VALUE = 4, 226 227 /* RFC8152: Table 26: CoAP Content-Formats for COSE */ 228 229 LWSCOAP_CONTENTFORMAT_COSE_SIGN = 98, 230 LWSCOAP_CONTENTFORMAT_COSE_SIGN1 = 18, 231 LWSCOAP_CONTENTFORMAT_COSE_ENCRYPT = 96, 232 LWSCOAP_CONTENTFORMAT_COSE_ENCRYPT0 = 16, 233 LWSCOAP_CONTENTFORMAT_COSE_MAC = 97, 234 LWSCOAP_CONTENTFORMAT_COSE_MAC0 = 17, 235 LWSCOAP_CONTENTFORMAT_COSE_KEY = 101, 236 LWSCOAP_CONTENTFORMAT_COSE_KEY_SET = 102, 237 238 /* RFC8152: Table 27: Header Parameter for CounterSignature0 */ 239 240 LWSCOSE_WKL_COUNTERSIGNATURE0 = 9, /* bstr */ 241 242 /* RFC8812: Table 1: RSASSA-PKCS1-v1_5 Algorithm Values */ 243 244 LWSCOSE_WKARSA_ALG_RS256 = -257, /* + SHA-256 */ 245 LWSCOSE_WKARSA_ALG_RS384 = -258, /* + SHA-384 */ 246 LWSCOSE_WKARSA_ALG_RS512 = -259, /* + SHA-512 */ 247 }; 248 249 enum enum_cose_key_meta_tok { 250 COSEKEY_META_KTY, 251 COSEKEY_META_KID, 252 COSEKEY_META_KEY_OPS, 253 COSEKEY_META_BASE_IV, 254 COSEKEY_META_ALG, 255 256 LWS_COUNT_COSE_KEY_ELEMENTS 257 }; 258 259 typedef int64_t cose_param_t; 260 261 LWS_VISIBLE LWS_EXTERN const char * 262 lws_cose_alg_to_name(cose_param_t alg); 263 264 LWS_VISIBLE LWS_EXTERN cose_param_t 265 lws_cose_name_to_alg(const char *name); 266 267 /* 268 * cose_key 269 */ 270 271 typedef struct lws_cose_key { 272 /* key data elements */ 273 struct lws_gencrypto_keyelem e[LWS_GENCRYPTO_MAX_KEYEL_COUNT]; 274 /* generic meta key elements, like KID */ 275 struct lws_gencrypto_keyelem meta[LWS_COUNT_COSE_KEY_ELEMENTS]; 276 lws_dll2_t list; /* used when part of a set */ 277 int gencrypto_kty; /**< one of LWS_GENCRYPTO_KTY_ */ 278 cose_param_t kty; 279 cose_param_t cose_alg; 280 cose_param_t cose_curve; 281 char private_key; /* nonzero = has private key elements */ 282 } lws_cose_key_t; 283 284 typedef int (*lws_cose_key_import_callback)(struct lws_cose_key *s, void *user); 285 286 /** lws_cose_jwk_import() - Create an lws_cose_key_t object from cose_key CBOR 287 * 288 * \param pkey_set: NULL, or a pointer to an lws_dll2_owner_t for a cose_key set 289 * \param cb: callback for each jwk-processed key, or NULL if importing a single 290 * key with no parent "keys" JSON 291 * \param user: pointer to be passed to the callback, otherwise ignored by lws. 292 * NULL if importing a single key with no parent "keys" JSON 293 * \param in: a single cose_key 294 * \param len: the length of the cose_key in bytes 295 * 296 * Creates a single lws_cose_key_t if \p pkey_set is NULL or if the incoming 297 * CBOR doesn't start with an array, otherwise expects a CBOR array containing 298 * zero or more cose_key CBOR, and adds each to the \p pkey_set 299 * lws_dll2_owner_t struct. Created lws_cose_key_t are filled with data from 300 * the COSE representation and can be used with other COSE crypto ops. 301 */ 302 LWS_VISIBLE LWS_EXTERN lws_cose_key_t * 303 lws_cose_key_import(lws_dll2_owner_t *pkey_set, lws_cose_key_import_callback cb, 304 void *user, const uint8_t *in, size_t len); 305 306 /** lws_cose_key_export() - Create cose_key CBOR from an lws_cose_key_t 307 * 308 * \param ck: the lws_cose_key_t to export to CBOR 309 * \param ctx: the CBOR writing context (same as for lws_lec_printf()) 310 * \param flags: 0 to export only public elements, or LWSJWKF_EXPORT_PRIVATE 311 * 312 * Creates an lws_jwk struct filled with data from the COSE representation. 313 */ 314 LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret 315 lws_cose_key_export(lws_cose_key_t *ck, lws_lec_pctx_t *ctx, int flags); 316 317 /** 318 * lws_cose_key_generate() - generate a fresh key 319 * 320 * \param context: the lws_context used to get random 321 * \param cose_kty: one of LWSCOSE_WKKTV_ indicating the well-known key type 322 * \param use_mask: 0, or a bitfield where (1 << LWSCOSE_WKKO_...) set means valid for use 323 * \param bits: key bits for RSA 324 * \param curve: for EC keys, one of "P-256", "P-384" or "P-521" currently 325 * \param kid: string describing the key, or NULL 326 * 327 * Create an lws_cose_key_t of the specified type and return it 328 */ 329 LWS_VISIBLE LWS_EXTERN lws_cose_key_t * 330 lws_cose_key_generate(struct lws_context *context, cose_param_t cose_kty, 331 int use_mask, int bits, const char *curve, 332 const uint8_t *kid, size_t kl); 333 334 LWS_VISIBLE LWS_EXTERN lws_cose_key_t * 335 lws_cose_key_from_set(lws_dll2_owner_t *set, const uint8_t *kid, size_t kl); 336 337 LWS_VISIBLE LWS_EXTERN void 338 lws_cose_key_destroy(lws_cose_key_t **ck); 339 340 LWS_VISIBLE LWS_EXTERN void 341 lws_cose_key_set_destroy(lws_dll2_owner_t *o); 342 343 /* only available in _DEBUG build */ 344 345 LWS_VISIBLE LWS_EXTERN void 346 lws_cose_key_dump(const lws_cose_key_t *ck); 347 348 /* 349 * cose_sign 350 */ 351 352 struct lws_cose_validate_context; 353 354 355 enum lws_cose_sig_types { 356 SIGTYPE_UNKNOWN, 357 SIGTYPE_MULTI, 358 SIGTYPE_SINGLE, 359 SIGTYPE_COUNTERSIGNED, /* not yet supported */ 360 SIGTYPE_MAC, /* only supported for validation */ 361 SIGTYPE_MAC0, 362 }; 363 364 /* a list of these result objects is the output of the validation process */ 365 366 typedef struct { 367 lws_dll2_t list; 368 369 const lws_cose_key_t *cose_key; 370 cose_param_t cose_alg; 371 372 int result; /* 0 = validated */ 373 374 } lws_cose_validate_res_t; 375 376 enum { 377 LCOSESIGEXTCB_RET_FINISHED, 378 LCOSESIGEXTCB_RET_AGAIN, 379 LCOSESIGEXTCB_RET_ERROR = -1 380 }; 381 382 typedef struct { 383 struct lws_cose_validate_context *cps; 384 const uint8_t *ext; 385 size_t xl; 386 } lws_cose_sig_ext_pay_t; 387 388 typedef int (*lws_cose_sign_ext_pay_cb_t)(lws_cose_sig_ext_pay_t *x); 389 typedef int (*lws_cose_validate_pay_cb_t)(struct lws_cose_validate_context *cps, 390 void *opaque, const uint8_t *paychunk, 391 size_t paychunk_len); 392 393 typedef struct lws_cose_validate_create_info { 394 struct lws_context *cx; 395 /**< REQUIRED: the lws context */ 396 lws_dll2_owner_t *keyset; 397 /**< REQUIRED: one or more cose_keys */ 398 399 enum lws_cose_sig_types sigtype; 400 /**< 0 if a CBOR tag is in the sig, else one of SIGTYPE_MULTI, 401 * SIGTYPE_SINGLE, etc*/ 402 403 lws_cose_validate_pay_cb_t pay_cb; 404 /**< optional: called back with unvalidated payload pieces */ 405 void *pay_opaque; 406 /**< optional: passed into pay_cb callback along with payload chunk */ 407 408 lws_cose_sign_ext_pay_cb_t ext_cb; 409 /**< optional extra application data provision callback */ 410 void *ext_opaque; 411 /**< optional extra application data provision callback opaque */ 412 size_t ext_len; 413 /**< if we have extra app data, this must be set to the length of it */ 414 } lws_cose_validate_create_info_t; 415 416 /** 417 * lws_cose_validate_create() - create a signature validation context 418 * 419 * \param info: struct describing the validation context to create 420 * 421 * Creates a signature validation context set up as described in \p info. 422 * 423 * You can then pass the signature cbor chunks to it using 424 * lws_cose_validate_chunk(), finialize and get the results list using 425 * lws_cose_validate_results() and destroy with lws_cose_validate_destroy(). 426 */ 427 LWS_VISIBLE LWS_EXTERN struct lws_cose_validate_context * 428 lws_cose_validate_create(const lws_cose_validate_create_info_t *info); 429 430 /** 431 * lws_cose_validate_chunk() - passes chunks of CBOR into the signature validator 432 * 433 * \param cps: the validation context 434 * \param in: the chunk of CBOR (does not have to be logically complete) 435 * \param in_len: number of bytes available at \p in 436 * 437 * Parses signature CBOR to produce a list of result objects. 438 * 439 * 440 */ 441 LWS_VISIBLE LWS_EXTERN int 442 lws_cose_validate_chunk(struct lws_cose_validate_context *cps, 443 const uint8_t *in, size_t in_len, size_t *used_in); 444 445 LWS_VISIBLE LWS_EXTERN lws_dll2_owner_t * 446 lws_cose_validate_results(struct lws_cose_validate_context *cps); 447 448 LWS_VISIBLE LWS_EXTERN void 449 lws_cose_validate_destroy(struct lws_cose_validate_context **cps); 450 451 struct lws_cose_sign_context; 452 453 #define LCSC_FL_ADD_CBOR_TAG (1 << 0) 454 #define LCSC_FL_ADD_CBOR_PREFER_MAC0 (1 << 1) 455 456 typedef struct lws_cose_sign_create_info { 457 struct lws_context *cx; 458 /**< REQUIRED: the lws context */ 459 lws_dll2_owner_t *keyset; 460 /**< REQUIRED: one or more cose_keys */ 461 462 lws_lec_pctx_t *lec; 463 /**< REQUIRED: the cbor output context to emit to, user must 464 * initialize with lws_lec_init() beforehand */ 465 466 lws_cose_sign_ext_pay_cb_t ext_cb; 467 /**< optional extra application data provision callback */ 468 void *ext_opaque; 469 /**< optional extra application data provision callback opaque */ 470 size_t ext_len; 471 /**< if we have extra app data, this must be set to the length of it */ 472 473 size_t inline_payload_len; 474 /**< REQUIRED: size of the inline payload we will provide */ 475 476 int flags; 477 /**< bitmap of LCSC_FL_* */ 478 enum lws_cose_sig_types sigtype; 479 /**< 0, or sign type hint */ 480 } lws_cose_sign_create_info_t; 481 482 /** 483 * lws_cose_sign_create() - Create a signing context 484 * 485 * \param info: a structure describing the signing context you want to create 486 * 487 * This allocates and returns a signing context created according to what is in 488 * the \p info parameter. 489 * 490 * \p info must be prepared with the lws_context, a keyset to use, a CBOR 491 * output context, and the inline payload length. 492 * 493 * Returns NULL on failure or the created signing context ready to add alg(s) 494 * to. 495 */ 496 497 LWS_VISIBLE LWS_EXTERN struct lws_cose_sign_context * 498 lws_cose_sign_create(const lws_cose_sign_create_info_t *info); 499 500 LWS_VISIBLE LWS_EXTERN int 501 lws_cose_sign_add(struct lws_cose_sign_context *csc, cose_param_t alg, 502 const lws_cose_key_t *ck); 503 504 LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret 505 lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, 506 const uint8_t *in, size_t in_len); 507 508 LWS_VISIBLE LWS_EXTERN void 509 lws_cose_sign_destroy(struct lws_cose_sign_context **csc); 510 511 //@} 512