1.\" $OpenBSD: RSA_get_ex_new_index.3,v 1.13 2023/11/19 21:08:04 tb Exp $
2.\"
3.\" Copyright (c) 2023 Ingo Schwarze <schwarze@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.Dd $Mdocdate: November 19 2023 $
18.Dt RSA_GET_EX_NEW_INDEX 3
19.Os
20.Sh NAME
21.Nm RSA_get_ex_new_index ,
22.Nm RSA_set_ex_data ,
23.Nm RSA_get_ex_data
24.Nd add application specific data to RSA objects
25.Sh SYNOPSIS
26.In openssl/rsa.h
27.Ft int
28.Fo RSA_get_ex_new_index
29.Fa "long argl"
30.Fa "void *argp"
31.Fa "CRYPTO_EX_new *new_func"
32.Fa "CRYPTO_EX_dup *dup_func"
33.Fa "CRYPTO_EX_free *free_func"
34.Fc
35.Ft int
36.Fo RSA_set_ex_data
37.Fa "RSA *rsa"
38.Fa "int idx"
39.Fa "void *data"
40.Fc
41.Ft void *
42.Fo RSA_get_ex_data
43.Fa "RSA *rsa"
44.Fa "int idx"
45.Fc
46.Sh DESCRIPTION
47The following parent objects can have application specific data called
48.Dq ex_data
49attached to them:
50.Vt BIO , DH , DSA , EC_KEY , RSA ,
51.Vt SSL , SSL_CTX , SSL_SESSION , UI , X509 , X509_STORE ,
52and
53.Vt X509_STORE_CTX .
54.\" CRYPTO_EX_INDEX_APP and CRYPTO_EX_INDEX_UI_METHOD are unused.
55The present manual page documents the related API functions taking the
56.Vt RSA
57object type as an example.
58The functions for the other object types work in exactly the same way:
59just replace the string
60.Qq RSA
61with the name of the respective object type
62throughout the rest of this manual page.
63.Pp
64By default, each individual
65.Vt RSA
66object can store one
67.Vt void *
68pointing to application specific data.
69That specific pointer is identified by an
70.Fa idx
71argument of 0.
72.Pp
73.Fn RSA_get_ex_new_index
74reserves the next consecutive
75.Fa idx
76argument, enabling storage of one additional
77.Vt void *
78per
79.Vt RSA
80object.
81It is typically called at program startup.
82It can be called more than once if some
83.Vt RSA
84objects need to store more than two application specific pointers.
85Reserving an additional index for one parent object type, for example for
86.Vt RSA ,
87does not change the numbers of indices that can be used
88with any other parent object type.
89.Pp
90It is strongly recommended to always pass three
91.Dv NULL
92pointers for the arguments
93.Fa new_func ,
94.Fa dup_func ,
95and
96.Fa free_func .
97When following this recommendation, the arguments
98.Fa argl
99and
100.Fa argp
101are ignored; conventionally, passing 0 and
102.Dv NULL
103is recommended.
104Because using them is discouraged, the three function callback types
105are only documented in the low-level
106.Xr CRYPTO_EX_new 3
107manual page.
108.Pp
109.Fn RSA_set_ex_data
110stores the
111.Fa data
112pointer as application specific data at the given
113.Fa idx
114in the given
115.Fa rsa
116object.
117The meaning of the data pointed to is up to the application.
118The caller retains ownership of the
119.Fa data
120and is responsible for freeing it when neither the caller nor the
121.Fa rsa
122object need it any longer.
123Any other pointer that was previously stored at the same
124.Fa idx
125in the same
126.Fa rsa
127object is silently overwritten.
128Passing a
129.Dv NULL
130pointer for the
131.Fa data
132argument is valid and indicates that no application specific data
133currently needs to be stored at the given
134.Fa idx .
135.Pp
136.Fn RSA_get_ex_data
137retrieves the last pointer that was stored using
138.Fn RSA_set_ex_data
139at the given
140.Fa idx
141in the given
142.Fa rsa
143object.
144.Sh RETURN VALUES
145.Fn RSA_get_ex_new_index
146returns a new index equal to or greater than 1
147or \-1 if memory allocation fails.
148.Pp
149.Fn RSA_set_ex_data
150returns 1 on success or 0 if memory allocation fails.
151.Pp
152.Fn RSA_get_ex_data
153returns the application specific data or
154.Dv NULL
155if
156.Fa rsa
157does not contain application specific data at the given
158.Fa idx .
159.Sh ERRORS
160After failure of
161.Fn RSA_get_ex_new_index
162or
163.Fn RSA_set_ex_data ,
164the following diagnostic can be retrieved with
165.Xr ERR_get_error 3 ,
166.Xr ERR_GET_REASON 3 ,
167and
168.Xr ERR_reason_error_string 3 :
169.Bl -tag -width Ds
170.It Dv ERR_R_MALLOC_FAILURE Qq "malloc failure"
171Memory allocation failed.
172.El
173.Pp
174In a few unusual failure cases,
175.Xr ERR_get_error 3
176may report different errors caused by
177.Xr OPENSSL_init_crypto 3
178or even none at all.
179.Pp
180.Fn RSA_get_ex_data
181does not distinguish success from failure.
182Consequently, after
183.Fn RSA_get_ex_data
184returns
185.Dv NULL ,
186.Xr ERR_get_error 3
187returns 0 unless there is still an earlier error in the queue.
188.Sh SEE ALSO
189.Xr BIO_set_ex_data 3 ,
190.Xr CRYPTO_set_ex_data 3 ,
191.Xr DH_set_ex_data 3 ,
192.Xr DSA_set_ex_data 3 ,
193.Xr RSA_new 3 ,
194.Xr SSL_CTX_set_ex_data 3 ,
195.Xr SSL_SESSION_set_ex_data 3 ,
196.Xr SSL_set_ex_data 3 ,
197.Xr X509_STORE_CTX_set_ex_data 3 ,
198.Xr X509_STORE_set_ex_data 3
199.Sh HISTORY
200These functions first appeared in SSLeay 0.9.0
201and have been available since
202.Ox 2.4 .
203.Sh CAVEATS
204A relatively small minority of application programs
205attempt to change the API contract such that
206.Fn RSA_set_ex_data
207transfers ownership of the
208.Fa data
209to the
210.Fa rsa
211object.
212They do this by providing a
213.Fa free_func
214that calls
215.Xr free 3
216or higher-level
217.Fn *_free
218functions on the
219.Fa data
220and sometimes also attempt additional cleanup work as a side effect.
221.Pp
222This practice is discouraged for several reasons:
223.Bl -enum
224.It
225Due to a massive design mistake in the low-level API function
226.Xr CRYPTO_free_ex_data 3 ,
227this practice creates a possibility that
228.Xr RSA_free 3
229may fail due to memory allocation failure, consequently leaking the
230memory containing the application specific data and silently skipping
231any additional cleanup work the
232.Fa free_func
233was supposed to do, leaving the application in an undetectably
234inconsistent state.
235Arguably, leaking additional memory while trying to free some
236is most unfortunate especially when the program
237is already starved for memory.
238.It
239This practice introduces a risk of use-after-free and double-free
240bugs in case the
241.Fa rsa
242object gets destructed while a caller of
243.Fn RSA_set_ex_data
244or
245.Fn RSA_get_ex_data
246still holds a
247.Fa data
248pointer.
249No such risk exists when no
250.Fa free_func
251is installed.
252.It
253Attempting additional cleanup work in
254.Fa free_func
255is an even worse idea because
256.Fa free_func
257is unable to report any issues it might detect while doing that work.
258Instead, if any additional cleanup work is needed, it is recommended
259that the calling code takes care of that before calling
260.Xr RSA_free 3 .
261.El
262.Pp
263Even fewer application programs install a
264.Fa new_func
265that allocates memory and stores a pointer to it in the
266.Fa rsa
267object by calling
268.Xr CRYPTO_set_ex_data 3 .
269That is useless because
270.Fa new_func
271does not have access to any useful information it could store in such memory
272and because the default return value of
273.Dv NULL
274from
275.Fn RSA_get_ex_data
276is sufficient to indicate
277that no application specific data has been stored yet.
278In addition, allocating memory in
279.Fa new_func
280is also inadvisable because it introduces an additional responsibility
281for callers of
282.Fn RSA_set_ex_data
283to always call
284.Fn RSA_get_ex_data
285first, even when it is the first time the application wants to set
286application specific data in a particular
287.Fa rsa
288object, and to either modify whatever
289.Fn RSA_get_ex_data
290returns or to free it before calling
291.Fn RSA_set_ex_data .
292If that is forgotten, a memory leak results.
293.Pp
294Consequently, allocating any required memory
295is better left to the application code that calls
296.Fn RSA_set_ex_data .
297.Pp
298Installing a
299.Fa dup_func
300is often seen in combination with installing a
301.Fa free_func ,
302for obvious reasons.
303It is rarely useful because for most parent object types
304that support ex_data, including for
305.Vt RSA ,
306the library does not provide a copying API function in the first place, and
307even where copying functions exist, they tend to be fragile and error-prone.
308When a new object is needed, it is usually advisable to construct it from
309scratch whenever possible, rather than attempting a copy operation.
310.Pp
311On top of that, if
312.Fa dup_func
313fails, for example because of a memory allocation failure, the
314failure is neither reported nor detectable in any way, leaving the
315new parent object with incomplete data and potentially in an
316inconsistent state.
317.Sh BUGS
318If
319.Fn RSA_set_ex_data
320fails, recovery is very difficult.
321In particular, calling
322.Xr RSA_free 3
323on the parent
324.Fa rsa
325object right afterwards is likely to also hit a memory allocation
326failure, leaking all memory internally allocated by all earlier calls of
327.Fn RSA_set_ex_data
328on
329.Fa rsa
330rather than freeing that memory.
331In order to recover, the application program
332would have to free a sufficient amount of
333.Em other
334memory before calling
335.Xr RSA_free 3 ,
336which will rarely be feasible.
337Consequently, after a failure of
338.Fn RSA_set_ex_data ,
339terminating the program is likely the only reasonable option.
340.Pp
341If
342.Fn RSA_set_ex_data
343is called with an
344.Fa idx
345argument greater than the last one previously returned from
346.Fn RSA_get_ex_new_index ,
347it may still succeed, and though that is not guaranteed by the API,
348retrieving the
349.Fa data
350from such a bogus
351.Fa idx
352may even be possible with
353.Fn RSA_get_ex_data ,
354hiding the bug in the application program that caused passing the bogus
355.Fa idx
356to
357.Fn RSA_set_ex_data
358in the first place.
359.Pp
360If the bogus
361.Fa idx
362argument is large,
363.Fn RSA_set_ex_data
364may uselessly allocate a large amount of memory.
365Calling
366.Xr RSA_free 3
367on the parent
368.Fa rsa
369object is the only way to recover that memory.
370.Pp
371If the bogus
372.Fa idx
373argument is very large,
374.Fn RSA_set_ex_data
375is likely to cause a significant delay before eventually failing
376due to memory exhaustion.
377It is likely to return without releasing the memory already
378allocated, causing any subsequent attempt to allocate memory
379for other purposes to fail, too.
380In this situation, what was said above about failure of
381.Fn RSA_set_ex_data
382applies, so terminating the program is likely the only reasonable option.
383