/ 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  }