]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
util: extend unbase64mem() to accept secure flag
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 7 Apr 2019 18:41:03 +0000 (03:41 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 7 Apr 2019 18:43:00 +0000 (03:43 +0900)
When the flag is set, buffer is cleared on failure.

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

index a5660a0ff3a23045f01176c83ae032655fdd2dff..132439fd1c5c8063b959dc28879f2c957ba2e556 100644 (file)
@@ -685,11 +685,12 @@ static int unbase64_next(const char **p, size_t *l) {
         return ret;
 }
 
-int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
+int unbase64mem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_size) {
         _cleanup_free_ uint8_t *buf = NULL;
         const char *x;
         uint8_t *z;
         size_t len;
+        int r;
 
         assert(p || l == 0);
         assert(ret);
@@ -712,36 +713,54 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
                 a = unbase64_next(&x, &l);
                 if (a == -EPIPE) /* End of string */
                         break;
-                if (a < 0)
-                        return a;
-                if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */
-                        return -EINVAL;
+                if (a < 0) {
+                        r = a;
+                        goto on_failure;
+                }
+                if (a == INT_MAX) { /* Padding is not allowed at the beginning of a 4ch block */
+                        r = -EINVAL;
+                        goto on_failure;
+                }
 
                 b = unbase64_next(&x, &l);
-                if (b < 0)
-                        return b;
-                if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */
-                        return -EINVAL;
+                if (b < 0) {
+                        r = b;
+                        goto on_failure;
+                }
+                if (b == INT_MAX) { /* Padding is not allowed at the second character of a 4ch block either */
+                        r = -EINVAL;
+                        goto on_failure;
+                }
 
                 c = unbase64_next(&x, &l);
-                if (c < 0)
-                        return c;
+                if (c < 0) {
+                        r = c;
+                        goto on_failure;
+                }
 
                 d = unbase64_next(&x, &l);
-                if (d < 0)
-                        return d;
+                if (d < 0) {
+                        r = d;
+                        goto on_failure;
+                }
 
                 if (c == INT_MAX) { /* Padding at the third character */
 
-                        if (d != INT_MAX) /* If the third character is padding, the fourth must be too */
-                                return -EINVAL;
+                        if (d != INT_MAX) { /* If the third character is padding, the fourth must be too */
+                                r = -EINVAL;
+                                goto on_failure;
+                        }
 
                         /* b == 00YY0000 */
-                        if (b & 15)
-                                return -EINVAL;
+                        if (b & 15) {
+                                r = -EINVAL;
+                                goto on_failure;
+                        }
 
-                        if (l > 0) /* Trailing rubbish? */
-                                return -ENAMETOOLONG;
+                        if (l > 0) { /* Trailing rubbish? */
+                                r = -ENAMETOOLONG;
+                                goto on_failure;
+                        }
 
                         *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
                         break;
@@ -749,11 +768,15 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
 
                 if (d == INT_MAX) {
                         /* c == 00ZZZZ00 */
-                        if (c & 3)
-                                return -EINVAL;
+                        if (c & 3) {
+                                r = -EINVAL;
+                                goto on_failure;
+                        }
 
-                        if (l > 0) /* Trailing rubbish? */
-                                return -ENAMETOOLONG;
+                        if (l > 0) { /* Trailing rubbish? */
+                                r = -ENAMETOOLONG;
+                                goto on_failure;
+                        }
 
                         *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
                         *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
@@ -771,6 +794,12 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
         *ret = TAKE_PTR(buf);
 
         return 0;
+
+on_failure:
+        if (secure)
+                explicit_bzero_safe(buf, len);
+
+        return r;
 }
 
 void hexdump(FILE *f, const void *p, size_t s) {
index 9477d16e37e725fe3f157f8965ca012af0743c0b..fa6013ee7506090284fe1e977ff87d85e2ab1b23 100644 (file)
@@ -33,6 +33,9 @@ ssize_t base64mem(const void *p, size_t l, char **out);
 int base64_append(char **prefix, int plen,
                   const void *p, size_t l,
                   int margin, int width);
-int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
+int unbase64mem_full(const char *p, size_t l, bool secure, void **mem, size_t *len);
+static inline int unbase64mem(const char *p, size_t l, void **mem, size_t *len) {
+        return unbase64mem_full(p, l, false, mem, len);
+}
 
 void hexdump(FILE *f, const void *p, size_t s);