/ ltc-dh.c
ltc-dh.c
1 /* 2 * Licensed under the Apache License, Version 2.0 (the "License"); 3 * you may not use this file except in compliance with the License. 4 * See the NOTICE file distributed with this work for additional 5 * information regarding copyright ownership. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdarg.h> 18 #include <lscore/plugin.h> 19 #include <lscrypto/key.h> 20 #include <tomcrypt.h> 21 #include <lsplugin/mkobject.h> 22 #include <lsplugin/mkoperator.h> 23 #include <lsplugin/param.h> 24 #include "ltc-methods.h" 25 26 #define T(x) LE_status_is_OK(x) 27 28 #define nelems(a) (sizeof(a) / sizeof(a[0])) 29 30 /* Key data with support functions */ 31 struct ltc_dh_key_st { 32 /* 33 * I would prefer to have just the private and public key without the 34 * domain parameters, but the included domain parameters may be useful 35 * in some cases, so we keep around the whole libtomcrypt DH key for 36 * caching purposes if for nothing else. 37 * If DH is used in ephemeral mode and this key is used as the private 38 * key, a new |dh_key| will be derived from this for each derive operation. 39 */ 40 dh_key key; 41 42 /* Caches for key data operations */ 43 LSC_key_generator_t *generator; 44 LSC_key_constructor_t *constructor; 45 LSC_key_extractor_t *extractor; 46 /* Caches for primitive operations */ 47 LSC_derivator_t *derivator; 48 }; 49 50 /* Diverse parameter specification macros */ 51 52 #define DH_I_groupsize 0 53 #define DH_P_groupsize(t) \ 54 { "groupsize", DH_I_groupsize, \ 55 { LSC_DT_integer, { { sizeof(int), sizeof(int) }, }, }, \ 56 .p_private = &dh_##t##_groupsize_param_fns } 57 #define DH_I_prime 1 58 #define DH_I_base 2 59 #define DH_P_domain_params(t) \ 60 { "prime", DH_I_prime, \ 61 { LSC_DT_unsigned_integer, { { 0, 0 }, }, \ 62 .d_auxilliary.d_integer_desc = { \ 63 LSC_DTi_elem_is_bit, \ 64 LSC_DTi_mse_first_order \ 65 }, }, \ 66 .p_private = &dh_##t##_prime_param_fns }, \ 67 { "base", DH_I_base, \ 68 { LSC_DT_unsigned_integer, { { 0, 0 }, }, \ 69 .d_auxilliary.d_integer_desc = { \ 70 LSC_DTi_elem_is_bit, \ 71 LSC_DTi_mse_first_order \ 72 }, }, \ 73 .p_private = &dh_##t##_base_param_fns } 74 #define DH_I_pubkey 3 75 #define DH_I_privkey 4 76 #define DH_P_key(t) \ 77 { "pubkey", DH_I_pubkey, \ 78 { LSC_DT_unsigned_integer, { { 0, 0 }, }, \ 79 .d_auxilliary.d_integer_desc = { \ 80 LSC_DTi_elem_is_bit, \ 81 LSC_DTi_mse_first_order \ 82 }, }, \ 83 .p_private = &dh_##t##_pubkey_param_fns }, \ 84 { "privkey", DH_I_privkey, \ 85 { LSC_DT_unsigned_integer, { { 0, 0 }, }, \ 86 .d_auxilliary.d_integer_desc = { \ 87 LSC_DTi_elem_is_bit, \ 88 LSC_DTi_mse_first_order \ 89 }, }, \ 90 .p_private = &dh_##t##_privkey_param_fns } 91 92 /* 93 * The functions scrub_dh_data(), new_dh_data() and destroy_dh_data() 94 * are defined further down. 95 */ 96 static LE_STATUS scrub_dh_data(LSC_key_t *key); 97 static LE_STATUS new_dh_data(LSC_key_t *key, const void *unused); 98 99 /* Key generator operation with support functions */ 100 101 struct ltc_dh_generator_st { 102 LSC_key_t *key; 103 104 /* Operational parameters */ 105 106 int groupsize; 107 _Bool groupsize_set; 108 109 unsigned char *prime_bits; /* Known as |p| in DH descriptions */ 110 size_t prime_bits_len; /* ... in bits */ 111 112 unsigned char *base_bits; /* Known as |g| in DH descriptions */ 113 size_t base_bits_len; /* ... in bits */ 114 }; 115 116 static LSplugin_param_functions_t dh_gen_groupsize_param_fns = { 117 offsetof(struct ltc_dh_generator_st, groupsize), 0, 118 offsetof(struct ltc_dh_generator_st, groupsize_set), true, 119 LSplugin_set_int_param, LSplugin_get_int_param 120 }; 121 static LSplugin_param_functions_t dh_gen_prime_param_fns = { 122 offsetof(struct ltc_dh_generator_st, prime_bits), 123 offsetof(struct ltc_dh_generator_st, prime_bits_len), 124 0, false, 125 LSplugin_set_bitstring_param, LSplugin_get_bitstring_param 126 }; 127 static LSplugin_param_functions_t dh_gen_base_param_fns = { 128 offsetof(struct ltc_dh_generator_st, base_bits), 129 offsetof(struct ltc_dh_generator_st, base_bits_len), 130 0, false, 131 LSplugin_set_bitstring_param, LSplugin_get_bitstring_param 132 }; 133 134 static LE_STATUS scrub_dh_generator_data(LSC_key_generator_t *op) 135 { 136 if (op == NULL || op->lsc_data == NULL) 137 return LE_STS_SUCCESS; 138 139 struct ltc_dh_generator_st *g = op->lsc_data; 140 141 free(g->prime_bits); 142 free(g->base_bits); 143 memset(g, 0, sizeof(*g)); 144 return LE_STS_SUCCESS; 145 } 146 147 static LE_STATUS new_dh_generator_data(LSC_key_generator_t *op) 148 { 149 if (op == NULL) 150 return LE_STS_ERROR; 151 152 struct ltc_dh_generator_st **g 153 = (struct ltc_dh_generator_st **)&op->lsc_data; 154 155 if (*g == NULL && (*g = malloc(sizeof(**g))) != NULL) 156 memset(*g, 0, sizeof(**g)); 157 if (*g == NULL) 158 return LE_STS_FATAL_ERROR; 159 return LE_STS_SUCCESS; 160 } 161 162 static LE_STATUS clean_dh_generator_data(LSC_key_generator_t *op) 163 { 164 LE_STATUS sts; 165 166 if (op == NULL || op->lsc_data == NULL) 167 return LE_STS_SUCCESS; 168 if (T(sts = scrub_dh_generator_data(op))) { 169 free(op->lsc_data); 170 op->lsc_data = NULL; 171 } 172 return sts; 173 } 174 175 static LE_STATUS set_dh_generator(LSC_key_t *key, LSC_key_generator_t *op) 176 { 177 struct ltc_dh_key_st *k = key->lsc_data; 178 179 k->generator = op; 180 return LE_STS_SUCCESS; 181 } 182 183 static LE_STATUS set_generator_dh(LSC_key_generator_t *op, LSC_key_t *key) 184 { 185 LE_STATUS sts; 186 187 if (LE_status_is_OK(sts = scrub_dh_generator_data(op))) { 188 struct ltc_dh_generator_st *g = op->lsc_data; 189 190 g->key = key; 191 } 192 return sts; 193 } 194 195 static LE_STATUS get_generator_dh(LSC_key_generator_t *op, LSC_key_t **key) 196 { 197 struct ltc_dh_generator_st *g = op->lsc_data; 198 199 *key = g->key; 200 return LE_STS_SUCCESS; 201 } 202 203 static LE_STATUS get_generation_param_data(LSC_key_generator_t *op, void **data) 204 { 205 *data = op->lsc_data; 206 return LE_STS_SUCCESS; 207 } 208 209 static LE_STATUS 210 get_settable_generation_desc(LSC_key_generator_t *op, 211 const LSC_param_desc_t **param_desc) 212 { 213 static const LSC_param_desc_t pd[] = { 214 DH_P_groupsize(gen), 215 DH_P_domain_params(gen), 216 { NULL, } 217 }; 218 *param_desc = pd; 219 return LE_STS_SUCCESS; 220 } 221 222 static LE_STATUS generate_dh_data(LSC_key_generator_t *op) 223 { 224 int err; /* libtomcrypt status codes */ 225 LE_STATUS sts; 226 227 struct ltc_dh_generator_st *g = op->lsc_data; 228 struct ltc_dh_key_st *k = NULL; 229 230 sts = scrub_dh_data(g->key); 231 if (T(sts)) 232 k = g->key->lsc_data; 233 234 if (k != NULL) { 235 err = CRYPT_OK; 236 if (g->groupsize_set) 237 /* Groupsize expected */ 238 err = dh_set_pg_groupsize(g->groupsize, &k->key); 239 else if (err == CRYPT_OK 240 && g->prime_bits != NULL 241 && g->base_bits != NULL) 242 /* P & G expected */ 243 err = dh_set_pg(g->prime_bits, 244 (unsigned long)(g->prime_bits_len + 7) / 8, 245 g->base_bits, 246 (unsigned long)(g->base_bits_len + 7) / 8, 247 &k->key); 248 else 249 return LE_STS_ERROR; 250 251 if (err == CRYPT_OK) { 252 /* 253 * TODO: Ideally, we should have a randomness operation given by 254 * the application. For the time being, we use fortuna locally. 255 */ 256 prng_state prng; 257 int wprng; 258 259 if ((wprng = find_prng("fortuna")) == -1) 260 wprng = register_prng(&fortuna_desc); 261 if (wprng >= 0) 262 err = rng_make_prng(128, wprng, &prng, NULL); 263 if (err == CRYPT_OK) 264 err = dh_generate_key(&prng, wprng, &k->key); 265 fortuna_done(&prng); 266 } 267 sts = (err == CRYPT_OK) ? LE_STS_SUCCESS : LE_STS_ERROR; 268 } 269 270 return sts; 271 } 272 273 /* local DH generator descriptor, used in |ltc_dh_desc| below */ 274 static LSplugin_key_generator_desc_t ltc_dh_generator_desc = { 275 NULL, NULL, NULL, NULL, /* lsp_id, lsp_priv_desc, lsp_key_id */ 276 new_dh_generator_data, clean_dh_generator_data, 277 set_dh_generator, set_generator_dh, get_generator_dh, 278 (int[]){ LSC_NR_get_settable_key_generation_param_desc, 279 LSC_NR_set_key_generation_param, LSC_NR_generate_key, 0 }, 280 get_generation_param_data, 281 NULL, /* No gettable */ 282 get_settable_generation_desc, /* settable */ 283 generate_dh_data 284 }; 285 286 /* Key constructor operation */ 287 288 struct ltc_dh_constructor_st { 289 LSC_key_t *key; 290 291 /* Operational parameters */ 292 293 unsigned char *prime_bits; /* Known as |p| in DH descriptions */ 294 size_t prime_bits_len; /* ... in bits */ 295 296 unsigned char *base_bits; /* Known as |g| in DH descriptions */ 297 size_t base_bits_len; /* ... in bits */ 298 299 unsigned char *privkey_bits; 300 size_t privkey_bits_len; /* ... in bits */ 301 302 unsigned char *pubkey_bits; 303 size_t pubkey_bits_len; /* ... in bits */ 304 }; 305 306 static LSplugin_param_functions_t dh_constr_prime_param_fns = { 307 offsetof(struct ltc_dh_constructor_st, prime_bits), 308 offsetof(struct ltc_dh_constructor_st, prime_bits_len), 309 0, false, 310 LSplugin_set_bitstring_param, LSplugin_get_bitstring_param 311 }; 312 static LSplugin_param_functions_t dh_constr_base_param_fns = { 313 offsetof(struct ltc_dh_constructor_st, base_bits), 314 offsetof(struct ltc_dh_constructor_st, base_bits_len), 315 0, false, 316 LSplugin_set_bitstring_param, LSplugin_get_bitstring_param 317 }; 318 static LSplugin_param_functions_t dh_constr_pubkey_param_fns = { 319 offsetof(struct ltc_dh_constructor_st, pubkey_bits), 320 offsetof(struct ltc_dh_constructor_st, pubkey_bits_len), 321 0, false, 322 LSplugin_set_bitstring_param, LSplugin_get_bitstring_param 323 }; 324 static LSplugin_param_functions_t dh_constr_privkey_param_fns = { 325 offsetof(struct ltc_dh_constructor_st, privkey_bits), 326 offsetof(struct ltc_dh_constructor_st, privkey_bits_len), 327 0, false, 328 LSplugin_set_bitstring_param, LSplugin_get_bitstring_param 329 }; 330 331 static LE_STATUS scrub_dh_constructor_data(LSC_key_constructor_t *op) 332 { 333 if (op == NULL || op->lsc_data == NULL) 334 return LE_STS_SUCCESS; 335 336 struct ltc_dh_constructor_st *g = op->lsc_data; 337 338 free(g->prime_bits); 339 free(g->base_bits); 340 free(g->privkey_bits); 341 free(g->pubkey_bits); 342 memset(g, 0, sizeof(*g)); 343 return LE_STS_SUCCESS; 344 } 345 346 static LE_STATUS new_dh_constructor_data(LSC_key_constructor_t *op) 347 { 348 LE_STATUS sts; 349 350 if (op == NULL) 351 return LE_STS_ERROR; 352 353 struct ltc_dh_constructor_st **c 354 = (struct ltc_dh_constructor_st **)&op->lsc_data; 355 356 if (*c == NULL && (*c = malloc(sizeof(**c))) != NULL) 357 memset(*c, 0, sizeof(**c)); 358 if (*c == NULL) 359 return LE_STS_FATAL_ERROR; 360 return LE_STS_SUCCESS; 361 } 362 363 static LE_STATUS clean_dh_constructor_data(LSC_key_constructor_t *op) 364 { 365 LE_STATUS sts; 366 367 if (op == NULL || op->lsc_data == NULL) 368 return LE_STS_SUCCESS; 369 if (T(sts = scrub_dh_constructor_data(op))) { 370 free(op->lsc_data); 371 op->lsc_data = NULL; 372 } 373 return sts; 374 } 375 376 static LE_STATUS set_dh_constructor(LSC_key_t *key, LSC_key_constructor_t *op) 377 { 378 struct ltc_dh_key_st *k = key->lsc_data; 379 380 k->constructor = op; 381 return LE_STS_SUCCESS; 382 } 383 384 static LE_STATUS set_constructor_dh(LSC_key_constructor_t *op, LSC_key_t *key) 385 { 386 LE_STATUS sts; 387 388 if (LE_status_is_OK(sts = new_dh_constructor_data(op))) { 389 struct ltc_dh_constructor_st *c = op->lsc_data; 390 391 c->key = key; 392 } 393 return sts; 394 } 395 396 static LE_STATUS get_constructor_dh(LSC_key_constructor_t *op, LSC_key_t **key) 397 { 398 struct ltc_dh_constructor_st *c = op->lsc_data; 399 400 *key = c->key; 401 return LE_STS_SUCCESS; 402 } 403 404 static LE_STATUS get_construction_param_data(LSC_key_constructor_t *op, void **data) 405 { 406 *data = op->lsc_data; 407 return LE_STS_SUCCESS; 408 } 409 410 static LE_STATUS 411 get_settable_construction_desc(LSC_key_constructor_t *op, 412 const LSC_param_desc_t **param_desc) 413 { 414 static const LSC_param_desc_t pd[] = { 415 DH_P_domain_params(constr), 416 DH_P_key(constr), 417 { NULL, } 418 }; 419 *param_desc = pd; 420 return LE_STS_SUCCESS; 421 } 422 423 LE_STATUS construct_dh_data(LSC_key_constructor_t *op) 424 { 425 int err; /* libtomcrypt status codes */ 426 LE_STATUS sts; 427 struct ltc_dh_constructor_st *g = op->lsc_data; 428 429 if (T(sts = scrub_dh_data(g->key))) { 430 struct ltc_dh_key_st *k = g->key->lsc_data; 431 432 if (g->prime_bits != NULL && g->base_bits != NULL) 433 err = dh_set_pg(g->prime_bits, 434 (unsigned long)(g->prime_bits_len + 7) / 8, 435 g->base_bits, 436 (unsigned long)(g->base_bits_len + 7) / 8, 437 &k->key); 438 if (err == CRYPT_OK && g->privkey_bits != NULL) 439 err = dh_set_key(g->privkey_bits, 440 (unsigned long)(g->privkey_bits_len + 7) / 8, 441 PK_PRIVATE, &k->key); 442 else if (err == CRYPT_OK && g->pubkey_bits != NULL) 443 err = dh_set_key(g->pubkey_bits, 444 (unsigned long)(g->pubkey_bits_len + 7) / 8, 445 PK_PUBLIC, &k->key); 446 sts = (err == CRYPT_OK) ? LE_STS_SUCCESS : LE_STS_ERROR; 447 } 448 449 return sts; 450 } 451 452 /* local DH constructor descriptor, used in |ltc_dh_desc| below */ 453 static LSplugin_key_constructor_desc_t ltc_dh_constructor_desc = { 454 NULL, NULL, NULL, NULL, /* lsp_docstring, lsp_id, lsp_priv_desc, lsp_key_id */ 455 new_dh_constructor_data, clean_dh_constructor_data, 456 set_dh_constructor, set_constructor_dh, get_constructor_dh, 457 (int[]){ LSC_NR_get_settable_key_construction_param_desc, 458 LSC_NR_set_key_construction_param, LSC_NR_construct_key, 0 }, 459 get_construction_param_data, 460 NULL, /* No gettable */ 461 get_settable_construction_desc, /* settable */ 462 construct_dh_data 463 }; 464 465 /* Key extractor operation */ 466 467 static LSplugin_param_functions_t prime_param_fns = { 468 offsetof(dh_key, prime), 0, 0, false, NULL, LSplugin_get_bitstring_param 469 }; 470 static LSplugin_param_functions_t base_param_fns = { 471 offsetof(dh_key, base), 0, 0, false, NULL, LSplugin_get_bitstring_param 472 }; 473 static LSplugin_param_functions_t privkey_param_fns = { 474 offsetof(dh_key, x), 0, 0, false, NULL, LSplugin_get_bitstring_param 475 }; 476 static LSplugin_param_functions_t pubkey_param_fns = { 477 offsetof(dh_key, y), 0, 0, false, NULL, LSplugin_get_bitstring_param 478 }; 479 static LE_STATUS 480 get_gettable_extraction_desc(LSC_key_extractor_t *op, 481 const LSC_param_desc_t **param_desc) 482 { 483 static const LSC_param_desc_t pd[] = { 484 { "prime", DH_I_prime, 485 { LSC_DT_unsigned_integer, { { 0, 0 }, }, 486 .d_auxilliary.d_integer_desc = { 487 LSC_DTi_elem_is_bit, 488 LSC_DTi_mse_first_order 489 }, }, 490 .p_private = &prime_param_fns }, 491 { "base", DH_I_base, 492 { LSC_DT_unsigned_integer, { { 0, 0 }, }, 493 .d_auxilliary.d_integer_desc = { 494 LSC_DTi_elem_is_bit, 495 LSC_DTi_mse_first_order 496 }, }, 497 .p_private = &base_param_fns }, 498 { "privkey", 5, 499 { LSC_DT_unsigned_integer, { { 0, 0 }, }, 500 .d_auxilliary.d_integer_desc = { 501 LSC_DTi_elem_is_bit, 502 LSC_DTi_mse_first_order 503 }, }, 504 .p_private = &privkey_param_fns }, 505 { "pubkey", 6, 506 { LSC_DT_unsigned_integer, { { 0, 0 }, }, 507 .d_auxilliary.d_integer_desc = { 508 LSC_DTi_elem_is_bit, 509 LSC_DTi_mse_first_order 510 }, }, 511 .p_private = &pubkey_param_fns }, 512 { NULL, } 513 }; 514 *param_desc = pd; 515 return LE_STS_SUCCESS; 516 } 517 518 static LE_STATUS set_dh_extractor(LSC_key_t *key, LSC_key_extractor_t *op) 519 { 520 struct ltc_dh_key_st *k = key->lsc_data; 521 522 k->extractor = op; 523 return LE_STS_SUCCESS; 524 } 525 526 static LE_STATUS set_extractor_dh(LSC_key_extractor_t *op, LSC_key_t *key) 527 { 528 op->lsc_data = key; 529 return LE_STS_SUCCESS; 530 } 531 532 static LE_STATUS get_extractor_dh(LSC_key_extractor_t *op, LSC_key_t **key) 533 { 534 *key = op->lsc_data; 535 return LE_STS_SUCCESS; 536 } 537 538 static LE_STATUS get_extractor_param_data(LSC_key_extractor_t *op, void **data) 539 { 540 *data = op->lsc_data; 541 return LE_STS_SUCCESS; 542 } 543 544 /* local DH extractor descriptor, used in |ltc_dh_desc| below */ 545 static LSplugin_key_extractor_desc_t ltc_dh_extractor_desc = { 546 NULL, NULL, NULL, NULL, /* lsp_docstring, lsp_id, lsp_priv_desc, lsp_key_id */ 547 NULL, NULL, 548 set_dh_extractor, set_extractor_dh, get_extractor_dh, 549 (int[]){ LSC_NR_get_gettable_key_extraction_param_desc, 550 LSC_NR_get_key_extraction_param, 0}, 551 get_extractor_param_data, /* The data param functions act upon */ 552 get_gettable_extraction_desc, /* gettable */ 553 NULL /* No settable */ 554 }; 555 556 /* Key derivator operation */ 557 558 struct ltc_dh_derivator_st { 559 LSC_key_t *key; 560 /* Operational parameters */ 561 void *p; size_t p_len; 562 void *g; size_t g_len; 563 }; 564 565 static LE_STATUS scrub_dh_derivator_data(LSC_derivator_t *op) 566 { 567 if (op == NULL || op->lsc_data == NULL) 568 return LE_STS_SUCCESS; 569 570 struct ltc_dh_derivator_st *d = op->lsc_data; 571 572 free(d->p); 573 free(d->g); 574 memset(d, 0, sizeof(*d)); 575 return LE_STS_SUCCESS; 576 } 577 578 static LE_STATUS new_dh_derivator_data(LSC_derivator_t *op) 579 { 580 if (op == NULL) 581 return LE_STS_ERROR; 582 583 LE_STATUS sts; 584 585 struct ltc_dh_derivator_st **d 586 = (struct ltc_dh_derivator_st **)&op->lsc_data; 587 588 if (*d == NULL && (*d = malloc(sizeof(**d))) != NULL) 589 memset(*d, 0, sizeof(**d)); 590 if (*d == NULL) 591 return LE_STS_FATAL_ERROR; 592 return LE_STS_SUCCESS; 593 } 594 595 static LE_STATUS clean_dh_derivator_data(LSC_derivator_t *op) 596 { 597 LE_STATUS sts; 598 599 if (op == NULL || op->lsc_data == NULL) 600 return LE_STS_SUCCESS; 601 if (T(sts = scrub_dh_derivator_data(op))) { 602 free(op->lsc_data); 603 op->lsc_data = NULL; 604 } 605 return sts; 606 } 607 608 static LE_STATUS set_dh_derivator(LSC_key_t *key, LSC_derivator_t *op) 609 { 610 struct ltc_dh_key_st *k = key->lsc_data; 611 612 k->derivator = op; 613 return LE_STS_SUCCESS; 614 } 615 616 static LE_STATUS set_derivator_dh(LSC_derivator_t *op, LSC_key_t *key) 617 { 618 LE_STATUS sts; 619 620 if (LE_status_is_OK(sts = new_dh_derivator_data(op))) { 621 struct ltc_dh_derivator_st *d = op->lsc_data; 622 623 d->key = key; 624 } 625 return sts; 626 } 627 628 static LE_STATUS get_derivator_dh(LSC_derivator_t *op, LSC_key_t **key) 629 { 630 struct ltc_dh_derivator_st *d = op->lsc_data; 631 632 *key = d->key; 633 return LE_STS_SUCCESS; 634 } 635 636 static LE_STATUS perform_dh_derivation_once(LSC_derivator_t *op, 637 LSC_key_t *peer, 638 unsigned char *out, 639 size_t outsize, 640 size_t *outlen) 641 { 642 LE_STATUS sts = LE_STS_ERROR; 643 struct ltc_dh_derivator_st *drv = op->lsc_data; 644 LSC_key_t *key = drv->key; 645 struct ltc_dh_key_st *k = key->lsc_data; 646 LSC_key_extractor_t *e = NULL; 647 const LSC_param_desc_t *desc, *pd; 648 int prime_id = -1, base_id = -1, pubkey_id = -1; 649 650 if (!T(sts = LSC_get_key_extractor(peer, &e)) 651 || !T(sts = LSC_get_gettable_key_extraction_param_desc(e, &desc))) 652 return sts; 653 654 for (pd = desc; pd->p_name != NULL; pd++) { 655 if (strcmp("prime", pd->p_name) == 0) 656 prime_id = pd->p_id; 657 else if (strcmp("base", pd->p_name) == 0) 658 base_id = pd->p_id; 659 else if (strcmp("pubkey", pd->p_name) == 0) 660 pubkey_id = pd->p_id; 661 } 662 663 if (prime_id == -1 || base_id == -1 || pubkey_id == -1) 664 return LE_STS_ERROR; 665 666 size_t prime_size1 = 0; 667 unsigned char prime_buffer1[1]; 668 LSC_get_key_extraction_param(e, prime_id, (LSC_param_t []){ 669 { prime_buffer1, 670 sizeof(prime_buffer1), 671 &prime_size1 }, 672 { NULL, 0, NULL } 673 }); 674 if (prime_size1 == 0) 675 return LE_STS_ERROR; 676 size_t base_size1 = 0; 677 unsigned char base_buffer1[1]; 678 LSC_get_key_extraction_param(e, base_id, (LSC_param_t []){ 679 { base_buffer1, 680 sizeof(base_buffer1), 681 &base_size1 }, 682 { NULL, 0, NULL } 683 }); 684 if (base_size1 == 0) 685 return LE_STS_ERROR; 686 size_t pubkey_size1 = 0; 687 unsigned char pubkey_buffer1[1]; 688 LSC_get_key_extraction_param(e, pubkey_id, (LSC_param_t []){ 689 { pubkey_buffer1, 690 sizeof(pubkey_buffer1), 691 &pubkey_size1 }, 692 { NULL, 0, NULL } 693 }); 694 if (pubkey_size1 == 0) 695 return LE_STS_ERROR; 696 697 size_t prime_size2 = 0; 698 unsigned char prime_buffer2[prime_size1]; 699 if (!T(sts = LSC_get_key_extraction_param(e, prime_id, 700 (LSC_param_t []){ 701 { prime_buffer2, 702 sizeof(prime_buffer2), 703 &prime_size2 }, 704 { NULL, 0, NULL } 705 }))) 706 return LE_STS_ERROR; 707 size_t base_size2 = 0; 708 unsigned char base_buffer2[base_size1]; 709 if (!T(sts = LSC_get_key_extraction_param(e, base_id, 710 (LSC_param_t []){ 711 { base_buffer2, 712 sizeof(base_buffer2), 713 &base_size2 }, 714 { NULL, 0, NULL } 715 }))) 716 return LE_STS_ERROR; 717 size_t pubkey_size2 = 0; 718 unsigned char pubkey_buffer2[pubkey_size1]; 719 if (!T(sts = LSC_get_key_extraction_param(e, pubkey_id, 720 (LSC_param_t []){ 721 { pubkey_buffer2, 722 sizeof(pubkey_buffer2), 723 &pubkey_size2 }, 724 { NULL, 0, NULL } 725 }))) 726 return LE_STS_ERROR; 727 728 dh_key peerkey; 729 if (dh_set_pg(prime_buffer2, (unsigned long)prime_size2, 730 base_buffer2, (unsigned long)base_size2, 731 &peerkey) != CRYPT_OK 732 || dh_set_key(pubkey_buffer2, (unsigned long)pubkey_size2, 733 PK_PUBLIC, &peerkey)) 734 return LE_STS_ERROR; 735 736 unsigned long _outlen = (unsigned long)outsize; 737 int err = dh_shared_secret(&k->key, &peerkey, out, &_outlen); 738 739 dh_free(&peerkey); 740 741 sts = (err == CRYPT_OK) ? LE_STS_SUCCESS : LE_STS_ERROR; 742 if (T(sts)) 743 *outlen = _outlen; 744 745 return sts; 746 } 747 748 /* local DH derivator descriptor, used in |ltc_dh_desc| below */ 749 static LSplugin_derivator_desc_t ltc_dh_derivator_desc = { 750 NULL, NULL, NULL, NULL, /* lsp_docstring, lsp_id, lsp_priv_desc, lsp_key_id */ 751 new_dh_derivator_data, clean_dh_derivator_data, 752 set_dh_derivator, set_derivator_dh, get_derivator_dh, 753 (int[]){ LSC_NR_perform_derivation_once, 0 }, 754 NULL, NULL, NULL, 755 perform_dh_derivation_once, 756 }; 757 758 /* Main object functions */ 759 760 static LE_STATUS scrub_dh_data(LSC_key_t *key) 761 { 762 if (key == NULL || key->lsc_data == NULL) 763 return LE_STS_SUCCESS; 764 765 struct ltc_dh_key_st *k = key->lsc_data; 766 767 dh_free(&k->key); 768 /* DO NOTE that we aren't scrubbing the cached primitive operations */ 769 return LE_STS_SUCCESS; 770 } 771 772 static LE_STATUS new_dh_data(LSC_key_t *key, const void *unused) 773 { 774 LE_STATUS sts; 775 776 if (key == NULL) 777 return LE_STS_ERROR; 778 779 struct ltc_dh_key_st **k = (struct ltc_dh_key_st **)&key->lsc_data; 780 781 if (*k == NULL && (*k = malloc(sizeof(**k))) != NULL) 782 memset(*k, 0, sizeof(**k)); 783 if (*k == NULL) 784 return LE_STS_FATAL_ERROR; 785 return LE_STS_SUCCESS; 786 } 787 788 static LE_STATUS clean_dh_data(LSC_key_t *key) 789 { 790 LE_STATUS sts; 791 792 if (key == NULL || key->lsc_data == NULL) 793 return LE_STS_SUCCESS; 794 if (T(sts = scrub_dh_data(key))) { 795 struct ltc_dh_key_st *k = key->lsc_data; 796 /* 797 * The generator, constructor, extractor and derivator are cached, 798 * so they don't provide a destroy function in the operation object, 799 * which means that the LSC_free_key_{operation}() calls end up doing 800 * nothing. Therefore, we must destroy them now, using their destroy 801 * functions (which do exist) directly. 802 */ 803 LSplugin_destroy_key_generator(k->generator); 804 LSplugin_destroy_key_constructor(k->constructor); 805 LSplugin_destroy_key_extractor(k->extractor); 806 LSplugin_destroy_derivator(k->derivator); 807 free(k); 808 key->lsc_data = NULL; 809 } 810 return sts; 811 } 812 813 static LE_STATUS get_dh_key_size(LSC_key_t *key, size_t *keysize) 814 { 815 LE_STATUS sts; 816 817 if (key == NULL || keysize == NULL) 818 return LE_STS_ERROR; 819 820 struct ltc_dh_key_st *k = key->lsc_data; 821 *keysize = dh_get_groupsize(&k->key) * 8; 822 return LE_STS_SUCCESS; 823 } 824 825 /* Global DH key descriptor, used by ltc-key.c */ 826 const LSplugin_key_desc_t ltc_dh_desc = { 827 NULL, "dh", NULL, /* lsp_docstring, lsp_id, libtomcrypt desc */ 828 new_dh_data, clean_dh_data, 829 (int[]){ LSC_NR_get_key_size, LSC_NR_get_key_generator, 830 LSC_NR_get_key_constructor, LSC_NR_get_key_extractor, 831 LSC_NR_get_associated_derivator, 0 }, 832 get_dh_key_size, 833 <c_dh_generator_desc, 834 <c_dh_constructor_desc, 835 <c_dh_extractor_desc, 836 NULL, /* No encryptor */ 837 NULL, /* No decryptor */ 838 NULL, /* No signed */ 839 NULL, /* No verifier */ 840 <c_dh_derivator_desc, 841 };