util: extend unbase64mem() to accept secure flag

When the flag is set, buffer is cleared on failure.
This commit is contained in:
Yu Watanabe 2019-04-08 03:41:03 +09:00
parent 03fec54396
commit 2432d09c7a
2 changed files with 56 additions and 24 deletions

View file

@ -685,11 +685,12 @@ static int unbase64_next(const char **p, size_t *l) {
return ret; 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; _cleanup_free_ uint8_t *buf = NULL;
const char *x; const char *x;
uint8_t *z; uint8_t *z;
size_t len; size_t len;
int r;
assert(p || l == 0); assert(p || l == 0);
assert(ret); 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); a = unbase64_next(&x, &l);
if (a == -EPIPE) /* End of string */ if (a == -EPIPE) /* End of string */
break; break;
if (a < 0) if (a < 0) {
return a; r = a;
if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */ goto on_failure;
return -EINVAL; }
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); b = unbase64_next(&x, &l);
if (b < 0) if (b < 0) {
return b; r = b;
if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */ goto on_failure;
return -EINVAL; }
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); c = unbase64_next(&x, &l);
if (c < 0) if (c < 0) {
return c; r = c;
goto on_failure;
}
d = unbase64_next(&x, &l); d = unbase64_next(&x, &l);
if (d < 0) if (d < 0) {
return d; r = d;
goto on_failure;
}
if (c == INT_MAX) { /* Padding at the third character */ if (c == INT_MAX) { /* Padding at the third character */
if (d != INT_MAX) /* If the third character is padding, the fourth must be too */ if (d != INT_MAX) { /* If the third character is padding, the fourth must be too */
return -EINVAL; r = -EINVAL;
goto on_failure;
}
/* b == 00YY0000 */ /* b == 00YY0000 */
if (b & 15) if (b & 15) {
return -EINVAL; r = -EINVAL;
goto on_failure;
}
if (l > 0) /* Trailing rubbish? */ if (l > 0) { /* Trailing rubbish? */
return -ENAMETOOLONG; r = -ENAMETOOLONG;
goto on_failure;
}
*(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */ *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
break; break;
@ -749,11 +768,15 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
if (d == INT_MAX) { if (d == INT_MAX) {
/* c == 00ZZZZ00 */ /* c == 00ZZZZ00 */
if (c & 3) if (c & 3) {
return -EINVAL; r = -EINVAL;
goto on_failure;
}
if (l > 0) /* Trailing rubbish? */ if (l > 0) { /* Trailing rubbish? */
return -ENAMETOOLONG; r = -ENAMETOOLONG;
goto on_failure;
}
*(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
*(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ *(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); *ret = TAKE_PTR(buf);
return 0; return 0;
on_failure:
if (secure)
explicit_bzero_safe(buf, len);
return r;
} }
void hexdump(FILE *f, const void *p, size_t s) { void hexdump(FILE *f, const void *p, size_t s) {

View file

@ -33,6 +33,9 @@ ssize_t base64mem(const void *p, size_t l, char **out);
int base64_append(char **prefix, int plen, int base64_append(char **prefix, int plen,
const void *p, size_t l, const void *p, size_t l,
int margin, int width); 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); void hexdump(FILE *f, const void *p, size_t s);