/ lib / rand.c
rand.c
  1  /*
  2   * SPDX-FileCopyrightText: Le'Sec collective
  3   *
  4   * SPDX-License-Identifier: LGPL-3.0-or-later
  5   */
  6  
  7  #include <stdio.h>
  8  #include <stdbool.h>
  9  #include <string.h>
 10  #include <lesec/rand.h>
 11  #include <lesec/plugin.h>
 12  #include <lscore/index.h>
 13  #include <lscrypto/rand.h>
 14  #include "local.h"
 15  
 16  struct do_all_data_st {
 17    LeSec_do_all_rbg_implementations_callback_fn *fn;
 18    void *user_arg;
 19  };
 20  
 21  static LE_STATUS
 22  do_all_hook(const char *class, const char *id,
 23              const LSC_plugin_t *plug, const LSC_env_t *env,
 24              LSC_rbg_dispatch_fn *dispatch,
 25              LSC_rbg_destroy_fn *destroy,
 26              const void *dispatch_data,
 27              const char *docstring,
 28              void *arg)
 29  {
 30    LE_STATUS sts;
 31    LeSec_plugin_t *plugin = NULL;
 32    struct do_all_data_st *data = arg;
 33    LSC_plugin_t *plug_noconst = (LSC_plugin_t *)plug;
 34    int app_index;
 35  
 36    if (!LE_status_is_OK(LSC_get_index((LSC_env_t *)env, LESEC_TAG, &app_index))
 37        || !LE_status_is_OK(sts = LSC_get_plugin_application_data(plug_noconst,
 38                                                                  app_index,
 39                                                                  &plugin)))
 40      return LE_STS_WARNING;
 41    return data->fn(class, id, plugin, data->user_arg);
 42  }
 43  
 44  LESEC_EXPORT LE_STATUS
 45  LeSec_do_all_rbg_implementations
 46  (LeSec_do_all_rbg_implementations_callback_fn *fn, void *user_arg,
 47   LeSec_env_t *env)
 48  {
 49    struct do_all_data_st data = { fn, user_arg };
 50    return LSC_do_all_rbg_implementations(env, do_all_hook, &data);
 51  }
 52  
 53  struct find_data_st {
 54    const char *id;
 55    LeSec_find_rbg_implementation_filter_fn *fn;
 56    void *user_arg;
 57  
 58    size_t implementations;
 59    LSC_rbg_dispatch_fn *dispatch;
 60    LSC_rbg_destroy_fn *destroy;
 61    const void *dispatch_data;
 62    const char *docstring;
 63  };
 64  
 65  static LE_STATUS
 66  find_hook(const char *class, const char *id,
 67            const LSC_plugin_t *plug, const LSC_env_t *env,
 68            LSC_rbg_dispatch_fn *dispatch,
 69            LSC_rbg_destroy_fn *destroy,
 70            const void *dispatch_data,
 71            const char *docstring,
 72            void *arg)
 73  {
 74    LE_STATUS sts;
 75    LeSec_plugin_t *plugin = NULL;
 76    struct find_data_st *data = arg;
 77    LSC_plugin_t *plug_noconst = (LSC_plugin_t *)plug;
 78    _Bool yes = false;
 79    int app_index;
 80  
 81    if (strcmp(id, data->id) != 0)
 82      return LE_STS_SUCCESS;   /* Do nothing but don't break the loop */
 83    if (!LE_status_is_OK(LSC_get_index((LSC_env_t *)env, LESEC_TAG, &app_index))
 84        || !LE_status_is_OK(sts = LSC_get_plugin_application_data(plug_noconst,
 85                                                                  app_index,
 86                                                                  &plugin)))
 87      return LE_STS_WARNING;
 88    if (data->fn == NULL
 89        || (LE_status_is_OK(sts = data->fn(class, id, plugin, &yes,
 90                                           data->user_arg))
 91            && yes)) {
 92      data->dispatch = dispatch;
 93      data->destroy = destroy;
 94      data->dispatch_data = dispatch_data;
 95      data->docstring = docstring;
 96      data->implementations++;
 97    }
 98    return sts;
 99  }
100  
101  LESEC_EXPORT LE_STATUS
102  LeSec_make_rbg(const char *id,
103                 LeSec_find_rbg_implementation_filter_fn *fn,
104                 void *user_arg,
105                 LeSec_rbg_t **sp,
106                 const char **docstring,
107                 LeSec_env_t *env)
108  {
109    LE_STATUS sts;
110    struct find_data_st data = { id, fn, user_arg, 0, NULL, NULL };
111  
112    if (id == NULL)
113      return LE_STS_ERROR;
114    if (LE_status_is_OK(sts = LSC_do_all_rbg_implementations(env, find_hook,
115                                                             &data)))
116      if (data.implementations == 0)
117        return LE_STS_NOT_IMPLEMENTED;
118      else if (data.implementations > 1)
119        return LE_STS_ERROR;
120  
121    sts = LSC_new_rbg(data.dispatch, data.destroy, data.dispatch_data, sp);
122    if (LE_status_is_OK(sts) && docstring != NULL)
123      *docstring = data.docstring;
124  
125    return sts;
126  }