about summary refs log tree commit diff
path: root/shared/nm-glib-aux/nm-secret-utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/nm-glib-aux/nm-secret-utils.h')
-rw-r--r--shared/nm-glib-aux/nm-secret-utils.h130
1 files changed, 122 insertions, 8 deletions
diff --git a/shared/nm-glib-aux/nm-secret-utils.h b/shared/nm-glib-aux/nm-secret-utils.h
index 1b98b7e9..501e7520 100644
--- a/shared/nm-glib-aux/nm-secret-utils.h
+++ b/shared/nm-glib-aux/nm-secret-utils.h
@@ -18,14 +18,7 @@ char *nm_secret_strchomp (char *secret);
 
 /*****************************************************************************/
 
-static inline void
-nm_free_secret (char *secret)
-{
-	if (secret) {
-		nm_explicit_bzero (secret, strlen (secret));
-		g_free (secret);
-	}
-}
+void nm_free_secret (char *secret);
 
 NM_AUTO_DEFINE_FCN0 (char *, _nm_auto_free_secret, nm_free_secret)
 /**
@@ -159,4 +152,125 @@ GBytes *nm_secret_buf_to_gbytes_take (NMSecretBuf *secret, gssize actual_len);
 
 gboolean nm_utils_memeqzero_secret (gconstpointer data, gsize length);
 
+/*****************************************************************************/
+
+/**
+ * nm_secret_mem_realloc:
+ * @m_old: the current buffer of length @cur_len.
+ * @do_bzero_mem: if %TRUE, bzero the old buffer
+ * @cur_len: the current buffer length of @m_old. It is necessary for bzero.
+ * @new_len: the desired new length
+ *
+ * If @do_bzero_mem is false, this is like g_realloc().
+ * Otherwise, this will allocate a new buffer of the desired size, copy over the
+ * old data, and bzero the old buffer before freeing it. As such, it also behaves
+ * similar to g_realloc(), with the overhead of nm_explicit_bzero() and using
+ * malloc/free intead of realloc().
+ *
+ * Returns: the new allocated buffer. Think of it behaving like g_realloc().
+ */
+static inline gpointer
+nm_secret_mem_realloc (gpointer m_old, gboolean do_bzero_mem, gsize cur_len, gsize new_len)
+{
+	gpointer m_new;
+
+	nm_assert (m_old || cur_len == 0);
+
+	if (   do_bzero_mem
+	    && G_LIKELY (cur_len > 0)) {
+		m_new = g_malloc (new_len);
+		if (G_LIKELY (new_len > 0))
+			memcpy (m_new, m_old, NM_MIN (cur_len, new_len));
+		nm_explicit_bzero (m_old, cur_len);
+		g_free (m_old);
+	} else
+		m_new = g_realloc (m_old, new_len);
+
+	return m_new;
+}
+
+/**
+ * nm_secret_mem_try_realloc:
+ * @m_old: the current buffer of length @cur_len.
+ * @do_bzero_mem: if %TRUE, bzero the old buffer
+ * @cur_len: the current buffer length of @m_old. It is necessary for bzero.
+ * @new_len: the desired new length
+ *
+ * If @do_bzero_mem is false, this is like g_try_realloc().
+ * Otherwise, this will try to allocate a new buffer of the desired size, copy over the
+ * old data, and bzero the old buffer before freeing it. As such, it also behaves
+ * similar to g_try_realloc(), with the overhead of nm_explicit_bzero() and using
+ * malloc/free intead of realloc().
+ *
+ * Returns: the new allocated buffer or NULL. Think of it behaving like g_try_realloc().
+ */
+static inline gpointer
+nm_secret_mem_try_realloc (gpointer m_old, gboolean do_bzero_mem, gsize cur_len, gsize new_len)
+{
+	gpointer m_new;
+
+	nm_assert (m_old || cur_len == 0);
+
+	if (   do_bzero_mem
+	    && G_LIKELY (cur_len > 0)) {
+		if (G_UNLIKELY (new_len == 0))
+			m_new = NULL;
+		else {
+			m_new = g_try_malloc (new_len);
+			if (!m_new)
+				return NULL;
+			memcpy (m_new, m_old, NM_MIN (cur_len, new_len));
+		}
+		nm_explicit_bzero (m_old, cur_len);
+		g_free (m_old);
+		return m_new;
+	}
+
+	return g_try_realloc (m_old, new_len);
+}
+
+/**
+ * nm_secret_mem_try_realloc_take:
+ * @m_old: the current buffer of length @cur_len.
+ * @do_bzero_mem: if %TRUE, bzero the old buffer
+ * @cur_len: the current buffer length of @m_old. It is necessary for bzero.
+ * @new_len: the desired new length
+ *
+ * This works like nm_secret_mem_try_realloc(), which is not unlike g_try_realloc().
+ * The difference is, if we fail to allocate a new buffer, then @m_old will be
+ * freed (and possibly cleared). This differs from plain realloc(), where the
+ * old buffer is unchanged if the operation fails.
+ *
+ * Returns: the new allocated buffer or NULL. Think of it behaving like g_try_realloc()
+ *   but it will always free @m_old.
+ */
+static inline gpointer
+nm_secret_mem_try_realloc_take (gpointer m_old, gboolean do_bzero_mem, gsize cur_len, gsize new_len)
+{
+	gpointer m_new;
+
+	nm_assert (m_old || cur_len == 0);
+
+	if (   do_bzero_mem
+	    && G_LIKELY (cur_len > 0)) {
+		if (G_UNLIKELY (new_len == 0))
+			m_new = NULL;
+		else {
+			m_new = g_try_malloc (new_len);
+			if (G_LIKELY (m_new))
+				memcpy (m_new, m_old, NM_MIN (cur_len, new_len));
+		}
+		nm_explicit_bzero (m_old, cur_len);
+		g_free (m_old);
+		return m_new;
+	}
+
+	m_new = g_try_realloc (m_old, new_len);
+	if (G_UNLIKELY (!m_new && new_len > 0))
+		g_free (m_old);
+	return m_new;
+}
+
+/*****************************************************************************/
+
 #endif /* __NM_SECRET_UTILS_H__ */