secure.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /*! \file
3  * \brief Security related functions
4  *
5  * Copyright (c) 2017-2020 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 (posix_mode_t) (POSIX_S_IRUSR | POSIX_S_IWUSR)
42 
43 /*! \brief Size of secret (64 octets is sufficient for the SHA2 family) */
44 #define SECURE_CL_SECSIZE (size_t) 64
45 
46 
47 /* ========================================================================== */
48 /* Variables */
49 
50 /*! \brief Message prefix for security related functions */
51 #define MAIN_ERR_PREFIX "MAIN: "
52 
53 
54 /* ========================================================================== */
55 /*! \brief Remove string from memory
56  *
57  * \param[in] p Pointer to memory block
58  * \param[in] len Number of bytes to clear
59  *
60  * This function overwrites \e len bytes starting at location \e p with
61  * undefined data.
62  *
63  * \note
64  * One or both parameters are allowed to be zero. This function executes as NOP
65  * in this case.
66  *
67  * \attention
68  * This function is currently only secure if TLS support is available (because
69  * it share a cryptographic function provided by OpenSSL).
70  */
71 
72 void secure_clear_memory(char* p, size_t len)
73 {
74  if (NULL != p && len)
75  {
76 #if CFG_USE_TLS
77  /* Older versions of OpenSSL may crash if 'len' is zero */
78  OPENSSL_cleanse((void*) p, len);
79 #else /* CFG_USE_TLS */
80  /*
81  * This is insecure: There is no portable standard C90 way to do it
82  *
83  * The 'volatile' qualifier is not handled as required for this purpose by
84  * some compilers (e.g. GCC 3.x).
85  * Modern compilers with LTO support use optimization beyond object file
86  * boundaries and may remove the whole function call (if they think the
87  * overwritten memory locations are not read again).
88  *
89  * If this branch of the code is required to work as intended, the
90  * optimizer of the compiler must be disabled.
91  */
92  memset((void*) p, 42, len);
93 #endif /* CFG_USE_TLS */
94  }
95 
96  return;
97 }
98 
99 
100 /* ========================================================================== */
101 /*! \brief Remove string from memory
102  *
103  * \param[in] p Pointer to string
104  *
105  * \attention
106  * \e p must point to a \c NUL terminated string.
107  *
108  * The complete string is overwritten and then \c NUL is written to the first
109  * byte. The function therefore returns with \e p pointing to an empty string.
110  *
111  * \attention
112  * This function is currently only secure if TLS support is available (because
113  * it share a cryptographic function provided by OpenSSL).
114  */
115 
116 void secure_clear_string(char* p)
117 {
118  secure_clear_memory(p, strlen(p));
119  p[0] = 0;
120 
121  return;
122 }
123 
124 
125 /* ========================================================================== */
126 /*! \brief Generate file with new secret if CL secret file is missing
127  *
128  * \param[in] pathname Pathname string of CL secret file
129  *
130  * If \e pathname is \c NULL no operation is excecuted.
131  *
132  * \attention
133  * This function currently only works if TLS support is available (because it
134  * uses the cryptographic PRNG provided by OpenSSL).
135  * The caller must ensure, that the OpenSSL PRNG is seeded!
136  */
137 
138 void secure_cl_secret(const char* pathname)
139 {
140 #if CFG_USE_TLS
141  int rv;
142  int fd = -1;
143  char buf[SECURE_CL_SECSIZE]; /* Do not initialize buffer! */
144 
145  if(NULL != pathname)
146  {
147  rv = fu_check_file(pathname, NULL);
148  if(-1 == rv && POSIX_ENOENT == posix_errno)
149  {
150  /* CL secret file for scheme SHA256 not present */
151  printf("%s: %s%s\n", CFG_NAME, MAIN_ERR_PREFIX,
152  "Generate CL secret for scheme SHA256");
153  rv = fu_open_file(pathname, &fd, POSIX_O_WRONLY | POSIX_O_CREAT,
155  if(rv) { PRINT_ERROR("Creation of CL secret file failed"); }
156  else
157  {
158  /*
159  * Read 512 Bit (64 octets) random data from crypto PRNG
160  *
161  * The content of the buffer is mixed into the entropy pool by
162  * RAND_bytes(3). The buffer should therefore be uninitialized.
163  */
164  rv = RAND_bytes((unsigned char*) buf, (int) SECURE_CL_SECSIZE);
165  if(1 != rv)
166  {
167  /* Failed => Remove CL secret file again */
168  PRINT_ERROR("Not enough random data from PRNG");
169  fu_close_file(&fd, NULL);
170  (void) fu_unlink_file(pathname);
171  }
172  else
173  {
174  /* Write random data to CL secret file */
175  rv = fu_write_to_filedesc(fd, buf, (size_t) SECURE_CL_SECSIZE);
177  if(rv) { PRINT_ERROR("Writing to CL secret file failed"); }
178  fu_close_file(&fd, NULL);
179  }
180  }
181  }
182  }
183 #endif /* CFG_USE_TLS */
184 
185  return;
186 }
187 
188 
189 /*! @} */
190 
191 /* 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:542
secure_clear_memory
void secure_clear_memory(char *p, size_t len)
Remove string from memory.
Definition: secure.c:72
secure_clear_string
void secure_clear_string(char *p)
Remove string from memory.
Definition: secure.c:116
MAIN_ERR_PREFIX
#define MAIN_ERR_PREFIX
Message prefix for security related functions.
Definition: secure.c:51
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:138
fu_unlink_file
int fu_unlink_file(const char *pathname)
Unlink file.
Definition: fileutils.c:355
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:44
fu_close_file
void fu_close_file(int *filedesc, FILE **stream)
Close file (and potentially associated I/O stream)
Definition: fileutils.c:290
fu_check_file
int fu_check_file(const char *pathname, struct_posix_stat *state)
Check whether file exist.
Definition: fileutils.c:211
fu_open_file
int fu_open_file(const char *pathname, int *filedesc, int mode, posix_mode_t perm)
Open file.
Definition: fileutils.c:243

Generated at 2024-04-27 using  doxygen