/ ltc-sym-keys.c
ltc-sym-keys.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 <stdbool.h>
 19  #include <lscore/plugin.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  #include "ltc-sym-keys.h"
 26  
 27  #define T(x) LE_status_is_OK(x)
 28  
 29  #define nelems(a) (sizeof(a) / sizeof(a[0]))
 30  
 31  /*
 32   * Key data support functions.  The key data they manipulate,
 33   * struct ltc_symkey_st, is defined in ltc-sym-keys.h.
 34   */
 35  /*
 36   * The functions scrub_symkey(), new_symkey() and
 37   * clean_symkey() are defined further down.
 38   */
 39  static LE_STATUS scrub_symkey_data(LSC_key_t *obj);
 40  static LE_STATUS new_symkey_data(LSC_key_t *obj, const void *desc);
 41  
 42  /* Key constructor operation with support functions */
 43  
 44  struct ltc_symkey_constructor_st {
 45    LSC_key_t *key;
 46  
 47    /* Operational parameters */
 48  
 49    /* Key bits */
 50    unsigned char *key_bits;
 51    size_t key_bits_len;          /* Measured in bits */
 52  
 53    /*
 54     * The parameter descriptions.
 55     * They need to be dynamic, because the key sizes depend on the algorithm.
 56     */
 57    LSC_param_desc_t gettable_params[2];
 58    LSC_param_desc_t settable_params[2];
 59  
 60    /* True when they've been cached in the key itself */
 61    _Bool key_bits_cached;
 62  };
 63  
 64  static LE_STATUS compute_desc_keysizes(struct ltc_symkey_constructor_st *c,
 65                                         LSC_param_desc_t *desc)
 66  {
 67    assert(c != NULL && desc != NULL);
 68  
 69    struct ltc_symkey_st *k = (c != NULL) ? c->key->lsc_data : NULL;
 70  
 71    unsigned int kb = 65536; /* We start with something absurdly large */
 72    unsigned int previous_kb = kb; /* To keep track of stepping */
 73    off_t start;             /* Where does the series of sizes start? */
 74    off_t end;               /* Where does the series of sizes start? */
 75    size_t d_elems_sz = nelems(desc->p_data.d_elems);
 76    size_t factor = desc->p_data.d_type == LSC_DT_bit_string ? 8 : 1;
 77    size_t step = 0;
 78    int ltc_err;
 79  
 80    start = end = d_elems_sz - 1;
 81    while (start > 0) {
 82      while ((ltc_err = k->desc->keysize(&kb)) == CRYPT_OK
 83             && step == previous_kb - kb) {
 84        desc->p_data.d_elems[start].min = kb * factor;
 85        previous_kb = kb--;
 86      }
 87      if (ltc_err != CRYPT_OK)
 88        break;
 89  
 90      previous_kb = kb--;
 91      start--;
 92      if (k->desc->keysize(&kb) == CRYPT_OK) {
 93        desc->p_data.d_elems[start].max = previous_kb * factor;
 94        desc->p_data.d_elems[start].min = kb * factor;
 95        step = previous_kb - kb;
 96        desc->p_data.d_elems[start].step = step * factor;
 97        previous_kb = kb--;
 98      } else {
 99        desc->p_data.d_elems[start].max = previous_kb * factor;
100        desc->p_data.d_elems[start].min = previous_kb * factor;
101        desc->p_data.d_elems[start].step = 0;
102        break;
103      }
104    }
105  
106    /* No sizes at all?  That's wrong! */
107    if (start == d_elems_sz - 1)
108      return LE_STS_ERROR;
109  
110    /* Now that we figured them out, adjust the array if needed */
111    if (start != 0) {
112      for (end = 0; start < d_elems_sz - 1; start++, end++)
113        desc->p_data.d_elems[end] = desc->p_data.d_elems[start];
114      if (start != d_elems_sz - 1)
115        return LE_STS_ERROR;
116    }
117  
118    /* Make sure to terminate */
119    desc->p_data.d_elems[end].min = desc->p_data.d_elems[end].max = 0;
120  
121    return LE_STS_SUCCESS;
122  }
123  
124  static LSplugin_param_functions_t symkey_bits_fns = {
125    offsetof(struct ltc_symkey_constructor_st, key_bits),
126    offsetof(struct ltc_symkey_constructor_st, key_bits_len),
127    0, false,
128    LSplugin_set_bitstring_param, LSplugin_get_bitstring_param
129  };
130  #define SYM_CIPHER_I_key_bits           1
131  #define SYM_CIPHER_P_key_bits                                   \
132    { "key", SYM_CIPHER_I_key_bits,                               \
133        { LSC_DT_bit_string, { { 0, 0 }, },                       \
134            .d_auxilliary = { 0 }, },                             \
135        &symkey_bits_fns }
136  
137  static LE_STATUS scrub_symkey_constructor_data(LSC_key_constructor_t *op)
138  {
139    if (op == NULL || op->lsc_data == NULL)
140      return LE_STS_SUCCESS;
141  
142    struct ltc_symkey_constructor_st *g = op->lsc_data;
143  
144    memset(g, 0, sizeof(*g));
145    return LE_STS_SUCCESS;
146  }
147  
148  static LE_STATUS new_symkey_constructor_data(LSC_key_constructor_t *op)
149  {
150    LE_STATUS sts;
151  
152    if (op == NULL)
153      return LE_STS_ERROR;
154  
155    struct ltc_symkey_constructor_st **g
156      = (struct ltc_symkey_constructor_st **)&op->lsc_data;
157  
158      if (*g == NULL && (*g = malloc(sizeof(**g))) != NULL)
159        memset(*g, 0, sizeof(**g));
160    if (*g == NULL)
161      return LE_STS_FATAL_ERROR;
162    return LE_STS_SUCCESS;
163  }
164  
165  static LE_STATUS clean_symkey_constructor_data(LSC_key_constructor_t *op)
166  {
167    LE_STATUS sts;
168  
169    if (op == NULL || op->lsc_data == NULL)
170      return LE_STS_SUCCESS;
171    if (T(sts = scrub_symkey_constructor_data(op))) {
172      free(op->lsc_data);
173      op->lsc_data = NULL;
174    }
175    return sts;
176  }
177  
178  static LE_STATUS set_symkey_constructor(LSC_key_t *key,
179                                          LSC_key_constructor_t *op)
180  {
181    struct ltc_symkey_st *k = key->lsc_data;
182  
183    k->constructor = op;
184    return LE_STS_SUCCESS;
185  }
186  
187  static LE_STATUS set_constructor_symkey(LSC_key_constructor_t *op,
188                                          LSC_key_t *key)
189  {
190    LE_STATUS sts;
191  
192    if (LE_status_is_OK(sts = new_symkey_constructor_data(op))) {
193      struct ltc_symkey_constructor_st *c = op->lsc_data;
194  
195      c->key = key;
196  
197      c->gettable_params[0] = (LSC_param_desc_t) SYM_CIPHER_P_key_bits;
198      if (!LE_status_is_OK(sts = compute_desc_keysizes(c, &c->gettable_params[0])))
199        return sts;
200      c->gettable_params[1] = (LSC_param_desc_t) { NULL, };
201  
202      c->settable_params[0] = (LSC_param_desc_t) SYM_CIPHER_P_key_bits;
203      if (!LE_status_is_OK(sts = compute_desc_keysizes(c, &c->settable_params[0])))
204        return sts;
205      c->settable_params[1] = (LSC_param_desc_t) { NULL, };
206    }
207    return sts;
208  }
209  
210  static LE_STATUS get_constructor_symkey(LSC_key_constructor_t *op,
211                                          LSC_key_t **key)
212  {
213    struct ltc_symkey_constructor_st *c = op->lsc_data;
214  
215    *key = c->key;
216    return LE_STS_SUCCESS;
217  }
218  
219  static LE_STATUS get_construction_param_data(LSC_key_constructor_t *op, void **data)
220  {
221    *data = op->lsc_data;
222    return LE_STS_SUCCESS;
223  }
224  
225  static LE_STATUS
226  get_gettable_construction_param_desc(LSC_key_constructor_t *op,
227                                       const LSC_param_desc_t **param_desc)
228  {
229    assert(op != NULL);
230    assert(param_desc != NULL);
231  
232    if (op->lsc_data == NULL) {
233      static const LSC_param_desc_t pd[] = {
234        SYM_CIPHER_P_key_bits,
235        { NULL, }
236      };
237      *param_desc = pd;
238    } else {
239      struct ltc_symkey_constructor_st *c = op->lsc_data;
240      *param_desc = c->gettable_params;
241    }
242    return LE_STS_SUCCESS;
243  }
244  
245  static LE_STATUS
246  get_settable_construction_param_desc(LSC_key_constructor_t *op,
247                                       const LSC_param_desc_t **param_desc)
248  {
249    assert(op != NULL);
250    assert(param_desc != NULL);
251  
252    if (op->lsc_data == NULL) {
253      static const LSC_param_desc_t pd[] = {
254        SYM_CIPHER_P_key_bits,
255        { NULL, }
256      };
257      *param_desc = pd;
258    } else {
259      struct ltc_symkey_constructor_st *c = op->lsc_data;
260      *param_desc = c->settable_params;
261    }
262    return LE_STS_SUCCESS;
263  }
264  
265  LE_STATUS construct_symkey_data(LSC_key_constructor_t *op)
266  {
267    LE_STATUS sts;
268    struct ltc_symkey_constructor_st *c = op->lsc_data;
269    LSC_key_t *key = c != NULL ? c->key : NULL;
270    struct ltc_symkey_st *k = (key != NULL) ? key->lsc_data : NULL;
271  
272    if (T(sts = scrub_symkey_data(key))) {
273      int err = k->desc->setup(c->key_bits, c->key_bits_len / 8, 0, &k->key);
274      sts = (err == CRYPT_OK) ? LE_STS_SUCCESS : LE_STS_ERROR;
275      if (T(sts)) {
276        /* Cache the key bits in the key itself too, to support extraction */
277        k->key_bits = c->key_bits;
278        k->key_bits_len = c->key_bits_len;
279        c->key_bits_cached = true;
280      }
281    }
282    return sts;
283  }
284  
285  /* local symkey constructor descriptor, used in |ltc_{name}_desc| below */
286  static LSplugin_key_constructor_desc_t ltc_symkey_constructor_desc = {
287    NULL, NULL, NULL, NULL, /* lsp_docstring, lsp_id, lsp_priv_desc, lsp_key_id */
288    new_symkey_constructor_data, clean_symkey_constructor_data,
289    set_symkey_constructor, set_constructor_symkey, get_constructor_symkey,
290    (int[]){ LSC_KEY_TYPE_CONSTRUCTOR_COMMANDS(),
291             LSC_NR_get_settable_key_construction_param_desc,
292             LSC_NR_set_key_construction_param,
293             LSC_NR_get_gettable_key_construction_param_desc,
294             LSC_NR_get_key_construction_param,
295             LSC_NR_construct_key, 0 },
296    get_construction_param_data,
297    get_gettable_construction_param_desc, /* gettable */
298    get_settable_construction_param_desc, /* settable */
299    construct_symkey_data
300  };
301  
302  /* Key associated operations (they all use the same libtomcrypt function) */
303  
304  LE_STATUS get_symkey_unit_size(LSC_key_t *key, size_t *size)
305  {
306    struct ltc_symkey_st *k = key->lsc_data;
307  
308    *size = k->desc->block_length;
309    return LE_STS_SUCCESS;
310  }
311  
312  LE_STATUS get_symkey_input_size(LSC_key_t *key, size_t *size)
313  {
314    return get_symkey_unit_size(key, size);
315  }
316  
317  LE_STATUS get_symkey_output_size(LSC_key_t *key, size_t *size)
318  {
319    return get_symkey_unit_size(key, size);
320  }
321  
322  #define IMPL_ASSOCIATED_OP_FUNCTIONS(T,N,F)                             \
323    static LE_STATUS set_symkey_##T(LSC_key_t *key, LSC_##T##_t *op)      \
324    {                                                                     \
325      struct ltc_symkey_st *k = key->lsc_data;                            \
326                                                                          \
327      k->T = op;                                                          \
328      return LE_STS_SUCCESS;                                              \
329    }                                                                     \
330    static LE_STATUS set_##T##_symkey(LSC_##T##_t *op, LSC_key_t *key)    \
331    {                                                                     \
332      op->lsc_data = key;                                                 \
333      return LE_STS_SUCCESS;                                              \
334    }                                                                     \
335    static LE_STATUS get_##T##_symkey(LSC_##T##_t *op, LSC_key_t **key)   \
336    {                                                                     \
337      *key = op->lsc_data;                                                \
338      return LE_STS_SUCCESS;                                              \
339    }                                                                     \
340    LE_STATUS perform_symkey_##N##_once(LSC_##T##_t *op,                  \
341                                        const unsigned char *in,          \
342                                        size_t inlen,                     \
343                                        unsigned char *out,               \
344                                        size_t outsize,                   \
345                                        size_t *outlen)                   \
346    {                                                                     \
347      LE_STATUS sts;                                                      \
348      LSC_key_t *key = NULL;                                              \
349                                                                          \
350      if (!LE_status_is_OK(get_##T##_symkey(op, &key)))                   \
351        return sts;                                                       \
352                                                                          \
353      struct ltc_symkey_st *k = key->lsc_data;                            \
354                                                                          \
355      if (inlen != k->desc->block_length                                  \
356          || outsize < k->desc->block_length)                             \
357        return LE_STS_ERROR;                                              \
358                                                                          \
359      int err = k->desc->F(in, out, &k->key);                             \
360      sts = (err == CRYPT_OK) ? LE_STS_SUCCESS : LE_STS_ERROR;            \
361                                                                          \
362      if (LE_status_is_OK(sts))                                           \
363        *outlen = inlen;                                                  \
364      return sts;                                                         \
365    }
366  #define IMPL_PRIMITIVE_SIZE_FUNCTION(T,N,K)                             \
367    static LE_STATUS get_symkey_##N##_##K##_size(LSC_##T##_t *op,         \
368                                                 size_t *size)            \
369    {                                                                     \
370      LE_STATUS sts;                                                      \
371      LSC_key_t *key = NULL;                                              \
372      if (!LE_status_is_OK(sts = get_##T##_symkey(op, &key)))             \
373        return sts;                                                       \
374      return get_symkey_##K##_size(key, size);                            \
375    }
376  
377  IMPL_ASSOCIATED_OP_FUNCTIONS(encryptor,encryption,ecb_encrypt);
378  IMPL_PRIMITIVE_SIZE_FUNCTION(encryptor,encryption,unit);
379  IMPL_PRIMITIVE_SIZE_FUNCTION(encryptor,encryption,input);
380  IMPL_PRIMITIVE_SIZE_FUNCTION(encryptor,encryption,output);
381  #define SPEC_SYMKEY_encryptor_COMMANDS()                                \
382    LSC_ENCRYPTOR_TYPE_BASE_COMMANDS(), LSC_ENCRYPTOR_SIZE_COMMANDS(),    \
383      LSC_NR_perform_encryption_once
384  #define SPEC_SYMKEY_encryptor_FUNCTIONS()                               \
385    get_symkey_encryption_unit_size, get_symkey_encryption_input_size,    \
386      get_symkey_encryption_output_size, perform_symkey_encryption_once
387  
388  IMPL_ASSOCIATED_OP_FUNCTIONS(decryptor,decryption,ecb_decrypt);
389  IMPL_PRIMITIVE_SIZE_FUNCTION(decryptor,decryption,unit);
390  IMPL_PRIMITIVE_SIZE_FUNCTION(decryptor,decryption,input);
391  IMPL_PRIMITIVE_SIZE_FUNCTION(decryptor,decryption,output);
392  #define SPEC_SYMKEY_decryptor_COMMANDS()                                \
393    LSC_DECRYPTOR_TYPE_BASE_COMMANDS(), LSC_DECRYPTOR_SIZE_COMMANDS(),    \
394      LSC_NR_perform_decryption_once
395  #define SPEC_SYMKEY_decryptor_FUNCTIONS()                               \
396    get_symkey_decryption_unit_size, get_symkey_decryption_input_size,    \
397      get_symkey_decryption_output_size, perform_symkey_decryption_once
398  
399  #define IMPL_ASSOCIATED_OP(T)                                           \
400    LSplugin_##T##_desc_t ltc_symkey_##T##_desc = {                       \
401      NULL, NULL, NULL, NULL, /* lsp_docstring, lsp_id, lsp_priv_desc, lsp_key_id */ \
402      NULL, NULL, set_symkey_##T, set_##T##_symkey, get_##T##_symkey,     \
403      (int[]){ SPEC_SYMKEY_##T##_COMMANDS() },                            \
404      NULL, NULL, NULL,                                                   \
405      SPEC_SYMKEY_##T##_FUNCTIONS()                                       \
406    }
407  
408  IMPL_ASSOCIATED_OP(encryptor);
409  IMPL_ASSOCIATED_OP(decryptor);
410  
411  /* Main object functions */
412  
413  static LE_STATUS scrub_symkey_data(LSC_key_t *key)
414  {
415    if (key == NULL || key->lsc_data == NULL)
416      return LE_STS_SUCCESS;
417  
418    struct ltc_symkey_st *k = key->lsc_data;
419  
420    k->desc->done(&k->key);
421    /* DO NOTE that we aren't scrubbing the cached associated operations */
422    return LE_STS_SUCCESS;
423  }
424  
425  static LE_STATUS new_symkey_data(LSC_key_t *key, const void *desc)
426  {
427    LE_STATUS sts;
428  
429    if (key == NULL)
430      return LE_STS_ERROR;
431    struct ltc_symkey_st **k = (struct ltc_symkey_st **)&key->lsc_data;
432  
433    if (*k == NULL && (*k = malloc(sizeof(**k))) != NULL) {
434      memset(*k, 0, sizeof(**k));
435      (*k)->desc = desc;
436    }
437    if (*k == NULL)
438      return LE_STS_FATAL_ERROR;
439    return LE_STS_SUCCESS;
440  }
441  
442  static LE_STATUS clean_symkey_data(LSC_key_t *key)
443  {
444    LE_STATUS sts;
445  
446    if (key == NULL || key->lsc_data == NULL)
447      return LE_STS_SUCCESS;
448    if (T(sts = scrub_symkey_data(key))) {
449      struct ltc_symkey_st *k = key->lsc_data;
450      /*
451       * The constructor, encryptor and decryptor are cached, so they don't
452       * provide a destroy function in the operation object, which means
453       * that the LSC_free_key_{operation}() calls end up doing nothing.
454       * Therefore, we must destroy them now, using their destroy functions
455       * (which do exist) directly.
456       */
457      LSplugin_destroy_key_constructor(k->constructor);
458      LSplugin_destroy_encryptor(k->encryptor);
459      LSplugin_destroy_decryptor(k->decryptor);
460      free(k);
461      key->lsc_data = NULL;
462    }
463    return sts;
464  }
465  
466  static LE_STATUS get_symkey_size(LSC_key_t *key, size_t *keysize)
467  {
468    struct ltc_symkey_st *k = key->lsc_data;
469  
470    if (k->key_bits == NULL)
471      return LE_STS_ERROR;
472    *keysize = k->key_bits_len;
473    return LE_STS_SUCCESS;
474  }
475  
476  #define IMPL_aes_NAME()         "aes"
477  #define IMPL_des3_NAME()        "3des"
478  #define IMPL_blowfish_NAME()    "blowfish"
479  #define IMPL_twofish_NAME()     "twofish"
480  #define IMPL_cast5_NAME()       "cast5"
481  #define IMPL_kseed_NAME()       "seed"
482  #define IMPL_camellia_NAME()    "camellia"
483  #define IMPL_CIPHER_KEY(N, propdef)                                     \
484    const LSplugin_key_desc_t ltc_##N##_desc = {                          \
485      NULL, IMPL_##N##_NAME(), &N##_desc,                                 \
486      new_symkey_data, clean_symkey_data,                                 \
487      (int[]){ LSC_KEY_TYPE_BASE_COMMANDS(),                              \
488               LSC_NR_get_key_size,                                       \
489               LSC_NR_get_key_constructor,                                \
490               LSC_NR_get_associated_encryptor,                           \
491               LSC_NR_get_associated_decryptor, 0 },                      \
492      get_symkey_size,                                                    \
493      NULL,                                                               \
494      &ltc_symkey_constructor_desc,                                       \
495      NULL,                                                               \
496      &ltc_symkey_encryptor_desc,                                         \
497      &ltc_symkey_decryptor_desc,                                         \
498    }
499  IMPL_CIPHER_KEY(aes, NULL);
500  IMPL_CIPHER_KEY(des3, NULL);
501  IMPL_CIPHER_KEY(blowfish, NULL);
502  IMPL_CIPHER_KEY(twofish, NULL);
503  IMPL_CIPHER_KEY(cast5, NULL);
504  IMPL_CIPHER_KEY(kseed, NULL);
505  IMPL_CIPHER_KEY(camellia, NULL);