/ plugin1.c
plugin1.c
1 #include <assert.h> 2 #include <string.h> 3 #include <lscore/plugin.h> 4 #include <lscore/param.h> 5 #include <lscrypto/key.h> 6 #include <lscrypto/encrypt.h> 7 #include "vigenere.h" 8 9 /* Forward declarations, used to see if we can make shortcuts */ 10 static LE_STATUS vkey_dispatch(LSC_key_t *key, int num, ...); 11 12 /* 13 * vencdec_dispatch is a bit complex, 'cause it acts both as a dispatch 14 * function for a key associated encryptor/decryptor, as well as a dispatch 15 * function for an independent encryptor/decryptor, and must be able to handle 16 * both situations. What that really comes down to is access to the key, and 17 * whether the caller can replace the key, i.e. whether or not it's acceptable 18 * to call the opeation LSC_NR_use_operation_object. 19 * 20 * With more complex algorithms that also take some optional parameters (for 21 * example, an IV), calls for such parameters would most likely be acceptable 22 * by the same rules as LSC_NR_use_operation_object. Also, the map of possible 23 * states becomes a bit more complex. Luckily, Vigenere doesn't have any 24 * optional parameters of that sort, so no need to care here. 25 * 26 * |op->lsc_data|, when non-NULL, always points at an LSC_key_t (let's 27 * call it |key| in this comment). |op->lsc_data|, when non-NULL, always 28 * points at a LSC_{enc,dec}ryptor_t, which may or may not be a key associated 29 * operation. 30 * 31 * We have the following possible states: 32 * 33 * | Y | Y | No key given yet, LSC_NR_use_operation_object is acceptable 34 * | | | 35 * | Y | N | Key given, |key->lsc_data| is a struct vigenere_key_st. 36 * | | | LSC_NR_use_operation_object is acceptable 37 * | N | Y | Key given, |op->lsc_dispatch_data| is a LSC_{enc,dec}ryptor_t 38 * | | | that all calls should be redirected to. 39 * | | | LSC_NR_use_operation_object is acceptable 40 * | N | N | Key given, |key->lsc_data| is a struct vigenere_key_st. 41 * | | | LSC_NR_use_operation_object is NOT acceptable. 42 * | | | (this is the dispatch function of an associated {enc,dec}ryptor) 43 * ^ ^ 44 * | | 45 * | `-- |op->lsc_data| == NULL 46 * `------ |op->lsc_dispatch_data| == NULL 47 */ 48 49 static LE_STATUS venc_dispatch(LSC_encryptor_t *enc, int num, ...) 50 { 51 assert(enc != NULL); 52 53 LSC_key_t *key = enc->lsc_data; 54 LSC_encryptor_t *nextenc = (LSC_encryptor_t *)enc->lsc_dispatch_data; 55 LE_STATUS sts = LE_STS_WARNING; /* Assume unsupported */ 56 int dispatch_cmds[] = { LSC_ENCRYPTOR_TYPE_BASE_COMMANDS(), 57 LSC_NR_get_encryptor_unit_size, 58 LSC_NR_get_encryptor_input_size, 59 LSC_NR_get_encryptor_output_size, 60 LSC_NR_start_encryption, 61 LSC_NR_perform_encryption, 62 LSC_NR_finalize_encryption, 63 LSC_NR_stop_encryption, 0 }; 64 va_list ap; 65 66 va_start(ap, num); 67 switch (num) { 68 LSC_ENCRYPTOR_TYPE_BASE_DISPATCHES("vigenere", enc, sts, ap, 69 dispatch_cmds); 70 case LSC_NR_can_encryptor_use_key: 71 case LSC_NR_use_encryptor_key: 72 if (key == NULL || nextenc == NULL) { 73 LSC_key_t *obj = va_arg(ap, LSC_key_t *); 74 75 _Bool can_enc = false; 76 /* 77 * If we recognise it as ours, it's a done deal. 78 * Otherwise, we need to look deeper */ 79 if (obj->lsc_dispatch == vkey_dispatch) { 80 can_enc = true; 81 } else { 82 const char *obj_class; 83 const char *obj_id; 84 sts = LSC_get_key_class(obj, &obj_class); 85 if (LE_status_is_OK(sts)) 86 sts = LSC_get_key_identity(obj, &obj_id); 87 if (!LE_status_is_OK(sts)) 88 break; 89 90 if (strcmp(obj_class, LSC_OBJECT_CLASS_PREFIX) == 0 91 && strcmp(obj_id, "vigenere") == 0) { 92 /* Can the key be used for encryption / decryption? */ 93 sts = LSC_can_key_do(obj, LSC_NR_get_associated_encryptor, &can_enc); 94 if (!LE_status_is_OK(sts)) 95 break; 96 } 97 } 98 99 switch (num) { 100 case LSC_NR_can_encryptor_use_key: 101 { 102 _Bool *yes = va_arg(ap, _Bool *); 103 *yes = can_enc; 104 } 105 sts = LE_STS_SUCCESS; 106 break; 107 case LSC_NR_use_encryptor_key: 108 if (can_enc) { 109 /* Clean up the last key or the last associated {enc,dec}ryptor */ 110 if (key != NULL) { 111 key->lsc_destroy(key); 112 free(key); 113 key = NULL; 114 } else if (nextenc != NULL) { 115 nextenc->lsc_destroy(nextenc); 116 free(nextenc); 117 nextenc = NULL; 118 } 119 120 /* If we recognise it as ours, it's a cut deal */ 121 if (obj->lsc_dispatch == vkey_dispatch) { 122 key = obj; 123 } else { 124 sts = LSC_get_associated_encryptor(obj, &nextenc); 125 if (!LE_status_is_OK(sts)) 126 break; 127 } 128 129 /* At this point, we really should have either a key or an encdec */ 130 assert(key == NULL || nextenc == NULL); 131 132 if (key != NULL || nextenc != NULL) { 133 enc->lsc_dispatch_data = nextenc; 134 enc->lsc_data = key; 135 sts = LE_STS_SUCCESS; 136 } else { 137 sts = LE_STS_ERROR; 138 } 139 } 140 break; 141 } 142 } 143 break; 144 case LSC_NR_get_expected_encryptor_key_identity: 145 { 146 const char **obj_id = va_arg(ap, const char **); 147 *obj_id = "vigenere"; 148 } 149 sts = LE_STS_SUCCESS; 150 break; 151 case LSC_NR_get_encryptor_unit_size: 152 { 153 size_t *size = va_arg(ap, size_t *); 154 *size = 1; 155 } 156 sts = LE_STS_SUCCESS; 157 break; 158 case LSC_NR_get_encryptor_input_size: 159 { 160 size_t *size = va_arg(ap, size_t *); 161 *size = 0; 162 } 163 sts = LE_STS_SUCCESS; 164 break; 165 case LSC_NR_get_encryptor_output_size: 166 { 167 size_t *size = va_arg(ap, size_t *); 168 *size = 0; 169 } 170 sts = LE_STS_SUCCESS; 171 break; 172 case LSC_NR_start_encryption: 173 /* Not much to do here */ 174 if (key == NULL && nextenc == NULL) 175 sts = LE_STS_ERROR; 176 else 177 sts = LE_STS_SUCCESS; 178 break; 179 case LSC_NR_perform_encryption: 180 if (key == NULL && nextenc == NULL) { 181 sts = LE_STS_ERROR; 182 } else { 183 const unsigned char *in = va_arg(ap, const unsigned char *); 184 size_t inlen = va_arg(ap, size_t); 185 unsigned char *out = va_arg(ap, unsigned char *); 186 size_t outsize = va_arg(ap, size_t); 187 size_t *outlen = va_arg(ap, size_t *); 188 189 if (key != NULL) { 190 int res = vigenere_encrypt(in, inlen, out, outsize, key->lsc_data); 191 *outlen = inlen; 192 sts = res ? LE_STS_SUCCESS : LE_STS_ERROR; 193 } else { 194 sts = nextenc->lsc_dispatch(nextenc, LSC_NR_perform_encryption, 195 in, inlen, out, outsize, outlen); 196 } 197 } 198 break; 199 case LSC_NR_finalize_encryption: 200 if (key == NULL && nextenc == NULL) { 201 sts = LE_STS_ERROR; 202 } else { 203 /* Not much to do here, but we still must fill in |*outlen| */ 204 unsigned char *out = va_arg(ap, unsigned char *); 205 size_t outsize = va_arg(ap, size_t); 206 size_t *outlen = va_arg(ap, size_t *); 207 208 *outlen = 0; 209 sts = LE_STS_SUCCESS; 210 } 211 break; 212 case LSC_NR_stop_encryption: 213 /* Not much to do here */ 214 if (key == NULL && nextenc == NULL) 215 sts = LE_STS_ERROR; 216 else 217 sts = LE_STS_SUCCESS; 218 break; 219 }; 220 va_end(ap); 221 222 return sts; 223 } 224 225 static LE_STATUS venc_destroy(LSC_encryptor_t *enc) 226 { 227 return LE_STS_WARNING; 228 } 229 230 static LE_STATUS vdec_dispatch(LSC_decryptor_t *dec, int num, ...) 231 { 232 assert(dec != NULL); 233 234 LSC_key_t *key = dec->lsc_data; 235 LSC_decryptor_t *nextdec = (LSC_decryptor_t *)dec->lsc_dispatch_data; 236 LE_STATUS sts = LE_STS_WARNING; /* Assume unsupported */ 237 int dispatch_cmds[] = { LSC_DECRYPTOR_TYPE_BASE_COMMANDS(), 238 LSC_NR_get_decryptor_unit_size, 239 LSC_NR_get_decryptor_input_size, 240 LSC_NR_get_decryptor_output_size, 241 LSC_NR_start_decryption, 242 LSC_NR_perform_decryption, 243 LSC_NR_finalize_decryption, 244 LSC_NR_stop_decryption, 0 }; 245 va_list ap; 246 247 va_start(ap, num); 248 switch (num) { 249 LSC_DECRYPTOR_TYPE_BASE_DISPATCHES("vigenere", dec, sts, ap, dispatch_cmds); 250 case LSC_NR_can_decryptor_use_key: 251 case LSC_NR_use_decryptor_key: 252 if (key == NULL || nextdec == NULL) { 253 LSC_key_t *obj = va_arg(ap, LSC_key_t *); 254 255 _Bool can_encdec = false; 256 /* 257 * If we recognise it as ours, it's a done deal. 258 * Otherwise, we need to look deeper */ 259 if (obj->lsc_dispatch == vkey_dispatch) { 260 can_encdec = true; 261 } else { 262 const char *obj_class; 263 const char *obj_id; 264 sts = LSC_get_key_class(obj, &obj_class); 265 if (LE_status_is_OK(sts)) 266 sts = LSC_get_key_identity(obj, &obj_id); 267 if (!LE_status_is_OK(sts)) 268 break; 269 270 if (strcmp(obj_class, LSC_OBJECT_CLASS_PREFIX) == 0 271 && strcmp(obj_id, "vigenere") == 0) { 272 /* Can the key be used for decryption? */ 273 sts = LSC_can_key_do(obj, LSC_NR_get_associated_decryptor, &can_encdec); 274 if (!LE_status_is_OK(sts)) 275 break; 276 } 277 } 278 279 switch (num) { 280 case LSC_NR_can_decryptor_use_key: 281 { 282 _Bool *yes = va_arg(ap, _Bool *); 283 *yes = can_encdec; 284 } 285 sts = LE_STS_SUCCESS; 286 break; 287 case LSC_NR_use_decryptor_key: 288 if (can_encdec) { 289 /* Clean up the last key or the last associated {enc,dec}ryptor */ 290 if (key != NULL) { 291 key->lsc_destroy(key); 292 free(key); 293 key = NULL; 294 } else if (nextdec != NULL) { 295 nextdec->lsc_destroy(nextdec); 296 free(nextdec); 297 nextdec = NULL; 298 } 299 300 /* If we recognise it as ours, it's a cut deal */ 301 if (obj->lsc_dispatch == vkey_dispatch) { 302 key = obj; 303 } else { 304 sts = LSC_get_associated_decryptor(obj, (LSC_decryptor_t **)&nextdec); 305 if (!LE_status_is_OK(sts)) 306 break; 307 } 308 309 /* At this point, we really should have either a key or an nextdec */ 310 assert(key == NULL || nextdec == NULL); 311 312 if (key != NULL || nextdec != NULL) { 313 dec->lsc_dispatch_data = nextdec; 314 dec->lsc_data = key; 315 sts = LE_STS_SUCCESS; 316 } else { 317 sts = LE_STS_ERROR; 318 } 319 } 320 break; 321 } 322 } 323 break; 324 case LSC_NR_get_expected_decryptor_key_identity: 325 { 326 const char **obj_id = va_arg(ap, const char **); 327 *obj_id = "vigenere"; 328 } 329 sts = LE_STS_SUCCESS; 330 break; 331 case LSC_NR_get_decryptor_unit_size: 332 { 333 size_t *size = va_arg(ap, size_t *); 334 *size = 1; 335 } 336 sts = LE_STS_SUCCESS; 337 break; 338 case LSC_NR_get_decryptor_input_size: 339 { 340 size_t *size = va_arg(ap, size_t *); 341 *size = 0; 342 } 343 sts = LE_STS_SUCCESS; 344 break; 345 case LSC_NR_get_decryptor_output_size: 346 { 347 size_t *size = va_arg(ap, size_t *); 348 *size = 0; 349 } 350 sts = LE_STS_SUCCESS; 351 break; 352 case LSC_NR_start_decryption: 353 /* Not much to do here */ 354 if (key == NULL && nextdec == NULL) 355 sts = LE_STS_ERROR; 356 else 357 sts = LE_STS_SUCCESS; 358 break; 359 case LSC_NR_perform_decryption: 360 if (key == NULL && nextdec == NULL) { 361 sts = LE_STS_ERROR; 362 } else { 363 const unsigned char *in = va_arg(ap, const unsigned char *); 364 size_t inlen = va_arg(ap, size_t); 365 unsigned char *out = va_arg(ap, unsigned char *); 366 size_t outsize = va_arg(ap, size_t); 367 size_t *outlen = va_arg(ap, size_t *); 368 369 if (key != NULL) { 370 int res = vigenere_decrypt(in, inlen, out, outsize, key->lsc_data); 371 *outlen = inlen; 372 sts = res ? LE_STS_SUCCESS : LE_STS_ERROR; 373 } else { 374 sts = nextdec->lsc_dispatch(nextdec, LSC_NR_perform_decryption, 375 in, inlen, out, outsize, outlen); 376 } 377 } 378 break; 379 case LSC_NR_finalize_decryption: 380 if (key == NULL && nextdec == NULL) { 381 sts = LE_STS_ERROR; 382 } else { 383 /* Not much to do here, but we still must fill in |*outlen| */ 384 unsigned char *out = va_arg(ap, unsigned char *); 385 size_t outsize = va_arg(ap, size_t); 386 size_t *outlen = va_arg(ap, size_t *); 387 388 *outlen = 0; 389 sts = LE_STS_SUCCESS; 390 } 391 break; 392 case LSC_NR_stop_decryption: 393 /* Not much to do here */ 394 if (key == NULL && nextdec == NULL) 395 sts = LE_STS_ERROR; 396 else 397 sts = LE_STS_SUCCESS; 398 break; 399 }; 400 va_end(ap); 401 402 return sts; 403 } 404 405 static LE_STATUS vdec_destroy(LSC_decryptor_t *dec) 406 { 407 return LE_STS_WARNING; 408 } 409 410 const LSC_param_desc_t constructor_param_descs[] = { 411 { "key", 1, 412 { LSC_DT_bit_string, { { 8, 0, 8 } } }, 413 .p_docstring = "The key bits used for encryption / decryption" }, 414 { NULL, } 415 }; 416 417 static LE_STATUS vcon_dispatch(LSC_key_constructor_t *op, int num, ...) 418 { 419 if (op == NULL || op->lsc_data == NULL) 420 return LE_STS_ERROR; 421 422 LSC_key_t *key = op->lsc_data; 423 struct vigenere_key_st *k = key->lsc_data; 424 LE_STATUS sts; 425 va_list ap; 426 427 sts = LE_STS_WARNING; /* Assume unsupported */ 428 va_start(ap, num); 429 switch (num) { 430 LSC_KEY_CONSTRUCTOR_TYPE_DISPATCHES("vigenere", op, sts, ap, 431 (int[]){0}); 432 case LSC_NR_get_settable_key_construction_param_desc: 433 const LSC_param_desc_t **paramdesc 434 = va_arg(ap, const LSC_param_desc_t **); 435 *paramdesc = constructor_param_descs; 436 sts = LE_STS_SUCCESS; 437 break; 438 case LSC_NR_set_key_construction_param: 439 unsigned int param_num = va_arg(ap, int); 440 LSC_param_t *data = va_arg(ap, LSC_param_t *); 441 442 switch (param_num) { 443 case 1: /* key */ 444 vigenere_init(k, data->data, data->size / 8); 445 if (data->len != NULL) 446 *data->len = data->size; 447 sts = LE_STS_SUCCESS; 448 break; 449 } 450 break; 451 case LSC_NR_construct_key: 452 /* Do nothing here, as we've done it all when setting the key param */ 453 sts = LE_STS_SUCCESS; 454 break; 455 } 456 va_end(ap); 457 458 return sts; 459 } 460 461 LE_STATUS vkey_dispatch(LSC_key_t *key, int num, ...) 462 { 463 if (key == NULL) 464 return LE_STS_ERROR; 465 466 if (key->lsc_data == NULL) { 467 key->lsc_data = malloc(sizeof(struct vigenere_key_st)); 468 if (key->lsc_data == NULL) 469 return LE_STS_ERROR; 470 memset(key->lsc_data, 0, sizeof(struct vigenere_key_st)); 471 } 472 473 void *operator; 474 LE_STATUS sts; 475 va_list ap; 476 477 sts = LE_STS_WARNING; /* Assume unsupported */ 478 va_start(ap, num); 479 switch (num) { 480 LSC_KEY_TYPE_BASE_DISPATCHES("vigenere", key, sts, ap, 481 (int[]){0}); 482 case LSC_NR_get_key_size: { 483 struct vigenere_key_st *k = key->lsc_data; 484 if (k == NULL || k->key == NULL) { 485 sts = LE_STS_ERROR; 486 } else { 487 size_t *keysize = va_arg(ap, size_t *); 488 *keysize = k->keysize; 489 sts = LE_STS_SUCCESS; 490 } 491 break; 492 } 493 case LSC_NR_get_key_constructor: { 494 LSC_key_constructor_t *op = NULL; 495 sts = LSC_new_key_constructor(vcon_dispatch, NULL, NULL, &op); 496 if (LE_status_is_OK(sts)) { 497 op->lsc_data = key; 498 operator = op; 499 goto finish_operator; 500 } 501 break; 502 } 503 case LSC_NR_get_associated_encryptor: { 504 LSC_encryptor_t *op = NULL; 505 sts = LSC_new_encryptor(venc_dispatch, venc_destroy, NULL, &op); 506 if (LE_status_is_OK(sts)) { 507 op->lsc_dispatch_data = op; 508 op->lsc_data = key; 509 operator = op; 510 goto finish_operator; 511 } 512 break; 513 } 514 case LSC_NR_get_associated_decryptor: { 515 LSC_decryptor_t *op = NULL; 516 sts = LSC_new_decryptor(vdec_dispatch, vdec_destroy, NULL, &op); 517 if (LE_status_is_OK(sts)) { 518 op->lsc_dispatch_data = op; 519 op->lsc_data = key; 520 operator = op; 521 goto finish_operator; 522 } 523 break; 524 } 525 finish_operator: 526 if (LE_status_is_OK(sts)) { 527 void **op = va_arg(ap, void **); 528 *op = operator; 529 } 530 break; 531 } 532 va_end(ap); 533 534 return sts; 535 } 536 537 static LE_STATUS vkey_destroy(LSC_key_t *key) 538 { 539 vigenere_done(key->lsc_data); /* For good measure */ 540 free(key->lsc_data); 541 key->lsc_data = NULL; 542 return LE_STS_SUCCESS; 543 } 544 545 LSC_EXPORT const char LSC_plugin_docstring[] = 546 "The Vigenère plugin"; 547 548 static const char vigenere_impl_docstring[] = 549 "'vigenere' is a modern implementation of the a cipher First described \ 550 by Giovan Battista Bellaso in 1553, and was later misattributed to Blaise \ 551 de Vigenère.\n\ 552 \n\ 553 Read all about it in https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher."; 554 555 LSC_EXPORT LE_STATUS LSC_plugin_start(LSC_plugin_t *plugin) 556 { 557 LSC_env_t *env; 558 LE_STATUS sts; 559 560 if (!LE_status_is_OK(sts = LSC_get_plugin_parent_environment(plugin, &env))) 561 return sts; 562 sts = LSC_register_key_implementation(env, plugin, "vigenere", 563 vkey_dispatch, vkey_destroy, NULL, 564 vigenere_impl_docstring); 565 if (!LE_status_is_OK(sts)) 566 return sts; 567 sts = LSC_register_encryptor_implementation(env, plugin, "vigenere", 568 venc_dispatch, venc_destroy, NULL, 569 vigenere_impl_docstring); 570 if (!LE_status_is_OK(sts)) 571 return sts; 572 sts = LSC_register_decryptor_implementation(env, plugin, "vigenere", 573 vdec_dispatch, vdec_destroy, NULL, 574 vigenere_impl_docstring); 575 return sts; 576 } 577 578 LSC_EXPORT LE_STATUS LSC_plugin_stop(LSC_plugin_t *plugin) 579 { 580 LSC_env_t *env; 581 LE_STATUS sts; 582 583 if (!LE_status_is_OK(sts = LSC_get_plugin_parent_environment(plugin, &env))) 584 return sts; 585 sts = LSC_deregister_key_implementation(env, plugin, "vigenere", 586 vkey_dispatch, vkey_destroy, NULL, 587 vigenere_impl_docstring); 588 if (!LE_status_is_OK(sts)) 589 return sts; 590 sts = LSC_deregister_encryptor_implementation(env, plugin, "vigenere", 591 venc_dispatch, venc_destroy, NULL, 592 vigenere_impl_docstring); 593 if (!LE_status_is_OK(sts)) 594 return sts; 595 sts = LSC_deregister_decryptor_implementation(env, plugin, "vigenere", 596 vdec_dispatch, vdec_destroy, NULL, 597 vigenere_impl_docstring); 598 return sts; 599 }