secure.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /*! \file
3  * \brief Security related functions
4  *
5  * Copyright (c) 2017-2024 by the developers. See the LICENSE file for details.
6  * If nothing else is specified, functions return zero to indicate success
7  * and a negative value to indicate an error.
8  *
9  * Using a separate source file for this make it easier to use different
10  * compiler flags. It will also make it harder for optimizers to break the
11  * intended functionality of the functions in this file.
12  */
13 
14 
15 /* ========================================================================== */
16 /* Include headers */
17 
18 #include "posix.h" /* Include this first because of feature test macros */
19 
20 #include "config.h"
21 
22 #if CFG_USE_TLS /* This requires data from "config.h" */
23 # include <openssl/crypto.h>
24 # include <openssl/rand.h>
25 #endif /* CFG_USE_TLS */
26 #include <string.h>
27 #include "fileutils.h"
28 #include "main.h"
29 #include "secure.h"
30 
31 
32 /* ========================================================================== */
33 /*! \addtogroup MAIN */
34 /*! @{ */
35 
36 
37 /* ========================================================================== */
38 /* Constants */
39 
40 /*! \brief Permissions for Cancel-Lock secret file */
41 #define SECURE_CL_PERM \
42  (api_posix_mode_t) (API_POSIX_S_IRUSR | API_POSIX_S_IWUSR)
43 
44 /*! \brief Size of secret (64 octets is sufficient for the SHA2 family) */
45 #define SECURE_CL_SECSIZE (size_t) 64
46 
47 
48 /* ========================================================================== */
49 /* Variables */
50 
51 /*! \brief Message prefix for security related functions */
52 #define MAIN_ERR_PREFIX "MAIN: "
53 
54 
55 /* ========================================================================== */
56 /*! \brief Remove string from memory
57  *
58  * \param[in] p Pointer to memory block
59  * \param[in] len Number of bytes to clear
60  *
61  * This function overwrites \e len bytes starting at location \e p with
62  * undefined data.
63  *
64  * \note
65  * One or both parameters are allowed to be zero. This function executes as NOP
66  * in this case.
67  *
68  * \attention
69  * This function is currently only secure if TLS support is available (because
70  * it share a cryptographic function provided by OpenSSL).
71  */
72 
73 void secure_clear_memory(char* p, size_t len)
74 {
75  if (NULL != p && len)
76  {
77 #if CFG_USE_TLS
78  /* Older versions of OpenSSL may crash if 'len' is zero */
79  OPENSSL_cleanse((void*) p, len);
80 #else /* CFG_USE_TLS */
81  /*
82  * This is insecure: There is no portable standard C90 way to do it
83  *
84  * The 'volatile' qualifier is not handled as required for this purpose by
85  * some compilers (e.g. GCC 3.x).
86  * Modern compilers with LTO support use optimization beyond object file
87  * boundaries and may remove the whole function call (if they think the
88  * overwritten memory locations are not read again).
89  *
90  * If this branch of the code is required to work as intended, the
91  * optimizer of the compiler must be disabled.
92  */
93  memset((void*) p, 42, len);
94 #endif /* CFG_USE_TLS */
95  }
96 
97  return;
98 }
99 
100 
101 /* ========================================================================== */
102 /*! \brief Remove string from memory
103  *
104  * \param[in] p Pointer to string
105  *
106  * \attention
107  * \e p must point to a \c NUL terminated string.
108  *
109  * The complete string is overwritten and then \c NUL is written to the first
110  * byte. The function therefore returns with \e p pointing to an empty string.
111  *
112  * \attention
113  * This function is currently only secure if TLS support is available (because
114  * it share a cryptographic function provided by OpenSSL).
115  */
116 
117 void secure_clear_string(char* p)
118 {
119  secure_clear_memory(p, strlen(p));
120  p[0] = 0;
121 
122  return;
123 }
124 
125 
126 /* ========================================================================== */
127 /*! \brief Generate file with new secret if CL secret file is missing
128  *
129  * \param[in] pathname Pathname string of CL secret file
130  *
131  * If \e pathname is \c NULL no operation is excecuted.
132  *
133  * \attention
134  * This function currently only works if TLS support is available (because it
135  * uses the cryptographic PRNG provided by OpenSSL).
136  * The caller must ensure, that the OpenSSL PRNG is seeded!
137  */
138 
139 void secure_cl_secret(const char* pathname)
140 {
141 #if CFG_USE_TLS
142  int rv;
143  int fd = -1;
144  char buf[SECURE_CL_SECSIZE]; /* Do not initialize buffer! */
145 
146  if(NULL != pathname)
147  {
148  rv = fu_check_file(pathname, NULL);
149  if(-1 == rv && API_POSIX_ENOENT == api_posix_errno)
150  {
151  /* CL secret file for scheme SHA256 not present */
152  printf("%s: %s%s\n", CFG_NAME, MAIN_ERR_PREFIX,
153  "Generate CL secret for scheme SHA256");
154  rv = fu_open_file(pathname, &fd,
155  API_POSIX_O_WRONLY | API_POSIX_O_CREAT,
157  if(rv) { PRINT_ERROR("Creation of CL secret file failed"); }
158  else
159  {
160  /*
161  * Read 512 Bit (64 octets) random data from crypto PRNG
162  *
163  * The content of the buffer is mixed into the entropy pool by
164  * RAND_bytes(3). The buffer should therefore be uninitialized.
165  */
166  rv = RAND_bytes((unsigned char*) buf, (int) SECURE_CL_SECSIZE);
167  if(1 != rv)
168  {
169  /* Failed => Remove CL secret file again */
170  PRINT_ERROR("Not enough random data from PRNG");
171  fu_close_file(&fd, NULL);
172  (void) fu_unlink_file(pathname);
173  }
174  else
175  {
176  /* Write random data to CL secret file */
177  rv = fu_write_to_filedesc(fd, buf, (size_t) SECURE_CL_SECSIZE);
179  if(rv) { PRINT_ERROR("Writing to CL secret file failed"); }
180  fu_close_file(&fd, NULL);
181  }
182  }
183  }
184  }
185 #endif /* CFG_USE_TLS */
186 
187  return;
188 }
189 
190 
191 /*! @} */
192 
193 /* EOF */
fu_write_to_filedesc
int fu_write_to_filedesc(int filedesc, const char *buffer, size_t len)
Write data block to filedescriptor.
Definition: fileutils.c:552
secure_clear_memory
void secure_clear_memory(char *p, size_t len)
Remove string from memory.
Definition: secure.c:73
secure_clear_string
void secure_clear_string(char *p)
Remove string from memory.
Definition: secure.c:117
MAIN_ERR_PREFIX
#define MAIN_ERR_PREFIX
Message prefix for security related functions.
Definition: secure.c:52
SECURE_CL_PERM
#define SECURE_CL_PERM
Permissions for Cancel-Lock secret file.
Definition: secure.c:41
secure_cl_secret
void secure_cl_secret(const char *pathname)
Generate file with new secret if CL secret file is missing.
Definition: secure.c:139
fu_check_file
int fu_check_file(const char *pathname, api_posix_struct_stat *state)
Check whether file exist.
Definition: fileutils.c:214
fu_unlink_file
int fu_unlink_file(const char *pathname)
Unlink file.
Definition: fileutils.c:362
PRINT_ERROR
#define PRINT_ERROR(s)
Prepend module prefix and print error message.
Definition: main.h:19
SECURE_CL_SECSIZE
#define SECURE_CL_SECSIZE
Size of secret (64 octets is sufficient for the SHA2 family)
Definition: secure.c:45
fu_close_file
void fu_close_file(int *filedesc, FILE **stream)
Close file (and potentially associated I/O stream)
Definition: fileutils.c:297
fu_open_file
int fu_open_file(const char *pathname, int *filedesc, int mode, api_posix_mode_t perm)
Open file.
Definition: fileutils.c:246

Generated at 2026-01-27 using  doxygen