summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authortb <>2024-01-13 11:08:39 +0000
committertb <>2024-01-13 11:08:39 +0000
commit9fffb87f5d35d0387d2fef05868f79d200d8a912 (patch)
treef1a62b5297113e91a818c32f3ecb135d9a98c389 /src/lib
parent455bb26ef6b3e1e6c272effb3d99a0c59a1300d8 (diff)
downloadopenbsd-9fffb87f5d35d0387d2fef05868f79d200d8a912.tar.gz
openbsd-9fffb87f5d35d0387d2fef05868f79d200d8a912.tar.bz2
openbsd-9fffb87f5d35d0387d2fef05868f79d200d8a912.zip
Reimplement {EVP_CIPHER,EVP_MD,OBJ_NAME}_do_all{,_sorted}(3)
This implements the do_all API by simple loops over the tables of digests and ciphers. Since some ciphers are only available on some platforms, we need to skip them if necessary. We use loops in each of the functions rather the convoluted way of reducing some of the loops to others. Since the tables are sorted, as ensured by regress, both do_all() and do_all_sorted() walk the lists in order. In particular, we no longer need to allocate to be able to sort hash tables by name on the fly in a void function that may end up doing nothing because allocation failed. We still need to do an unchecked OPENSSL_init_crypto() call. But that's what prayer and clean living are there for (as beck put it). The OBJ_NAME API is completely misnamed. It has little to do with objects and a lot to do with EVP. Therefore we implement what will remain from its saner replacement in the evp directory, i.e., evp_names.c. ok jsing
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/evp/evp_names.c162
-rw-r--r--src/lib/libcrypto/evp/names.c93
-rw-r--r--src/lib/libcrypto/objects/o_names.c81
3 files changed, 161 insertions, 175 deletions
diff --git a/src/lib/libcrypto/evp/evp_names.c b/src/lib/libcrypto/evp/evp_names.c
index fbd84711f5..b5d3b95b45 100644
--- a/src/lib/libcrypto/evp/evp_names.c
+++ b/src/lib/libcrypto/evp/evp_names.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: evp_names.c,v 1.2 2024/01/13 11:00:09 tb Exp $ */ 1/* $OpenBSD: evp_names.c,v 1.3 2024/01/13 11:08:39 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2023 Theo Buehler <tb@openbsd.org> 3 * Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
4 * 4 *
@@ -41,7 +41,7 @@ struct digest_name {
41 * regress/lib/libcrypto/evp/evp_test.c checks that. 41 * regress/lib/libcrypto/evp/evp_test.c checks that.
42 */ 42 */
43 43
44const struct cipher_name cipher_names[] = { 44static const struct cipher_name cipher_names[] = {
45#ifndef OPENSSL_NO_AES 45#ifndef OPENSSL_NO_AES
46 { 46 {
47 .name = SN_aes_128_cbc, 47 .name = SN_aes_128_cbc,
@@ -1099,7 +1099,7 @@ const struct cipher_name cipher_names[] = {
1099 * regresss/lib/libcrypto/evp/evp_test.c checks that. 1099 * regresss/lib/libcrypto/evp/evp_test.c checks that.
1100 */ 1100 */
1101 1101
1102const struct digest_name digest_names[] = { 1102static const struct digest_name digest_names[] = {
1103#ifndef OPENSSL_NO_GOST 1103#ifndef OPENSSL_NO_GOST
1104 { 1104 {
1105 .name = LN_id_Gost28147_89_MAC, 1105 .name = LN_id_Gost28147_89_MAC,
@@ -1559,3 +1559,159 @@ const struct digest_name digest_names[] = {
1559}; 1559};
1560 1560
1561#define N_DIGEST_NAMES (sizeof(digest_names) / sizeof(digest_names[0])) 1561#define N_DIGEST_NAMES (sizeof(digest_names) / sizeof(digest_names[0]))
1562
1563void
1564EVP_CIPHER_do_all_sorted(void (*fn)(const EVP_CIPHER *, const char *,
1565 const char *, void *), void *arg)
1566{
1567 size_t i;
1568
1569 /* Prayer and clean living lets you ignore errors, OpenSSL style. */
1570 (void)OPENSSL_init_crypto(0, NULL);
1571
1572 for (i = 0; i < N_CIPHER_NAMES; i++) {
1573 const struct cipher_name *cipher = &cipher_names[i];
1574 const EVP_CIPHER *evp_cipher;
1575
1576 if ((evp_cipher = cipher->cipher()) == NULL)
1577 continue;
1578
1579 if (cipher->alias != NULL)
1580 fn(NULL, cipher->name, cipher->alias, arg);
1581 else
1582 fn(evp_cipher, cipher->name, NULL, arg);
1583 }
1584}
1585
1586void
1587EVP_CIPHER_do_all(void (*fn)(const EVP_CIPHER *, const char *, const char *,
1588 void *), void *arg)
1589{
1590 EVP_CIPHER_do_all_sorted(fn, arg);
1591}
1592
1593void
1594EVP_MD_do_all_sorted(void (*fn)(const EVP_MD *, const char *, const char *,
1595 void *), void *arg)
1596{
1597 size_t i;
1598
1599 /* Prayer and clean living lets you ignore errors, OpenSSL style. */
1600 (void)OPENSSL_init_crypto(0, NULL);
1601
1602 for (i = 0; i < N_DIGEST_NAMES; i++) {
1603 const struct digest_name *digest = &digest_names[i];
1604 const EVP_MD *evp_md;
1605
1606 if ((evp_md = digest->digest()) == NULL)
1607 continue;
1608
1609 if (digest->alias != NULL)
1610 fn(NULL, digest->name, digest->alias, arg);
1611 else
1612 fn(evp_md, digest->name, NULL, arg);
1613 }
1614}
1615
1616void
1617EVP_MD_do_all(void (*fn)(const EVP_MD *, const char *, const char *, void *),
1618 void *arg)
1619{
1620 EVP_MD_do_all_sorted(fn, arg);
1621}
1622
1623/*
1624 * The OBJ_NAME API is completely misnamed. It has little to do with objects
1625 * and a lot to do with EVP. Therefore we implement a saner replacement for
1626 * the part of the old madness that we need to keep in the evp directory.
1627 */
1628
1629static int
1630OBJ_NAME_from_cipher_name(OBJ_NAME *obj_name, const struct cipher_name *cipher)
1631{
1632 const EVP_CIPHER *evp_cipher;
1633
1634 if ((evp_cipher = cipher->cipher()) == NULL)
1635 return 0;
1636
1637 obj_name->type = OBJ_NAME_TYPE_CIPHER_METH;
1638 obj_name->name = cipher->name;
1639 if (cipher->alias != NULL) {
1640 obj_name->alias = OBJ_NAME_ALIAS;
1641 obj_name->data = cipher->alias;
1642 } else {
1643 obj_name->alias = 0;
1644 obj_name->data = (const char *)evp_cipher;
1645 }
1646
1647 return 1;
1648}
1649
1650static void
1651OBJ_NAME_do_all_ciphers(void (*fn)(const OBJ_NAME *, void *), void *arg)
1652{
1653 size_t i;
1654
1655 for (i = 0; i < N_CIPHER_NAMES; i++) {
1656 const struct cipher_name *cipher = &cipher_names[i];
1657 OBJ_NAME name;
1658
1659 if (OBJ_NAME_from_cipher_name(&name, cipher))
1660 fn(&name, arg);
1661 }
1662}
1663
1664static int
1665OBJ_NAME_from_digest_name(OBJ_NAME *obj_name, const struct digest_name *digest)
1666{
1667 const EVP_MD *evp_md;
1668
1669 if ((evp_md = digest->digest()) == NULL)
1670 return 0;
1671
1672 obj_name->type = OBJ_NAME_TYPE_MD_METH;
1673 obj_name->name = digest->name;
1674 if (digest->alias != NULL) {
1675 obj_name->alias = OBJ_NAME_ALIAS;
1676 obj_name->data = digest->alias;
1677 } else {
1678 obj_name->alias = 0;
1679 obj_name->data = (const char *)evp_md;
1680 }
1681
1682 return 1;
1683}
1684
1685static void
1686OBJ_NAME_do_all_digests(void (*fn)(const OBJ_NAME *, void *), void *arg)
1687{
1688 size_t i;
1689
1690 for (i = 0; i < N_DIGEST_NAMES; i++) {
1691 const struct digest_name *digest = &digest_names[i];
1692 OBJ_NAME name;
1693
1694 if (OBJ_NAME_from_digest_name(&name, digest))
1695 fn(&name, arg);
1696 }
1697}
1698
1699void
1700OBJ_NAME_do_all_sorted(int type, void (*fn)(const OBJ_NAME *, void *), void *arg)
1701{
1702 /* Prayer and clean living lets you ignore errors, OpenSSL style. */
1703 (void)OPENSSL_init_crypto(0, NULL);
1704
1705 if (type == OBJ_NAME_TYPE_CIPHER_METH)
1706 OBJ_NAME_do_all_ciphers(fn, arg);
1707 if (type == OBJ_NAME_TYPE_MD_METH)
1708 OBJ_NAME_do_all_digests(fn, arg);
1709}
1710LCRYPTO_ALIAS(OBJ_NAME_do_all_sorted);
1711
1712void
1713OBJ_NAME_do_all(int type, void (*fn)(const OBJ_NAME *, void *), void *arg)
1714{
1715 OBJ_NAME_do_all_sorted(type, fn, arg);
1716}
1717LCRYPTO_ALIAS(OBJ_NAME_do_all);
diff --git a/src/lib/libcrypto/evp/names.c b/src/lib/libcrypto/evp/names.c
index a96301ed56..7f5b455088 100644
--- a/src/lib/libcrypto/evp/names.c
+++ b/src/lib/libcrypto/evp/names.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: names.c,v 1.22 2023/12/15 14:22:10 tb Exp $ */ 1/* $OpenBSD: names.c,v 1.23 2024/01/13 11:08:39 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -146,94 +146,3 @@ EVP_cleanup(void)
146 OBJ_cleanup(); 146 OBJ_cleanup();
147 } 147 }
148} 148}
149
150struct doall_cipher {
151 void *arg;
152 void (*fn)(const EVP_CIPHER *ciph, const char *from, const char *to,
153 void *arg);
154};
155
156static void
157do_all_cipher_fn(const OBJ_NAME *nm, void *arg)
158{
159 struct doall_cipher *dc = arg;
160
161 if (nm->alias)
162 dc->fn(NULL, nm->name, nm->data, dc->arg);
163 else
164 dc->fn((const EVP_CIPHER *)nm->data, nm->name, NULL, dc->arg);
165}
166
167void
168EVP_CIPHER_do_all(void (*fn)(const EVP_CIPHER *ciph, const char *from,
169 const char *to, void *x), void *arg)
170{
171 struct doall_cipher dc;
172
173 /* Prayer and clean living lets you ignore errors, OpenSSL style */
174 (void) OPENSSL_init_crypto(0, NULL);
175
176 dc.fn = fn;
177 dc.arg = arg;
178 OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc);
179}
180
181void
182EVP_CIPHER_do_all_sorted(void (*fn)(const EVP_CIPHER *ciph, const char *from,
183 const char *to, void *x), void *arg)
184{
185 struct doall_cipher dc;
186
187 /* Prayer and clean living lets you ignore errors, OpenSSL style */
188 (void) OPENSSL_init_crypto(0, NULL);
189
190 dc.fn = fn;
191 dc.arg = arg;
192 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
193 do_all_cipher_fn, &dc);
194}
195
196struct doall_md {
197 void *arg;
198 void (*fn)(const EVP_MD *ciph, const char *from, const char *to,
199 void *arg);
200};
201
202static void
203do_all_md_fn(const OBJ_NAME *nm, void *arg)
204{
205 struct doall_md *dc = arg;
206
207 if (nm->alias)
208 dc->fn(NULL, nm->name, nm->data, dc->arg);
209 else
210 dc->fn((const EVP_MD *)nm->data, nm->name, NULL, dc->arg);
211}
212
213void
214EVP_MD_do_all(void (*fn)(const EVP_MD *md, const char *from, const char *to,
215 void *x), void *arg)
216{
217 struct doall_md dc;
218
219 /* Prayer and clean living lets you ignore errors, OpenSSL style */
220 (void) OPENSSL_init_crypto(0, NULL);
221
222 dc.fn = fn;
223 dc.arg = arg;
224 OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
225}
226
227void
228EVP_MD_do_all_sorted(void (*fn)(const EVP_MD *md,
229 const char *from, const char *to, void *x), void *arg)
230{
231 struct doall_md dc;
232
233 /* Prayer and clean living lets you ignore errors, OpenSSL style */
234 (void) OPENSSL_init_crypto(0, NULL);
235
236 dc.fn = fn;
237 dc.arg = arg;
238 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
239}
diff --git a/src/lib/libcrypto/objects/o_names.c b/src/lib/libcrypto/objects/o_names.c
index 48b95d6767..1007c5e23a 100644
--- a/src/lib/libcrypto/objects/o_names.c
+++ b/src/lib/libcrypto/objects/o_names.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: o_names.c,v 1.24 2023/07/08 12:27:51 beck Exp $ */ 1/* $OpenBSD: o_names.c,v 1.25 2024/01/13 11:08:39 tb Exp $ */
2#include <stdio.h> 2#include <stdio.h>
3#include <stdlib.h> 3#include <stdlib.h>
4#include <string.h> 4#include <string.h>
@@ -240,85 +240,6 @@ OBJ_NAME_remove(const char *name, int type)
240} 240}
241LCRYPTO_ALIAS(OBJ_NAME_remove); 241LCRYPTO_ALIAS(OBJ_NAME_remove);
242 242
243struct doall {
244 int type;
245 void (*fn)(const OBJ_NAME *, void *arg);
246 void *arg;
247};
248
249static void
250do_all_fn_doall_arg(const OBJ_NAME *name, struct doall *d)
251{
252 if (name->type == d->type)
253 d->fn(name, d->arg);
254}
255
256static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME, struct doall)
257
258void
259OBJ_NAME_do_all(int type, void (*fn)(const OBJ_NAME *, void *arg), void *arg)
260{
261 struct doall d;
262
263 d.type = type;
264 d.fn = fn;
265 d.arg = arg;
266
267 lh_OBJ_NAME_doall_arg(names_lh, LHASH_DOALL_ARG_FN(do_all_fn),
268 struct doall, &d);
269}
270LCRYPTO_ALIAS(OBJ_NAME_do_all);
271
272struct doall_sorted {
273 int type;
274 int n;
275 const OBJ_NAME **names;
276};
277
278static void
279do_all_sorted_fn(const OBJ_NAME *name, void *d_)
280{
281 struct doall_sorted *d = d_;
282
283 if (name->type != d->type)
284 return;
285
286 d->names[d->n++] = name;
287}
288
289static int
290do_all_sorted_cmp(const void *n1_, const void *n2_)
291{
292 const OBJ_NAME * const *n1 = n1_;
293 const OBJ_NAME * const *n2 = n2_;
294
295 return strcmp((*n1)->name, (*n2)->name);
296}
297
298void
299OBJ_NAME_do_all_sorted(int type, void (*fn)(const OBJ_NAME *, void *arg),
300 void *arg)
301{
302 struct doall_sorted d;
303 int n;
304
305 d.type = type;
306 d.names = reallocarray(NULL, lh_OBJ_NAME_num_items(names_lh),
307 sizeof *d.names);
308 d.n = 0;
309 if (d.names != NULL) {
310 OBJ_NAME_do_all(type, do_all_sorted_fn, &d);
311
312 qsort((void *)d.names, d.n, sizeof *d.names, do_all_sorted_cmp);
313
314 for (n = 0; n < d.n; ++n)
315 fn(d.names[n], arg);
316
317 free(d.names);
318 }
319}
320LCRYPTO_ALIAS(OBJ_NAME_do_all_sorted);
321
322static int free_type; 243static int free_type;
323 244
324static void 245static void