/ kems.c
kems.c
1 #include <stdlib.h> 2 #include <string.h> 3 #include <lscore/index.h> 4 #include <lscore/plugin.h> 5 #include <lsplugin/mkobject.h> 6 #include <lsplugin/mkoperator.h> 7 #include <lsplugin/param.h> 8 #include <oqs/kem.h> 9 #include "local.h" 10 11 /* The live key structure */ 12 struct oqs_key_st { 13 uint8_t *sec; size_t sec_len; /* secret (private) key */ 14 uint8_t *pub; size_t pub_len; /* public key */ 15 }; 16 17 /* All data and descriptor structures for one OQS algorithm */ 18 struct oqs_impl_st { 19 /* The self-standing encapsulator and decapsulator... really just for convenience */ 20 LSplugin_encapsulator_desc_t encapsulator; 21 LSplugin_decapsulator_desc_t decapsulator; 22 /* The key associated encapsulator and decapsulator */ 23 LSplugin_encapsulator_desc_t assoc_encapsulator; 24 LSplugin_decapsulator_desc_t assoc_decapsulator; 25 LSplugin_key_generator_desc_t assoc_generator; 26 LSplugin_key_constructor_desc_t assoc_constructor; 27 LSplugin_key_extractor_desc_t assoc_extractor; 28 /* The key itself */ 29 LSplugin_key_desc_t key; 30 31 /* The parameters, made as a substructure to get pointers easily */ 32 struct oqs_data_st { 33 OQS_KEM *kem; 34 LSC_param_desc_t param_desc[3]; /* Space for the sec and pub key, and NULL */ 35 } _; 36 }; 37 38 /* Param helpers */ 39 40 static LSplugin_param_functions_t sec_fns = { 41 offsetof(struct oqs_key_st, sec), 42 offsetof(struct oqs_key_st, sec_len), 43 0, false, 44 LSplugin_set_octetstring_param, LSplugin_get_octetstring_param 45 }; 46 static LSplugin_param_functions_t pub_fns = { 47 offsetof(struct oqs_key_st, pub), 48 offsetof(struct oqs_key_st, pub_len), 49 0, false, 50 LSplugin_set_octetstring_param, LSplugin_get_octetstring_param 51 }; 52 53 /* 54 * The set of functions that actually do something 55 */ 56 57 /* For encapsulator operations */ 58 59 static LE_STATUS set_encap_key(LSC_encapsulator_t *op, LSC_key_t *key) 60 { 61 op->lsc_data = key; 62 return LE_STS_SUCCESS; 63 } 64 static LE_STATUS get_encap_key(LSC_encapsulator_t *op, LSC_key_t **key) 65 { 66 *key = op->lsc_data; 67 return LE_STS_SUCCESS; 68 } 69 70 static LE_STATUS get_encap_shared_secret_size(LSC_encapsulator_t *encap, size_t *size) 71 { 72 const LSplugin_encapsulator_desc_t *desc = encap->lsc_dispatch_data; 73 const struct oqs_data_st *data = desc->lsp_priv_desc; 74 *size = data->kem->length_shared_secret; 75 return LE_STS_SUCCESS; 76 } 77 static LE_STATUS get_encap_output_size(LSC_encapsulator_t *encap, size_t *size) 78 { 79 const LSplugin_encapsulator_desc_t *desc = encap->lsc_dispatch_data; 80 const struct oqs_data_st *data = desc->lsp_priv_desc; 81 *size = data->kem->length_ciphertext; 82 return LE_STS_SUCCESS; 83 } 84 static LE_STATUS perform_encap_once(LSC_encapsulator_t *op, 85 unsigned char *wrappedsecret, 86 size_t wrappedsecretsize, 87 size_t *wrappedsecretlen, 88 unsigned char *sharedsecret, 89 size_t sharedsecretsize, 90 size_t *sharedsecretlen) 91 { 92 LSC_key_t *key = op->lsc_data; 93 struct oqs_key_st *k = key->lsc_data; 94 const LSplugin_encapsulator_desc_t *desc = op->lsc_dispatch_data; 95 const struct oqs_data_st *data = desc->lsp_priv_desc; 96 if (data->kem->length_ciphertext > wrappedsecretsize 97 || data->kem->length_shared_secret > sharedsecretsize) 98 return LE_STS_ERROR; 99 if (k->pub == NULL) 100 return LE_STS_INVALID_PARAMETER; 101 OQS_STATUS oqssts = OQS_KEM_encaps(data->kem, wrappedsecret, sharedsecret, k->pub); 102 *wrappedsecretlen = data->kem->length_ciphertext; 103 *sharedsecretlen = data->kem->length_shared_secret; 104 return oqssts == OQS_SUCCESS ? LE_STS_SUCCESS : LE_STS_ERROR; 105 } 106 107 /* For decapsulator operations */ 108 109 static LE_STATUS set_decap_key(LSC_decapsulator_t *op, LSC_key_t *key) 110 { 111 op->lsc_data = key; 112 return LE_STS_SUCCESS; 113 } 114 static LE_STATUS get_decap_key(LSC_decapsulator_t *op, LSC_key_t **key) 115 { 116 *key = op->lsc_data; 117 return LE_STS_SUCCESS; 118 } 119 static LE_STATUS get_decap_input_size(LSC_decapsulator_t *decap, size_t *size) 120 { 121 const LSplugin_decapsulator_desc_t *desc = decap->lsc_dispatch_data; 122 const struct oqs_data_st *data = desc->lsp_priv_desc; 123 *size = data->kem->length_ciphertext; 124 return LE_STS_SUCCESS; 125 } 126 static LE_STATUS get_decap_shared_secret_size(LSC_decapsulator_t *decap, size_t *size) 127 { 128 const LSplugin_decapsulator_desc_t *desc = decap->lsc_dispatch_data; 129 const struct oqs_data_st *data = desc->lsp_priv_desc; 130 *size = data->kem->length_shared_secret; 131 return LE_STS_SUCCESS; 132 } 133 static LE_STATUS perform_decap_once(LSC_decapsulator_t *op, 134 const unsigned char *wrappedsecret, 135 size_t wrappedsecretlen, 136 unsigned char *sharedsecret, 137 size_t sharedsecretsize, 138 size_t *sharedsecretlen) 139 { 140 LSC_key_t *key = op->lsc_data; 141 struct oqs_key_st *k = key->lsc_data; 142 const LSplugin_encapsulator_desc_t *desc = op->lsc_dispatch_data; 143 const const struct oqs_data_st *data = desc->lsp_priv_desc; 144 if (data->kem->length_ciphertext != wrappedsecretlen 145 || data->kem->length_shared_secret > sharedsecretsize) 146 return LE_STS_ERROR; 147 if (k->sec == NULL) 148 return LE_STS_INVALID_PARAMETER; 149 OQS_STATUS oqssts = OQS_KEM_decaps(data->kem, sharedsecret, wrappedsecret, k->sec); 150 *sharedsecretlen = data->kem->length_shared_secret; 151 return oqssts == OQS_SUCCESS ? LE_STS_SUCCESS : LE_STS_ERROR; 152 } 153 154 /* For generator operations */ 155 156 static LE_STATUS set_gen_key(LSC_key_generator_t *op, LSC_key_t *key) 157 { 158 op->lsc_data = key; 159 return LE_STS_SUCCESS; 160 } 161 162 static LE_STATUS get_gen_key(LSC_key_generator_t *op, LSC_key_t **key) 163 { 164 *key = op->lsc_data; 165 return LE_STS_SUCCESS; 166 } 167 168 static LE_STATUS generate_key(LSC_key_generator_t *op) 169 { 170 LSC_key_t *key = op->lsc_data; 171 struct oqs_key_st *k = key->lsc_data; 172 const LSplugin_key_generator_desc_t *desc = op->lsc_dispatch_data; 173 const struct oqs_data_st *data = desc->lsp_priv_desc; 174 k->sec = realloc(k->sec, data->kem->length_secret_key); 175 k->pub = realloc(k->pub, data->kem->length_public_key); 176 if (k->sec == NULL || k->pub == NULL) 177 return LE_STS_FATAL_ERROR; 178 OQS_STATUS oqssts = OQS_KEM_keypair(data->kem, k->pub, k->sec); 179 if (oqssts != OQS_SUCCESS) 180 return LE_STS_ERROR; 181 k->sec_len = data->kem->length_secret_key; 182 k->pub_len = data->kem->length_public_key; 183 return LE_STS_SUCCESS; 184 } 185 186 /* For constructor operations */ 187 188 static LE_STATUS set_con_key(LSC_key_constructor_t *op, LSC_key_t *key) 189 { 190 op->lsc_data = key; 191 return LE_STS_SUCCESS; 192 } 193 194 static LE_STATUS get_con_key(LSC_key_constructor_t *op, LSC_key_t **key) 195 { 196 *key = op->lsc_data; 197 return LE_STS_SUCCESS; 198 } 199 200 static LE_STATUS get_con_param_data(LSC_key_constructor_t *op, void **data) 201 { 202 LSC_key_t *key = op->lsc_data; 203 *data = key->lsc_data; 204 return LE_STS_SUCCESS; 205 } 206 207 static LE_STATUS 208 get_settable_con_param_desc(LSC_key_constructor_t *op, 209 const LSC_param_desc_t **param_desc) 210 { 211 const LSplugin_key_constructor_desc_t *desc = op->lsc_dispatch_data; 212 const struct oqs_data_st *data = desc->lsp_priv_desc; 213 *param_desc = data->param_desc; 214 return LE_STS_SUCCESS; 215 } 216 217 /* For extractor operations */ 218 219 static LE_STATUS set_ext_key(LSC_key_extractor_t *op, LSC_key_t *key) 220 { 221 op->lsc_data = key; 222 return LE_STS_SUCCESS; 223 } 224 225 static LE_STATUS get_ext_key(LSC_key_extractor_t *op, LSC_key_t **key) 226 { 227 *key = op->lsc_data; 228 return LE_STS_SUCCESS; 229 } 230 231 static LE_STATUS get_ext_param_data(LSC_key_extractor_t *op, void **data) 232 { 233 LSC_key_t *key = op->lsc_data; 234 *data = key->lsc_data; 235 return LE_STS_SUCCESS; 236 } 237 238 static LE_STATUS 239 get_gettable_ext_param_desc(LSC_key_extractor_t *op, 240 const LSC_param_desc_t **param_desc) 241 { 242 const LSplugin_key_extractor_desc_t *desc = op->lsc_dispatch_data; 243 const struct oqs_data_st *data = desc->lsp_priv_desc; 244 *param_desc = data->param_desc; 245 return LE_STS_SUCCESS; 246 } 247 248 /* For the key objects */ 249 250 static LE_STATUS setup_key_data(LSC_key_t *key, const void *priv_desc) 251 { 252 const struct oqs_data_st *data = priv_desc; 253 struct oqs_key_st **k = (struct oqs_key_st **)&(key->lsc_data); 254 if (*k == NULL) { 255 (*k) = malloc(sizeof(**k)); 256 memset(*k, 0, sizeof(**k)); 257 } 258 return LE_STS_SUCCESS; 259 } 260 261 static LE_STATUS clean_key_data(LSC_key_t *key) 262 { 263 struct oqs_key_st **k = (struct oqs_key_st **)&(key->lsc_data); 264 if (*k != NULL) { 265 free((*k)->sec); (*k)->sec = NULL; 266 free((*k)->pub); (*k)->pub = NULL; 267 free((*k)); *k = NULL; 268 } 269 return LE_STS_SUCCESS; 270 } 271 272 /* 273 * Create the list of struct oqs_encap_st, save that list in our environment, 274 * and register all the algorithms in the plugin's parent environment 275 */ 276 277 static struct oqs_impl_st *mkkemlist(void) 278 { 279 int nkems = OQS_KEM_alg_count(); 280 struct oqs_impl_st *kems = calloc(nkems + 1, sizeof(*kems)); 281 282 if (kems) 283 for (int i = 0, j = 0; i < nkems; i++) { 284 const char *name = OQS_KEM_alg_identifier(i); 285 if (!OQS_KEM_alg_is_enabled(name)) 286 continue; 287 OQS_KEM *encap = OQS_KEM_new(name); 288 if (encap == NULL) 289 continue; 290 size_t seclen = encap->length_secret_key; 291 size_t publen = encap->length_public_key; 292 293 kems[j] = (struct oqs_impl_st){ 294 /* Descriptors for the free standing implementations */ 295 .encapsulator = { 296 NULL, name, &kems[j]._, name, 297 NULL, NULL, 298 NULL, /* No lsp_set_key_encapsulator */ 299 set_encap_key, 300 get_encap_key, 301 (int[]){ LSC_ENCAPSULATOR_TYPE_BASE_COMMANDS(), 302 LSC_ENCAPSULATOR_SIZE_COMMANDS(), 303 LSC_NR_perform_encapsulation_once, 0 }, 304 NULL, 305 NULL, 306 NULL, 307 get_encap_shared_secret_size, 308 get_encap_output_size, 309 perform_encap_once, 310 }, 311 .decapsulator = { 312 NULL, name, &kems[j]._, name, 313 NULL, NULL, 314 NULL, /* No lsp_set_key_decapsulation */ 315 set_decap_key, 316 get_decap_key, 317 (int[]){ LSC_ENCAPSULATOR_TYPE_BASE_COMMANDS(), 318 LSC_ENCAPSULATOR_SIZE_COMMANDS(), 319 LSC_NR_perform_decapsulation_once, 0 }, 320 NULL, 321 NULL, 322 NULL, 323 get_decap_input_size, 324 get_decap_shared_secret_size, 325 perform_decap_once, 326 }, 327 328 /* Descriptors for the key associated implementations */ 329 .assoc_encapsulator = { 330 NULL, NULL, &kems[j]._, NULL, 331 NULL, NULL, 332 NULL, /* No lsp_set_key_encapsulator */ 333 set_encap_key, 334 get_encap_key, 335 (int[]){ LSC_ENCAPSULATOR_TYPE_BASE_COMMANDS(), 336 LSC_ENCAPSULATOR_SIZE_COMMANDS(), 337 LSC_NR_perform_encapsulation_once, 0 }, 338 NULL, 339 NULL, 340 NULL, 341 get_encap_shared_secret_size, 342 get_encap_output_size, 343 perform_encap_once, 344 }, 345 .assoc_decapsulator = { 346 NULL, NULL, &kems[j]._, NULL, 347 NULL, NULL, 348 NULL, /* No lsp_set_key_decapsulation */ 349 set_decap_key, 350 get_decap_key, 351 (int[]){ LSC_DECAPSULATOR_TYPE_BASE_COMMANDS(), 352 LSC_DECAPSULATOR_SIZE_COMMANDS(), 353 LSC_NR_perform_decapsulation_once, 0 }, 354 NULL, 355 NULL, 356 NULL, 357 get_decap_input_size, 358 get_decap_shared_secret_size, 359 perform_decap_once, 360 }, 361 362 /* Descriptors for the key generator */ 363 .assoc_generator = { 364 NULL, NULL, &kems[j]._, NULL, 365 NULL, NULL, 366 NULL, /* No lsp_set_key_generator */ 367 set_gen_key, 368 get_gen_key, 369 (int[]){ LSC_KEY_TYPE_BASE_COMMANDS(), 370 LSC_NR_generate_key, 0 }, 371 NULL, 372 NULL, /* No gettable */ 373 NULL, /* No settable */ 374 generate_key, 375 }, 376 377 /* Descriptors for the key constructor */ 378 .assoc_constructor = { 379 NULL, NULL, &kems[j]._, NULL, 380 NULL, NULL, 381 NULL, /* No lsp_set_key_constructor */ 382 set_con_key, 383 get_con_key, 384 (int[]){ LSC_KEY_TYPE_BASE_COMMANDS(), 385 LSC_NR_construct_key, 0 }, 386 get_con_param_data, 387 NULL, /* No gettable */ 388 get_settable_con_param_desc, 389 NULL, /* No constructor function */ 390 }, 391 392 /* Descriptors for the key extractor */ 393 .assoc_extractor = { 394 NULL, NULL, &kems[j]._, NULL, 395 NULL, NULL, 396 NULL, /* No lsp_set_key_extractor */ 397 set_ext_key, 398 get_ext_key, 399 (int[]){ LSC_KEY_TYPE_BASE_COMMANDS(), 0 }, 400 get_ext_param_data, 401 get_gettable_ext_param_desc, 402 NULL, /* No settable */ 403 }, 404 405 /* Descriptors for the key itself */ 406 .key = { 407 NULL, name, &kems[j]._, 408 setup_key_data, clean_key_data, 409 (int[]){ LSC_KEY_TYPE_BASE_COMMANDS(), 410 LSC_NR_get_key_generator, 411 LSC_NR_get_key_constructor, 412 LSC_NR_get_key_extractor, 413 LSC_NR_get_associated_encapsulator, 414 LSC_NR_get_associated_decapsulator, 0 }, 415 NULL, /* No get_key_size */ 416 &kems[j].assoc_generator, 417 &kems[j].assoc_constructor, 418 &kems[j].assoc_extractor, 419 NULL, 420 NULL, 421 NULL, 422 NULL, 423 NULL, 424 NULL, 425 &kems[j].assoc_encapsulator, 426 &kems[j].assoc_decapsulator, 427 }, 428 429 ._ = { 430 encap, 431 { 432 { "sec", 1, 433 { LSC_DT_octet_string, 434 { encap->length_secret_key, encap->length_secret_key } }, 435 &sec_fns, 436 "The secret key" }, 437 { "pub", 2, 438 { LSC_DT_octet_string, 439 { encap->length_public_key, encap->length_public_key } }, 440 &pub_fns, 441 "The public key" }, 442 { NULL, 0 } 443 } 444 } 445 }; 446 j++; 447 } 448 449 return kems; 450 } 451 452 static void freekemlist(struct oqs_impl_st *kems) 453 { 454 if (kems) { 455 for (struct oqs_impl_st *s = kems; s->key.lsp_id != NULL; s++) 456 OQS_KEM_free(s->_.kem); 457 free(kems); 458 } 459 } 460 461 /* The tag to get an index could be better... */ 462 static const char *tag = "oqs-kems"; 463 464 LE_STATUS oqs_register_kems(LSC_env_t *env, LSC_plugin_t *plugin) 465 { 466 LE_STATUS sts; 467 int index; 468 struct oqs_impl_st *kems = mkkemlist(); 469 470 if (kems == NULL) 471 return LE_STS_ALLOC_FAILURE; 472 if (LE_status_is_OK(sts = LSC_get_index(env, "oqs-kems", &index)) 473 && LE_status_is_OK(sts = LSC_set_plugin_application_data(plugin, index, kems))) 474 for (struct oqs_impl_st *s = kems; s->key.lsp_id != NULL; s++) { 475 sts = LSC_register_encapsulator_implementation(env, plugin, 476 s->encapsulator.lsp_id, 477 LSplugin_encapsulator_dispatch, 478 LSplugin_destroy_encapsulator, 479 &s->encapsulator, 480 s->encapsulator.lsp_docstring); 481 if (!LE_status_is_OK(sts)) 482 break; 483 sts = LSC_register_decapsulator_implementation(env, plugin, 484 s->decapsulator.lsp_id, 485 LSplugin_decapsulator_dispatch, 486 LSplugin_destroy_decapsulator, 487 &s->decapsulator, 488 s->decapsulator.lsp_docstring); 489 if (!LE_status_is_OK(sts)) 490 break; 491 sts = LSC_register_key_implementation(env, plugin, 492 s->key.lsp_id, 493 LSplugin_key_dispatch, 494 LSplugin_destroy_key, 495 &s->key, 496 s->key.lsp_docstring); 497 if (!LE_status_is_OK(sts)) 498 break; 499 } 500 501 return sts; 502 } 503 504 LE_STATUS oqs_deregister_kems(LSC_env_t *env, LSC_plugin_t *plugin) 505 { 506 LE_STATUS sts; 507 int index; 508 struct oqs_impl_st *kems = NULL; 509 510 if (LE_status_is_OK(sts = LSC_get_index(env, "oqs-kems", &index)) 511 && LE_status_is_OK(sts = LSC_get_plugin_application_data(plugin, index, &kems))) { 512 for (struct oqs_impl_st *s = kems; s->key.lsp_id != NULL; s++) { 513 sts = LSC_deregister_encapsulator_implementation(env, plugin, 514 s->encapsulator.lsp_id, 515 LSplugin_encapsulator_dispatch, 516 LSplugin_destroy_encapsulator, 517 &s->encapsulator, 518 s->encapsulator.lsp_docstring); 519 if (!LE_status_is_OK(sts)) 520 break; 521 sts = LSC_deregister_decapsulator_implementation(env, plugin, 522 s->decapsulator.lsp_id, 523 LSplugin_decapsulator_dispatch, 524 LSplugin_destroy_decapsulator, 525 &s->decapsulator, 526 s->decapsulator.lsp_docstring); 527 if (!LE_status_is_OK(sts)) 528 break; 529 sts = LSC_deregister_key_implementation(env, plugin, 530 s->key.lsp_id, 531 LSplugin_key_dispatch, 532 LSplugin_destroy_key, 533 &s->key, 534 s->key.lsp_docstring); 535 if (!LE_status_is_OK(sts)) 536 break; 537 } 538 freekemlist(kems); 539 } 540 return sts; 541 }