]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
util: extend unhexmem() to accept secure flag
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 10 Apr 2019 08:50:27 +0000 (17:50 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 12 Apr 2019 01:10:24 +0000 (10:10 +0900)
When the flag is set, buffer is cleared on failure.
This is a continuation of 2432d09c7a7115004b16eb11bf81ffeeb32d15ad.

src/basic/hexdecoct.c
src/basic/hexdecoct.h

index 132439fd1c5c8063b959dc28879f2c957ba2e556..5e425b0231dada277d3d3b4d2947ceaee8d13123 100644 (file)
@@ -108,10 +108,12 @@ static int unhex_next(const char **p, size_t *l) {
         return r;
 }
 
-int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
+int unhexmem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_len) {
         _cleanup_free_ uint8_t *buf = NULL;
+        size_t buf_size;
         const char *x;
         uint8_t *z;
+        int r;
 
         assert(ret);
         assert(ret_len);
@@ -121,7 +123,8 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
                 l = strlen(p);
 
         /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
-        buf = malloc((l + 1) / 2 + 1);
+        buf_size = (l + 1) / 2 + 1;
+        buf = malloc(buf_size);
         if (!buf)
                 return -ENOMEM;
 
@@ -131,12 +134,16 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
                 a = unhex_next(&x, &l);
                 if (a == -EPIPE) /* End of string */
                         break;
-                if (a < 0)
-                        return a;
+                if (a < 0) {
+                        r = a;
+                        goto on_failure;
+                }
 
                 b = unhex_next(&x, &l);
-                if (b < 0)
-                        return b;
+                if (b < 0) {
+                        r = b;
+                        goto on_failure;
+                }
 
                 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
         }
@@ -147,6 +154,12 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
         *ret = TAKE_PTR(buf);
 
         return 0;
+
+on_failure:
+        if (secure)
+                explicit_bzero_safe(buf, buf_size);
+
+        return r;
 }
 
 /* https://tools.ietf.org/html/rfc4648#section-6
index fa6013ee7506090284fe1e977ff87d85e2ab1b23..dfdff1e9bb0ce0d17993c29a6921859b7dd83b5a 100644 (file)
@@ -18,7 +18,10 @@ char hexchar(int x) _const_;
 int unhexchar(char c) _const_;
 
 char *hexmem(const void *p, size_t l);
-int unhexmem(const char *p, size_t l, void **mem, size_t *len);
+int unhexmem_full(const char *p, size_t l, bool secure, void **mem, size_t *len);
+static inline int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
+        return unhexmem_full(p, l, false, mem, len);
+}
 
 char base32hexchar(int x) _const_;
 int unbase32hexchar(char c) _const_;