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