@@ -8,11 +8,13 @@
* not contain newlines, depending on input length.
*
* @dst: Beginning of the destination buffer.
+ * @dst_max: Maximum amount of bytes to write to the destination buffer.
* @src: Beginning of the source buffer.
* @end: Sentinel for the source buffer, pointing one byte after the
* last byte to be encoded.
*
- * Returns the number of bytes written to the destination buffer.
+ * Returns the number of bytes written to the destination buffer, or
+ * an error of the output buffer is insufficient in size.
*
* _Neither_ the input or output are expected to be NULL-terminated.
*
@@ -22,19 +24,21 @@
*
* See base64_encode_buffer_bound below.
*/
-
-extern int base64_armor(char *dst, const char *src, const char *end);
+extern int base64_armor(char *dst, int dst_max, const char *src,
+ const char *end);
/**
* base64_unarmor: Perform armored base64 decoding.
*
* @dst: Beginning of the destination buffer.
+ * @dst_max: Maximum amount of bytes to write to the destination buffer.
* @src: Beginning of the source buffer
* @end: Sentinel for the source buffer, pointing one byte after the
* last byte to be encoded.
*
- * Returns the number of bytes written to the destination buffer, or
- * -EINVAL if the source buffer contains invalid bytes.
+ * Returns the number of bytes written to the destination buffer,
+ * -EINVAL if the source buffer contains invalid bytes, or -ENOSPC
+ * if the output buffer is insufficient in size.
*
* _Neither_ the input or output are expected to be NULL-terminated.
*
@@ -43,7 +47,8 @@ extern int base64_armor(char *dst, const char *src, const char *end);
*
* See base64_decode_buffer_bound below.
*/
-extern int base64_unarmor(char *dst, const char *src, const char *end);
+extern int base64_unarmor(char *dst, int dst_max, const char *src,
+ const char *end);
/*
@@ -33,7 +33,7 @@ static int decode_bits(char c)
return -EINVAL;
}
-int base64_armor(char *dst, const char *src, const char *end)
+int base64_armor(char *dst, int dst_max, const char *src, const char *end)
{
int olen = 0;
int line = 0;
@@ -42,6 +42,8 @@ int base64_armor(char *dst, const char *src, const char *end)
unsigned char a, b, c;
a = *src++;
+ if (dst_max < 4)
+ return -ENOSPC;
*dst++ = encode_bits(a >> 2);
if (src < end) {
b = *src++;
@@ -62,17 +64,22 @@ int base64_armor(char *dst, const char *src, const char *end)
}
olen += 4;
line += 4;
+ dst_max -= 4;
+
if (line == 64) {
line = 0;
+ if (dst_max < 1)
+ return -ENOSPC;
*(dst++) = '\n';
olen++;
+ dst_max--;
}
}
return olen;
}
EXPORT_SYMBOL(base64_unarmor);
-int base64_unarmor(char *dst, const char *src, const char *end)
+int base64_unarmor(char *dst, int dst_max, const char *src, const char *end)
{
int olen = 0;
@@ -92,13 +99,22 @@ int base64_unarmor(char *dst, const char *src, const char *end)
if (a < 0 || b < 0 || c < 0 || d < 0)
return -EINVAL;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = (a << 2) | (b >> 4);
+ dst_max--;
if (src[2] == '=')
return olen + 1;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = ((b & 15) << 4) | (c >> 2);
+ dst_max--;
if (src[3] == '=')
return olen + 2;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = ((c & 3) << 6) | d;
+ dst_max--;
olen += 3;
src += 4;
}
@@ -116,7 +116,7 @@ int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
buf = kmalloc(blen, GFP_NOFS);
if (!buf)
return -ENOMEM;
- blen = base64_unarmor(buf, inkey, inkey+inlen);
+ blen = base64_unarmor(buf, blen, inkey, inkey+inlen);
if (blen < 0) {
kfree(buf);
return blen;
Future use of the API can benefit from bounds checking. Signed-off-by: Dan Aloni <dan@kernelim.com> --- include/linux/base64-armor.h | 17 +++++++++++------ lib/base64-armor.c | 20 ++++++++++++++++++-- net/ceph/crypto.c | 2 +- 3 files changed, 30 insertions(+), 9 deletions(-)