summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbeck <>2020-09-11 14:30:51 +0000
committerbeck <>2020-09-11 14:30:51 +0000
commit202546ef369f5ea223c1ddaac656af9dc7a41988 (patch)
tree2c361434ce2dc8d153a1fde03838e84f4274d024
parent95b779941063fc220467e951ffe4eed9469efb64 (diff)
downloadopenbsd-202546ef369f5ea223c1ddaac656af9dc7a41988.tar.gz
openbsd-202546ef369f5ea223c1ddaac656af9dc7a41988.tar.bz2
openbsd-202546ef369f5ea223c1ddaac656af9dc7a41988.zip
Add issuer cache, to be used by upcoming changes to validation code.
ok tb@ jsing@
-rw-r--r--src/lib/libcrypto/Makefile3
-rw-r--r--src/lib/libcrypto/x509/x509_issuer_cache.c167
-rw-r--r--src/lib/libcrypto/x509/x509_issuer_cache.h47
3 files changed, 216 insertions, 1 deletions
diff --git a/src/lib/libcrypto/Makefile b/src/lib/libcrypto/Makefile
index 9207b93f32..2e778a5b23 100644
--- a/src/lib/libcrypto/Makefile
+++ b/src/lib/libcrypto/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.42 2020/06/09 16:53:52 deraadt Exp $ 1# $OpenBSD: Makefile,v 1.43 2020/09/11 14:30:51 beck Exp $
2 2
3LIB= crypto 3LIB= crypto
4LIBREBUILD=y 4LIBREBUILD=y
@@ -277,6 +277,7 @@ SRCS+= x509_bcons.c x509_bitst.c x509_conf.c x509_extku.c x509_ia5.c x509_lib.c
277SRCS+= x509_prn.c x509_utl.c x509_genn.c x509_alt.c x509_skey.c x509_akey.c x509_pku.c 277SRCS+= x509_prn.c x509_utl.c x509_genn.c x509_alt.c x509_skey.c x509_akey.c x509_pku.c
278SRCS+= x509_int.c x509_enum.c x509_sxnet.c x509_cpols.c x509_crld.c x509_purp.c x509_info.c 278SRCS+= x509_int.c x509_enum.c x509_sxnet.c x509_cpols.c x509_crld.c x509_purp.c x509_info.c
279SRCS+= x509_ocsp.c x509_akeya.c x509_pmaps.c x509_pcons.c x509_ncons.c x509_pcia.c x509_pci.c 279SRCS+= x509_ocsp.c x509_akeya.c x509_pmaps.c x509_pcons.c x509_ncons.c x509_pcia.c x509_pci.c
280SRCS+= x509_issuer_cache.c
280SRCS+= pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c 281SRCS+= pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c
281 282
282.PATH: ${.CURDIR}/arch/${MACHINE_CPU} \ 283.PATH: ${.CURDIR}/arch/${MACHINE_CPU} \
diff --git a/src/lib/libcrypto/x509/x509_issuer_cache.c b/src/lib/libcrypto/x509/x509_issuer_cache.c
new file mode 100644
index 0000000000..6831c18986
--- /dev/null
+++ b/src/lib/libcrypto/x509/x509_issuer_cache.c
@@ -0,0 +1,167 @@
1/* $OpenBSD: x509_issuer_cache.c,v 1.1 2020/09/11 14:30:51 beck Exp $ */
2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* x509_issuer_cache */
19
20/*
21 * The issuer cache is a cache of parent and child x509 certificate
22 * hashes with a signature validation result.
23 *
24 * Entries should only be added to the cache with a validation result
25 * from checking the public key math that "parent" signed "child".
26 *
27 * Finding an entry in the cache gets us the result of a previously
28 * performed validation of the signature of "parent" signing for the
29 * validity of "child". It allows us to skip doing the public key math
30 * when validating a certificate chain. It does not allow us to skip
31 * any other steps of validation (times, names, key usage, etc.)
32 */
33
34#include <pthread.h>
35#include <string.h>
36
37#include "x509_issuer_cache.h"
38
39static int
40x509_issuer_cmp(struct x509_issuer *x1, struct x509_issuer *x2)
41{
42 int pcmp;
43 if ((pcmp = memcmp(x1->parent_md, x2->parent_md, EVP_MAX_MD_SIZE)) != 0)
44 return pcmp;
45 return memcmp(x1->child_md, x2->child_md, EVP_MAX_MD_SIZE);
46}
47
48static size_t x509_issuer_cache_count;
49static size_t x509_issuer_cache_max = X509_ISSUER_CACHE_MAX;
50static RB_HEAD(x509_issuer_tree, x509_issuer) x509_issuer_cache =
51 RB_INITIALIZER(&x509_issuer_cache);
52static TAILQ_HEAD(lruqueue, x509_issuer) x509_issuer_lru =
53 TAILQ_HEAD_INITIALIZER(x509_issuer_lru);
54static pthread_mutex_t x509_issuer_tree_mutex = PTHREAD_MUTEX_INITIALIZER;
55
56RB_PROTOTYPE(x509_issuer_tree, x509_issuer, entry, x509_issuer_cmp);
57RB_GENERATE(x509_issuer_tree, x509_issuer, entry, x509_issuer_cmp);
58
59/*
60 * Set the maximum number of cached entries. On additions to the cache
61 * the least recently used entries will be discarded so that the cache
62 * stays under the maximum number of entries. Setting a maximum of 0
63 * disables the cache.
64 */
65int
66x509_issuer_cache_set_max(size_t max)
67{
68 if (pthread_mutex_lock(&x509_issuer_tree_mutex) != 0)
69 return 0;
70 x509_issuer_cache_max = max;
71 (void) pthread_mutex_unlock(&x509_issuer_tree_mutex);
72
73 return 1;
74}
75
76/*
77 * Find a previous result of checking if parent signed child
78 *
79 * Returns:
80 * -1 : No entry exists in the cache. signature must be checked.
81 * 0 : The signature of parent signing child is invalid.
82 * 1 : The signature of parent signing child is valid.
83 */
84int
85x509_issuer_cache_find(unsigned char *parent_md, unsigned char *child_md)
86{
87 struct x509_issuer candidate, *found;
88 int ret = -1;
89
90 memset(&candidate, 0, sizeof(candidate));
91 candidate.parent_md = parent_md;
92 candidate.child_md = child_md;
93
94 if (x509_issuer_cache_max == 0)
95 return -1;
96
97 if (pthread_mutex_lock(&x509_issuer_tree_mutex) != 0)
98 return -1;
99 if ((found = RB_FIND(x509_issuer_tree, &x509_issuer_cache,
100 &candidate)) != NULL) {
101 TAILQ_REMOVE(&x509_issuer_lru, found, queue);
102 TAILQ_INSERT_HEAD(&x509_issuer_lru, found, queue);
103 ret = found->valid;
104 }
105 (void) pthread_mutex_unlock(&x509_issuer_tree_mutex);
106
107 return ret;
108}
109
110/*
111 * Attempt to add a validation result to the cache.
112 *
113 * valid must be:
114 * 0: The signature of parent signing child is invalid.
115 * 1: The signature of parent signing child is valid.
116 *
117 * Previously added entries for the same parent and child are *not* replaced.
118 */
119void
120x509_issuer_cache_add(unsigned char *parent_md, unsigned char *child_md,
121 int valid)
122{
123 struct x509_issuer *new;
124
125 if (x509_issuer_cache_max == 0)
126 return;
127 if (valid != 0 && valid != 1)
128 return;
129
130 if ((new = calloc(1, sizeof(struct x509_issuer))) == NULL)
131 return;
132 if ((new->parent_md = calloc(1, EVP_MAX_MD_SIZE)) == NULL)
133 goto err;
134 memcpy(new->parent_md, parent_md, EVP_MAX_MD_SIZE);
135 if ((new->child_md = calloc(1, EVP_MAX_MD_SIZE)) == NULL)
136 goto err;
137 memcpy(new->child_md, child_md, EVP_MAX_MD_SIZE);
138
139 new->valid = valid;
140
141 if (pthread_mutex_lock(&x509_issuer_tree_mutex) != 0)
142 goto err;
143 while (x509_issuer_cache_count >= x509_issuer_cache_max) {
144 struct x509_issuer *old;
145 if ((old = TAILQ_LAST(&x509_issuer_lru, lruqueue)) == NULL)
146 goto err;
147 TAILQ_REMOVE(&x509_issuer_lru, old, queue);
148 RB_REMOVE(x509_issuer_tree, &x509_issuer_cache, old);
149 free(old->parent_md);
150 free(old->child_md);
151 free(old);
152 x509_issuer_cache_count--;
153 }
154 if (RB_INSERT(x509_issuer_tree, &x509_issuer_cache, new) == NULL) {
155 TAILQ_INSERT_HEAD(&x509_issuer_lru, new, queue);
156 x509_issuer_cache_count++;
157 new = NULL;
158 }
159 err:
160 (void) pthread_mutex_unlock(&x509_issuer_tree_mutex);
161 if (new != NULL) {
162 free(new->parent_md);
163 free(new->child_md);
164 }
165 free(new);
166 return;
167}
diff --git a/src/lib/libcrypto/x509/x509_issuer_cache.h b/src/lib/libcrypto/x509/x509_issuer_cache.h
new file mode 100644
index 0000000000..6dedde75f1
--- /dev/null
+++ b/src/lib/libcrypto/x509/x509_issuer_cache.h
@@ -0,0 +1,47 @@
1/* $OpenBSD: x509_issuer_cache.h,v 1.1 2020/09/11 14:30:51 beck Exp $ */
2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* x509_issuer_cache */
19#ifndef HEADER_X509_ISSUER_CACHE_H
20#define HEADER_X509_ISSUER_CACHE_H
21
22#include <sys/tree.h>
23#include <sys/queue.h>
24
25#include <openssl/x509.h>
26
27__BEGIN_HIDDEN_DECLS
28
29struct x509_issuer {
30 RB_ENTRY(x509_issuer) entry;
31 TAILQ_ENTRY(x509_issuer) queue; /* LRU of entries */
32 /* parent_md and child_md must point to EVP_MAX_MD_SIZE of memory */
33 unsigned char *parent_md;
34 unsigned char *child_md;
35 int valid; /* Result of signature validation. */
36};
37
38#define X509_ISSUER_CACHE_MAX 40000 /* Approx 7.5 MB, entries 200 bytes */
39
40int x509_issuer_cache_set_max(size_t max);
41int x509_issuer_cache_find(unsigned char *parent_md, unsigned char *child_md);
42void x509_issuer_cache_add(unsigned char *parent_md, unsigned char *child_md,
43 int valid);
44
45__END_HIDDEN_DECLS
46
47#endif