Coverage Report

Created: 2025-08-08 06:10

/src/rauc/subprojects/openssl-3.0.8/crypto/property/property_string.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2019-2022 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
11
#include <string.h>
12
#include <openssl/crypto.h>
13
#include <openssl/lhash.h>
14
#include "crypto/lhash.h"
15
#include "property_local.h"
16
17
/*
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.
23
 *
24
 * This implementation uses OpenSSL's standard hash table.  There are more
25
 * space and time efficient algorithms if this becomes a bottleneck.
26
 */
27
28
typedef struct {
29
    const char *s;
30
    OSSL_PROPERTY_IDX idx;
31
    char body[1];
32
} PROPERTY_STRING;
33
34
DEFINE_LHASH_OF(PROPERTY_STRING);
35
typedef LHASH_OF(PROPERTY_STRING) PROP_TABLE;
36
37
typedef struct {
38
    CRYPTO_RWLOCK *lock;
39
    PROP_TABLE *prop_names;
40
    PROP_TABLE *prop_values;
41
    OSSL_PROPERTY_IDX prop_name_idx;
42
    OSSL_PROPERTY_IDX prop_value_idx;
43
} PROPERTY_STRING_DATA;
44
45
static unsigned long property_hash(const PROPERTY_STRING *a)
46
7.63k
{
47
7.63k
    return OPENSSL_LH_strhash(a->s);
48
7.63k
}
49
50
static int property_cmp(const PROPERTY_STRING *a, const PROPERTY_STRING *b)
51
7.57k
{
52
7.57k
    return strcmp(a->s, b->s);
53
7.57k
}
54
55
static void property_free(PROPERTY_STRING *ps)
56
22
{
57
22
    OPENSSL_free(ps);
58
22
}
59
60
static void property_table_free(PROP_TABLE **pt)
61
2
{
62
2
    PROP_TABLE *t = *pt;
63
64
2
    if (t != NULL) {
65
2
        lh_PROPERTY_STRING_doall(t, &property_free);
66
2
        lh_PROPERTY_STRING_free(t);
67
2
        *pt = NULL;
68
2
    }
69
2
}
70
71
static void property_string_data_free(void *vpropdata)
72
1
{
73
1
    PROPERTY_STRING_DATA *propdata = vpropdata;
74
75
1
    if (propdata == NULL)
76
0
        return;
77
78
1
    CRYPTO_THREAD_lock_free(propdata->lock);
79
1
    property_table_free(&propdata->prop_names);
80
1
    property_table_free(&propdata->prop_values);
81
1
    propdata->prop_name_idx = propdata->prop_value_idx = 0;
82
83
1
    OPENSSL_free(propdata);
84
1
}
85
86
1
static void *property_string_data_new(OSSL_LIB_CTX *ctx) {
87
1
    PROPERTY_STRING_DATA *propdata = OPENSSL_zalloc(sizeof(*propdata));
88
89
1
    if (propdata == NULL)
90
0
        return NULL;
91
92
1
    propdata->lock = CRYPTO_THREAD_lock_new();
93
1
    if (propdata->lock == NULL)
94
0
        goto err;
95
96
1
    propdata->prop_names = lh_PROPERTY_STRING_new(&property_hash,
97
1
                                                  &property_cmp);
98
1
    if (propdata->prop_names == NULL)
99
0
        goto err;
100
101
1
    propdata->prop_values = lh_PROPERTY_STRING_new(&property_hash,
102
1
                                                   &property_cmp);
103
1
    if (propdata->prop_values == NULL)
104
0
        goto err;
105
106
1
    return propdata;
107
108
0
err:
109
0
    property_string_data_free(propdata);
110
0
    return NULL;
111
1
}
112
113
static const OSSL_LIB_CTX_METHOD property_string_data_method = {
114
    OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
115
    property_string_data_new,
116
    property_string_data_free,
117
};
118
119
static PROPERTY_STRING *new_property_string(const char *s,
120
                                            OSSL_PROPERTY_IDX *pidx)
121
22
{
122
22
    const size_t l = strlen(s);
123
22
    PROPERTY_STRING *ps = OPENSSL_malloc(sizeof(*ps) + l);
124
125
22
    if (ps != NULL) {
126
22
        memcpy(ps->body, s, l + 1);
127
22
        ps->s = ps->body;
128
22
        ps->idx = ++*pidx;
129
22
        if (ps->idx == 0) {
130
0
            OPENSSL_free(ps);
131
0
            return NULL;
132
0
        }
133
22
    }
134
22
    return ps;
135
22
}
136
137
static OSSL_PROPERTY_IDX ossl_property_string(CRYPTO_RWLOCK *lock,
138
                                              PROP_TABLE *t,
139
                                              OSSL_PROPERTY_IDX *pidx,
140
                                              const char *s)
