2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
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
12 #include <openssl/crypto.h>
13 #include <openssl/lhash.h>
14 #include "crypto/lhash.h"
15 #include "property_local.h"
18 * Property strings are a consolidation of all strings seen by the property
19 * subsystem. There are two name spaces to keep property names separate from
20 * property values (numeric values are not expected to be cached however).
21 * They allow a rapid conversion from a string to a unique index and any
22 * subsequent string comparison can be done via an integer compare.
24 * This implementation uses OpenSSL's standard hash table. There are more
25 * space and time efficient algorithms if this becomes a bottleneck.
30 OSSL_PROPERTY_IDX idx
;
34 DEFINE_LHASH_OF(PROPERTY_STRING
);
35 typedef LHASH_OF(PROPERTY_STRING
) PROP_TABLE
;
38 PROP_TABLE
*prop_names
;
39 PROP_TABLE
*prop_values
;
40 OSSL_PROPERTY_IDX prop_name_idx
;
41 OSSL_PROPERTY_IDX prop_value_idx
;
42 } PROPERTY_STRING_DATA
;
44 static unsigned long property_hash(const PROPERTY_STRING
*a
)
46 return OPENSSL_LH_strhash(a
->s
);
49 static int property_cmp(const PROPERTY_STRING
*a
, const PROPERTY_STRING
*b
)
51 return strcmp(a
->s
, b
->s
);
54 static void property_free(PROPERTY_STRING
*ps
)
59 static void property_table_free(PROP_TABLE
**pt
)
64 lh_PROPERTY_STRING_doall(t
, &property_free
);
65 lh_PROPERTY_STRING_free(t
);
70 static void property_string_data_free(void *vpropdata
)
72 PROPERTY_STRING_DATA
*propdata
= vpropdata
;
77 property_table_free(&propdata
->prop_names
);
78 property_table_free(&propdata
->prop_values
);
79 propdata
->prop_name_idx
= propdata
->prop_value_idx
= 0;
81 OPENSSL_free(propdata
);
84 static void *property_string_data_new(OSSL_LIB_CTX
*ctx
) {
85 PROPERTY_STRING_DATA
*propdata
= OPENSSL_zalloc(sizeof(*propdata
));
90 propdata
->prop_names
= lh_PROPERTY_STRING_new(&property_hash
,
92 if (propdata
->prop_names
== NULL
)
95 propdata
->prop_values
= lh_PROPERTY_STRING_new(&property_hash
,
97 if (propdata
->prop_values
== NULL
)
103 property_string_data_free(propdata
);
107 static const OSSL_LIB_CTX_METHOD property_string_data_method
= {
108 property_string_data_new
,
109 property_string_data_free
,
112 static PROPERTY_STRING
*new_property_string(const char *s
,
113 OSSL_PROPERTY_IDX
*pidx
)
115 const size_t l
= strlen(s
);
116 PROPERTY_STRING
*ps
= OPENSSL_malloc(sizeof(*ps
) + l
);
119 memcpy(ps
->body
, s
, l
+ 1);
130 static OSSL_PROPERTY_IDX
ossl_property_string(PROP_TABLE
*t
,
131 OSSL_PROPERTY_IDX
*pidx
,
134 PROPERTY_STRING p
, *ps
, *ps_new
;
137 ps
= lh_PROPERTY_STRING_retrieve(t
, &p
);
138 if (ps
== NULL
&& pidx
!= NULL
)
139 if ((ps_new
= new_property_string(s
, pidx
)) != NULL
) {
140 lh_PROPERTY_STRING_insert(t
, ps_new
);
141 if (lh_PROPERTY_STRING_error(t
)) {
142 property_free(ps_new
);
147 return ps
!= NULL
? ps
->idx
: 0;
150 OSSL_PROPERTY_IDX
ossl_property_name(OSSL_LIB_CTX
*ctx
, const char *s
,
153 PROPERTY_STRING_DATA
*propdata
154 = ossl_lib_ctx_get_data(ctx
, OSSL_LIB_CTX_PROPERTY_STRING_INDEX
,
155 &property_string_data_method
);
157 if (propdata
== NULL
)
159 return ossl_property_string(propdata
->prop_names
,
160 create
? &propdata
->prop_name_idx
: NULL
,
164 OSSL_PROPERTY_IDX
ossl_property_value(OSSL_LIB_CTX
*ctx
, const char *s
,
167 PROPERTY_STRING_DATA
*propdata
168 = ossl_lib_ctx_get_data(ctx
, OSSL_LIB_CTX_PROPERTY_STRING_INDEX
,
169 &property_string_data_method
);
171 if (propdata
== NULL
)
173 return ossl_property_string(propdata
->prop_values
,
174 create
? &propdata
->prop_value_idx
: NULL
,