property_string.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
  3. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
  4. *
  5. * Licensed under the Apache License 2.0 (the "License"). You may not use
  6. * this file except in compliance with the License. You can obtain a copy
  7. * in the file LICENSE in the source distribution or at
  8. * https://www.openssl.org/source/license.html
  9. */
  10. #include <string.h>
  11. #include <openssl/crypto.h>
  12. #include <openssl/lhash.h>
  13. #include "internal/lhash.h"
  14. #include "property_lcl.h"
  15. /*
  16. * Property strings are a consolidation of all strings seen by the property
  17. * subsystem. There are two name spaces to keep property names separate from
  18. * property values (numeric values are not expected to be cached however).
  19. * They allow a rapid conversion from a string to a unique index and any
  20. * subsequent string comparison can be done via an integer compare.
  21. *
  22. * This implementation uses OpenSSL's standard hash table. There are more
  23. * space and time efficient algorithms if this becomes a bottleneck.
  24. */
  25. typedef struct {
  26. const char *s;
  27. OSSL_PROPERTY_IDX idx;
  28. char body[1];
  29. } PROPERTY_STRING;
  30. DEFINE_LHASH_OF(PROPERTY_STRING);
  31. typedef LHASH_OF(PROPERTY_STRING) PROP_TABLE;
  32. typedef struct {
  33. PROP_TABLE *prop_names;
  34. PROP_TABLE *prop_values;
  35. OSSL_PROPERTY_IDX prop_name_idx;
  36. OSSL_PROPERTY_IDX prop_value_idx;
  37. } PROPERTY_STRING_DATA;
  38. static unsigned long property_hash(const PROPERTY_STRING *a)
  39. {
  40. return OPENSSL_LH_strhash(a->s);
  41. }
  42. static int property_cmp(const PROPERTY_STRING *a, const PROPERTY_STRING *b)
  43. {
  44. return strcmp(a->s, b->s);
  45. }
  46. static void property_free(PROPERTY_STRING *ps)
  47. {
  48. OPENSSL_free(ps);
  49. }
  50. static void property_table_free(PROP_TABLE **pt)
  51. {
  52. PROP_TABLE *t = *pt;
  53. if (t != NULL) {
  54. lh_PROPERTY_STRING_doall(t, &property_free);
  55. lh_PROPERTY_STRING_free(t);
  56. *pt = NULL;
  57. }
  58. }
  59. static void property_string_data_free(void *vpropdata)
  60. {
  61. PROPERTY_STRING_DATA *propdata = vpropdata;
  62. if (propdata == NULL)
  63. return;
  64. property_table_free(&propdata->prop_names);
  65. property_table_free(&propdata->prop_values);
  66. propdata->prop_name_idx = propdata->prop_value_idx = 0;
  67. OPENSSL_free(propdata);
  68. }
  69. static void *property_string_data_new(OPENSSL_CTX *ctx) {
  70. PROPERTY_STRING_DATA *propdata = OPENSSL_zalloc(sizeof(*propdata));
  71. if (propdata == NULL)
  72. return NULL;
  73. propdata->prop_names = lh_PROPERTY_STRING_new(&property_hash,
  74. &property_cmp);
  75. if (propdata->prop_names == NULL)
  76. goto err;
  77. propdata->prop_values = lh_PROPERTY_STRING_new(&property_hash,
  78. &property_cmp);
  79. if (propdata->prop_values == NULL)
  80. goto err;
  81. return propdata;
  82. err:
  83. property_string_data_free(propdata);
  84. return NULL;
  85. }
  86. static const OPENSSL_CTX_METHOD property_string_data_method = {
  87. property_string_data_new,
  88. property_string_data_free,
  89. };
  90. static PROPERTY_STRING *new_property_string(const char *s,
  91. OSSL_PROPERTY_IDX *pidx)
  92. {
  93. const size_t l = strlen(s);
  94. PROPERTY_STRING *ps = OPENSSL_malloc(sizeof(*ps) + l);
  95. if (ps != NULL) {
  96. memcpy(ps->body, s, l + 1);
  97. ps->s = ps->body;
  98. ps->idx = ++*pidx;
  99. if (ps->idx == 0) {
  100. OPENSSL_free(ps);
  101. return NULL;
  102. }
  103. }
  104. return ps;
  105. }
  106. static OSSL_PROPERTY_IDX ossl_property_string(PROP_TABLE *t,
  107. OSSL_PROPERTY_IDX *pidx,
  108. const char *s)
  109. {
  110. PROPERTY_STRING p, *ps, *ps_new;
  111. p.s = s;
  112. ps = lh_PROPERTY_STRING_retrieve(t, &p);
  113. if (ps == NULL && pidx != NULL)
  114. if ((ps_new = new_property_string(s, pidx)) != NULL) {
  115. lh_PROPERTY_STRING_insert(t, ps_new);
  116. if (lh_PROPERTY_STRING_error(t)) {
  117. property_free(ps_new);
  118. return 0;
  119. }
  120. ps = ps_new;
  121. }
  122. return ps != NULL ? ps->idx : 0;
  123. }
  124. OSSL_PROPERTY_IDX ossl_property_name(OPENSSL_CTX *ctx, const char *s,
  125. int create)
  126. {
  127. PROPERTY_STRING_DATA *propdata
  128. = openssl_ctx_get_data(ctx, OPENSSL_CTX_PROPERTY_STRING_INDEX,
  129. &property_string_data_method);
  130. if (propdata == NULL)
  131. return 0;
  132. return ossl_property_string(propdata->prop_names,
  133. create ? &propdata->prop_name_idx : NULL,
  134. s);
  135. }
  136. OSSL_PROPERTY_IDX ossl_property_value(OPENSSL_CTX *ctx, const char *s,
  137. int create)
  138. {
  139. PROPERTY_STRING_DATA *propdata
  140. = openssl_ctx_get_data(ctx, OPENSSL_CTX_PROPERTY_STRING_INDEX,
  141. &property_string_data_method);
  142. if (propdata == NULL)
  143. return 0;
  144. return ossl_property_string(propdata->prop_values,
  145. create ? &propdata->prop_value_idx : NULL,
  146. s);
  147. }