1 /* ========================================================================== */
2 /* Copyright (c) 2018 Michael Baeuerle
3 *
4 * All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, and/or sell copies of the Software, and to permit persons
11 * to whom the Software is furnished to do so, provided that the above
12 * copyright notice(s) and this permission notice appear in all copies of
13 * the Software and that both the above copyright notice(s) and this
14 * permission notice appear in supporting documentation.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
19 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
21 * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
22 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
23 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
24 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 *
26 * Except as contained in this notice, the name of a copyright holder
27 * shall not be used in advertising or otherwise to promote the sale, use
28 * or other dealings in this Software without prior written authorization
29 * of the copyright holder.
30 */
31
32 /* C11 (if available) */
33 #define __STDC_WANT_LIB_EXT1__ 1 /*!< Request for Annex K */
34
35 /* GNU autoconf */
36 #include <config.h>
37
38 /* C99 */
39 #include <string.h>
40
41 /* Local */
42 #include "canlock.h"
43
44
45 /* ========================================================================== */
46 /*! \brief Overwrite secret data in memory
47 *
48 * \param[in] sec Pointer to secret data
49 * \param[in] sec_size Size of secret data
50 * \param[in] buf_size Size of buffer
51 *
52 * \attention
53 * The default implementation uses \c memset() and is not crytographically
54 * secure. A smart compiler may optimize this function away completely.
55 * If no better function of the OS was available, this situation is indicated
56 * with a return value of 1.
57 *
58 * \note
59 * Even if the OS in general supports explicit overwriting of memory, on a
60 * modern machine with Cache, Swap, etc. it is not possible to securely
61 * overwrite all copies that such subsystems may have created (at least it
62 * is not possible in a portable way).
63 *
64 * \return
65 * - 0 on success
66 * - 1 if only \c memset() was available
67 * - -1 on error
68 */
69
cl_clear_secret(void * sec,size_t sec_size,size_t buf_size)70 int cl_clear_secret(void *sec, size_t sec_size, size_t buf_size)
71 {
72 int res = -1;
73
74 if (NULL != sec)
75 {
76 /*
77 * C11 Annex K specifies "__STDC_LIB_EXT1__" for detection:
78 * #if defined(__STDC_LIB_EXT1__)
79 * We use the check result from autoconf instead
80 */
81 #ifdef HAVE_MEMSET_S
82 /* Standard solution using C11 Annex K */
83 res = (int) memset_s(sec, buf_size, 0, sec_size);
84 if (res)
85 {
86 /* Nonzero return value indicates a constraint violation */
87 res = -1;
88 }
89 #else /* HAVE_MEMSET_S */
90 if (sec_size <= buf_size)
91 {
92 /* OS specific functions should be called here, if available */
93 # ifdef HAVE_EXPLICIT_MEMSET
94 /* NetBSD has 'explicit_memset()' since version 7.0 */
95 explicit_memset(sec, 0, sec_size);
96 res = 0;
97 # elif defined(HAVE_EXPLICIT_BZERO)
98 /* OpenBSD has 'explicit_bzero()' since version 5.5 */
99 /* GNU libc has 'explicit_bzero()' since version 2.25 */
100 explicit_bzero(sec, sec_size);
101 res = 0;
102 # else /* HAVE_EXPLICIT_MEMSET */
103 /*
104 * There seems to be no portable way to enforce memory access in C99.
105 * But there is a chance that the optimizer is not smart enough and
106 * 'memset()' will do the job.
107 */
108 memset(sec, 0, sec_size);
109 res = 1;
110 # endif
111 }
112 #endif /* HAVE_MEMSET_S */
113 }
114
115 return (res);
116 }
117
118
119 /* EOF */
120