1/*
2 * {- join("\n * ", @autowarntext) -}
3 *
4 * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
5 *
6 * Licensed under the Apache License 2.0 (the "License").  You may not use
7 * this file except in compliance with the License.  You can obtain a copy
8 * in the file LICENSE in the source distribution or at
9 * https://www.openssl.org/source/license.html
10 */
11
12{-
13use OpenSSL::stackhash qw(generate_stack_string_macros
14                          generate_stack_const_string_macros
15                          generate_stack_block_macros);
16-}
17
18#ifndef OPENSSL_SAFESTACK_H
19# define OPENSSL_SAFESTACK_H
20# pragma once
21
22# include <openssl/macros.h>
23# ifndef OPENSSL_NO_DEPRECATED_3_0
24#  define HEADER_SAFESTACK_H
25# endif
26
27# include <openssl/stack.h>
28# include <openssl/e_os2.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34# define STACK_OF(type) struct stack_st_##type
35
36/* Helper macro for internal use */
37# define SKM_DEFINE_STACK_OF_INTERNAL(t1, t2, t3) \
38    STACK_OF(t1); \
39    typedef int (*sk_##t1##_compfunc)(const t3 * const *a, const t3 *const *b); \
40    typedef void (*sk_##t1##_freefunc)(t3 *a); \
41    typedef t3 * (*sk_##t1##_copyfunc)(const t3 *a); \
42    static ossl_unused ossl_inline t2 *ossl_check_##t1##_type(t2 *ptr) \
43    { \
44        return ptr; \
45    } \
46    static ossl_unused ossl_inline const OPENSSL_STACK *ossl_check_const_##t1##_sk_type(const STACK_OF(t1) *sk) \
47    { \
48        return (const OPENSSL_STACK *)sk; \
49    } \
50    static ossl_unused ossl_inline OPENSSL_STACK *ossl_check_##t1##_sk_type(STACK_OF(t1) *sk) \
51    { \
52        return (OPENSSL_STACK *)sk; \
53    } \
54    static ossl_unused ossl_inline OPENSSL_sk_compfunc ossl_check_##t1##_compfunc_type(sk_##t1##_compfunc cmp) \
55    { \
56        return (OPENSSL_sk_compfunc)cmp; \
57    } \
58    static ossl_unused ossl_inline OPENSSL_sk_copyfunc ossl_check_##t1##_copyfunc_type(sk_##t1##_copyfunc cpy) \
59    { \
60        return (OPENSSL_sk_copyfunc)cpy; \
61    } \
62    static ossl_unused ossl_inline OPENSSL_sk_freefunc ossl_check_##t1##_freefunc_type(sk_##t1##_freefunc fr) \
63    { \
64        return (OPENSSL_sk_freefunc)fr; \
65    }
66
67# define SKM_DEFINE_STACK_OF(t1, t2, t3) \
68    STACK_OF(t1); \
69    typedef int (*sk_##t1##_compfunc)(const t3 * const *a, const t3 *const *b); \
70    typedef void (*sk_##t1##_freefunc)(t3 *a); \
71    typedef t3 * (*sk_##t1##_copyfunc)(const t3 *a); \
72    static ossl_unused ossl_inline int sk_##t1##_num(const STACK_OF(t1) *sk) \
73    { \
74        return OPENSSL_sk_num((const OPENSSL_STACK *)sk); \
75    } \
76    static ossl_unused ossl_inline t2 *sk_##t1##_value(const STACK_OF(t1) *sk, int idx) \
77    { \
78        return (t2 *)OPENSSL_sk_value((const OPENSSL_STACK *)sk, idx); \
79    } \
80    static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new(sk_##t1##_compfunc compare) \
81    { \
82        return (STACK_OF(t1) *)OPENSSL_sk_new((OPENSSL_sk_compfunc)compare); \
83    } \
84    static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_null(void) \
85    { \
86        return (STACK_OF(t1) *)OPENSSL_sk_new_null(); \
87    } \
88    static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_reserve(sk_##t1##_compfunc compare, int n) \
89    { \
90        return (STACK_OF(t1) *)OPENSSL_sk_new_reserve((OPENSSL_sk_compfunc)compare, n); \
91    } \
92    static ossl_unused ossl_inline int sk_##t1##_reserve(STACK_OF(t1) *sk, int n) \
93    { \
94        return OPENSSL_sk_reserve((OPENSSL_STACK *)sk, n); \
95    } \
96    static ossl_unused ossl_inline void sk_##t1##_free(STACK_OF(t1) *sk) \
97    { \
98        OPENSSL_sk_free((OPENSSL_STACK *)sk); \
99    } \
100    static ossl_unused ossl_inline void sk_##t1##_zero(STACK_OF(t1) *sk) \
101    { \
102        OPENSSL_sk_zero((OPENSSL_STACK *)sk); \
103    } \
104    static ossl_unused ossl_inline t2 *sk_##t1##_delete(STACK_OF(t1) *sk, int i) \
105    { \
106        return (t2 *)OPENSSL_sk_delete((OPENSSL_STACK *)sk, i); \
107    } \
108    static ossl_unused ossl_inline t2 *sk_##t1##_delete_ptr(STACK_OF(t1) *sk, t2 *ptr) \
109    { \
110        return (t2 *)OPENSSL_sk_delete_ptr((OPENSSL_STACK *)sk, \
111                                           (const void *)ptr); \
112    } \
113    static ossl_unused ossl_inline int sk_##t1##_push(STACK_OF(t1) *sk, t2 *ptr) \
114    { \
115        return OPENSSL_sk_push((OPENSSL_STACK *)sk, (const void *)ptr); \
116    } \
117    static ossl_unused ossl_inline int sk_##t1##_unshift(STACK_OF(t1) *sk, t2 *ptr) \
118    { \
119        return OPENSSL_sk_unshift((OPENSSL_STACK *)sk, (const void *)ptr); \
120    } \
121    static ossl_unused ossl_inline t2 *sk_##t1##_pop(STACK_OF(t1) *sk) \
122    { \
123        return (t2 *)OPENSSL_sk_pop((OPENSSL_STACK *)sk); \
124    } \
125    static ossl_unused ossl_inline t2 *sk_##t1##_shift(STACK_OF(t1) *sk) \
126    { \
127        return (t2 *)OPENSSL_sk_shift((OPENSSL_STACK *)sk); \
128    } \
129    static ossl_unused ossl_inline void sk_##t1##_pop_free(STACK_OF(t1) *sk, sk_##t1##_freefunc freefunc) \
130    { \
131        OPENSSL_sk_pop_free((OPENSSL_STACK *)sk, (OPENSSL_sk_freefunc)freefunc); \
132    } \
133    static ossl_unused ossl_inline int sk_##t1##_insert(STACK_OF(t1) *sk, t2 *ptr, int idx) \
134    { \
135        return OPENSSL_sk_insert((OPENSSL_STACK *)sk, (const void *)ptr, idx); \
136    } \
137    static ossl_unused ossl_inline t2 *sk_##t1##_set(STACK_OF(t1) *sk, int idx, t2 *ptr) \
138    { \
139        return (t2 *)OPENSSL_sk_set((OPENSSL_STACK *)sk, idx, (const void *)ptr); \
140    } \
141    static ossl_unused ossl_inline int sk_##t1##_find(STACK_OF(t1) *sk, t2 *ptr) \
142    { \
143        return OPENSSL_sk_find((OPENSSL_STACK *)sk, (const void *)ptr); \
144    } \
145    static ossl_unused ossl_inline int sk_##t1##_find_ex(STACK_OF(t1) *sk, t2 *ptr) \
146    { \
147        return OPENSSL_sk_find_ex((OPENSSL_STACK *)sk, (const void *)ptr); \
148    } \
149    static ossl_unused ossl_inline int sk_##t1##_find_all(STACK_OF(t1) *sk, t2 *ptr, int *pnum) \
150    { \
151        return OPENSSL_sk_find_all((OPENSSL_STACK *)sk, (const void *)ptr, pnum); \
152    } \
153    static ossl_unused ossl_inline void sk_##t1##_sort(STACK_OF(t1) *sk) \
154    { \
155        OPENSSL_sk_sort((OPENSSL_STACK *)sk); \
156    } \
157    static ossl_unused ossl_inline int sk_##t1##_is_sorted(const STACK_OF(t1) *sk) \
158    { \
159        return OPENSSL_sk_is_sorted((const OPENSSL_STACK *)sk); \
160    } \
161    static ossl_unused ossl_inline STACK_OF(t1) * sk_##t1##_dup(const STACK_OF(t1) *sk) \
162    { \
163        return (STACK_OF(t1) *)OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \
164    } \
165    static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_deep_copy(const STACK_OF(t1) *sk, \
166                                                    sk_##t1##_copyfunc copyfunc, \
167                                                    sk_##t1##_freefunc freefunc) \
168    { \
169        return (STACK_OF(t1) *)OPENSSL_sk_deep_copy((const OPENSSL_STACK *)sk, \
170                                            (OPENSSL_sk_copyfunc)copyfunc, \
171                                            (OPENSSL_sk_freefunc)freefunc); \
172    } \
173    static ossl_unused ossl_inline sk_##t1##_compfunc sk_##t1##_set_cmp_func(STACK_OF(t1) *sk, sk_##t1##_compfunc compare) \
174    { \
175        return (sk_##t1##_compfunc)OPENSSL_sk_set_cmp_func((OPENSSL_STACK *)sk, (OPENSSL_sk_compfunc)compare); \
176    }
177
178# define DEFINE_STACK_OF(t) SKM_DEFINE_STACK_OF(t, t, t)
179# define DEFINE_STACK_OF_CONST(t) SKM_DEFINE_STACK_OF(t, const t, t)
180# define DEFINE_SPECIAL_STACK_OF(t1, t2) SKM_DEFINE_STACK_OF(t1, t2, t2)
181# define DEFINE_SPECIAL_STACK_OF_CONST(t1, t2) \
182            SKM_DEFINE_STACK_OF(t1, const t2, t2)
183
184/*-
185 * Strings are special: normally an lhash entry will point to a single
186 * (somewhat) mutable object. In the case of strings:
187 *
188 * a) Instead of a single char, there is an array of chars, NUL-terminated.
189 * b) The string may have be immutable.
190 *
191 * So, they need their own declarations. Especially important for
192 * type-checking tools, such as Deputy.
193 *
194 * In practice, however, it appears to be hard to have a const
195 * string. For now, I'm settling for dealing with the fact it is a
196 * string at all.
197 */
198typedef char *OPENSSL_STRING;
199typedef const char *OPENSSL_CSTRING;
200
201/*-
202 * Confusingly, LHASH_OF(STRING) deals with char ** throughout, but
203 * STACK_OF(STRING) is really more like STACK_OF(char), only, as mentioned
204 * above, instead of a single char each entry is a NUL-terminated array of
205 * chars. So, we have to implement STRING specially for STACK_OF. This is
206 * dealt with in the autogenerated macros below.
207 */
208{-
209    generate_stack_string_macros()
210    .generate_stack_const_string_macros();
211-}
212
213#if !defined(OPENSSL_NO_DEPRECATED_3_0)
214/*
215 * This is not used by OpenSSL.  A block of bytes,  NOT nul-terminated.
216 * These should also be distinguished from "normal" stacks.
217 */
218typedef void *OPENSSL_BLOCK;
219{-
220    generate_stack_block_macros();
221-}
222#endif
223
224# ifdef  __cplusplus
225}
226# endif
227#endif
228