141
7.59k
{
142
7.59k
    PROPERTY_STRING p, *ps, *ps_new;
143
144
7.59k
    p.s = s;
145
7.59k
    if (!CRYPTO_THREAD_read_lock(lock)) {
146
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK);
147
0
        return 0;
148
0
    }
149
7.59k
    ps = lh_PROPERTY_STRING_retrieve(t, &p);
150
7.59k
    if (ps == NULL && pidx != NULL) {
151
22
        CRYPTO_THREAD_unlock(lock);
152
22
        if (!CRYPTO_THREAD_write_lock(lock)) {
153
0
            ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
154
0
            return 0;
155
0
        }
156
22
        ps = lh_PROPERTY_STRING_retrieve(t, &p);
157
22
        if (ps == NULL && (ps_new = new_property_string(s, pidx)) != NULL) {
158
22
            lh_PROPERTY_STRING_insert(t, ps_new);
159
22
            if (lh_PROPERTY_STRING_error(t)) {
160
0
                property_free(ps_new);
161
0
                CRYPTO_THREAD_unlock(lock);
162
0
                return 0;
163
0
            }
164
22
            ps = ps_new;
165
22
        }
166
22
    }
167
7.59k
    CRYPTO_THREAD_unlock(lock);
168
7.59k
    return ps != NULL ? ps->idx : 0;
169
7.59k
}
170
171
struct find_str_st {
172
    const char *str;
173
    OSSL_PROPERTY_IDX idx;
174
};
175
176
static void find_str_fn(PROPERTY_STRING *prop, void *vfindstr)
177
88.5k
{
178
88.5k
    struct find_str_st *findstr = vfindstr;
179
180
88.5k
    if (prop->idx == findstr->idx)
181
5.53k
        findstr->str = prop->s;
182
88.5k
}
183
184
static const char *ossl_property_str(int name, OSSL_LIB_CTX *ctx,
185
                                     OSSL_PROPERTY_IDX idx)
186
5.53k
{
187
5.53k
    struct find_str_st findstr;
188
5.53k
    PROPERTY_STRING_DATA *propdata
189
5.53k
        = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX,
190
5.53k
                                &property_string_data_method);
191
192
5.53k
    if (propdata == NULL)
193
0
        return NULL;
194
195
5.53k
    findstr.str = NULL;
196
5.53k
    findstr.idx = idx;
197
198
5.53k
    if (!CRYPTO_THREAD_read_lock(propdata->lock)) {
199
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK);
200
0
        return NULL;
201
0
    }
202
5.53k
    lh_PROPERTY_STRING_doall_arg(name ? propdata->prop_names
203
5.53k
                                      : propdata->prop_values,
204
5.53k
                                 find_str_fn, &findstr);
205
5.53k
    CRYPTO_THREAD_unlock(propdata->lock);
206
207
5.53k
    return findstr.str;
208
5.53k
}
209
210
OSSL_PROPERTY_IDX ossl_property_name(OSSL_LIB_CTX *ctx, const char *s,
211
                                     int create)
212
7.38k
{
213
7.38k
    PROPERTY_STRING_DATA *propdata
214
7.38k
        = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX,
215
7.38k
                                &property_string_data_method);
216
217
7.38k
    if (propdata == NULL)
218
0
        return 0;
219
7.38k
    return ossl_property_string(propdata->lock, propdata->prop_names,
220
7.38k
                                create ? &propdata->prop_name_idx : NULL,
221
7.38k
                                s);
222
7.38k
}
223
224
const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx)
225
0
{
226
0
    return ossl_property_str(1, ctx, idx);
227
0
}
228
229
OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s,
230
                                      int create)
231
207
{
232
207
    PROPERTY_STRING_DATA *propdata
233
207
        = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX,
234
207
                                &property_string_data_method);
235
236
207
    if (propdata == NULL)
237
0
        return 0;
238
207
    return ossl_property_string(propdata->lock, propdata->prop_values,
239
207
                                create ? &propdata->prop_value_idx : NULL,
240
207
                                s);
241
207
}
242
243
const char *ossl_property_value_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx)
244
5.53k
{
245
5.53k
    return ossl_property_str(0, ctx, idx);
246
5.53k
}