fscrypt: replace local base64url helpers with lib/base64
Replace the base64url encoding and decoding functions in fscrypt with the generic base64_encode() and base64_decode() helpers from lib/base64. This removes the custom implementation in fscrypt, reduces code duplication, and relies on the shared Base64 implementation in lib. The helpers preserve RFC 4648-compliant URL-safe Base64 encoding without padding, so there are no functional changes. This change also improves performance: encoding is about 2.7x faster and decoding achieves 43-52x speedups compared to the previous implementation. Link: https://lkml.kernel.org/r/20251114060221.89734-1-409411716@gms.tku.edu.tw Reviewed-by: Kuan-Wei Chiu <visitorckw@gmail.com> Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Cc: Christoph Hellwig <hch@lst.de> Cc: David Laight <david.laight.linux@gmail.com> Cc: Eric Biggers <ebiggers@kernel.org> Cc: Ilya Dryomov <idryomov@gmail.com> Cc: Jaegeuk Kim <jaegeuk@kernel.org> Cc: Jens Axboe <axboe@kernel.dk> Cc: Keith Busch <kbusch@kernel.org> Cc: Sagi Grimberg <sagi@grimberg.me> Cc: "Theodore Y. Ts'o" <tytso@mit.edu> Cc: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com> Cc: Xiubo Li <xiubli@redhat.com> Cc: Yu-Sheng Huang <home7438072@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>pull/1354/merge
parent
8b365c4f5b
commit
7794510e20
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/base64.h>
|
||||
|
||||
#include "fscrypt_private.h"
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ struct fscrypt_nokey_name {
|
|||
|
||||
/* Encoded size of max-size no-key name */
|
||||
#define FSCRYPT_NOKEY_NAME_MAX_ENCODED \
|
||||
FSCRYPT_BASE64URL_CHARS(FSCRYPT_NOKEY_NAME_MAX)
|
||||
BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX)
|
||||
|
||||
static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
|
||||
{
|
||||
|
|
@ -162,84 +163,6 @@ static int fname_decrypt(const struct inode *inode,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char base64url_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
||||
#define FSCRYPT_BASE64URL_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3)
|
||||
|
||||
/**
|
||||
* fscrypt_base64url_encode() - base64url-encode some binary data
|
||||
* @src: the binary data to encode
|
||||
* @srclen: the length of @src in bytes
|
||||
* @dst: (output) the base64url-encoded string. Not NUL-terminated.
|
||||
*
|
||||
* Encodes data using base64url encoding, i.e. the "Base 64 Encoding with URL
|
||||
* and Filename Safe Alphabet" specified by RFC 4648. '='-padding isn't used,
|
||||
* as it's unneeded and not required by the RFC. base64url is used instead of
|
||||
* base64 to avoid the '/' character, which isn't allowed in filenames.
|
||||
*
|
||||
* Return: the length of the resulting base64url-encoded string in bytes.
|
||||
* This will be equal to FSCRYPT_BASE64URL_CHARS(srclen).
|
||||
*/
|
||||
static int fscrypt_base64url_encode(const u8 *src, int srclen, char *dst)
|
||||
{
|
||||
u32 ac = 0;
|
||||
int bits = 0;
|
||||
int i;
|
||||
char *cp = dst;
|
||||
|
||||
for (i = 0; i < srclen; i++) {
|
||||
ac = (ac << 8) | src[i];
|
||||
bits += 8;
|
||||
do {
|
||||
bits -= 6;
|
||||
*cp++ = base64url_table[(ac >> bits) & 0x3f];
|
||||
} while (bits >= 6);
|
||||
}
|
||||
if (bits)
|
||||
*cp++ = base64url_table[(ac << (6 - bits)) & 0x3f];
|
||||
return cp - dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* fscrypt_base64url_decode() - base64url-decode a string
|
||||
* @src: the string to decode. Doesn't need to be NUL-terminated.
|
||||
* @srclen: the length of @src in bytes
|
||||
* @dst: (output) the decoded binary data
|
||||
*
|
||||
* Decodes a string using base64url encoding, i.e. the "Base 64 Encoding with
|
||||
* URL and Filename Safe Alphabet" specified by RFC 4648. '='-padding isn't
|
||||
* accepted, nor are non-encoding characters such as whitespace.
|
||||
*
|
||||
* This implementation hasn't been optimized for performance.
|
||||
*
|
||||
* Return: the length of the resulting decoded binary data in bytes,
|
||||
* or -1 if the string isn't a valid base64url string.
|
||||
*/
|
||||
static int fscrypt_base64url_decode(const char *src, int srclen, u8 *dst)
|
||||
{
|
||||
u32 ac = 0;
|
||||
int bits = 0;
|
||||
int i;
|
||||
u8 *bp = dst;
|
||||
|
||||
for (i = 0; i < srclen; i++) {
|
||||
const char *p = strchr(base64url_table, src[i]);
|
||||
|
||||
if (p == NULL || src[i] == 0)
|
||||
return -1;
|
||||
ac = (ac << 6) | (p - base64url_table);
|
||||
bits += 6;
|
||||
if (bits >= 8) {
|
||||
bits -= 8;
|
||||
*bp++ = (u8)(ac >> bits);
|
||||
}
|
||||
}
|
||||
if (ac & ((1 << bits) - 1))
|
||||
return -1;
|
||||
return bp - dst;
|
||||
}
|
||||
|
||||
bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
|
||||
u32 orig_len, u32 max_len,
|
||||
u32 *encrypted_len_ret)
|
||||
|
|
@ -387,8 +310,8 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
|||
nokey_name.sha256);
|
||||
size = FSCRYPT_NOKEY_NAME_MAX;
|
||||
}
|
||||
oname->len = fscrypt_base64url_encode((const u8 *)&nokey_name, size,
|
||||
oname->name);
|
||||
oname->len = base64_encode((const u8 *)&nokey_name, size,
|
||||
oname->name, false, BASE64_URLSAFE);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_fname_disk_to_usr);
|
||||
|
|
@ -467,8 +390,8 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
|
|||
if (fname->crypto_buf.name == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = fscrypt_base64url_decode(iname->name, iname->len,
|
||||
fname->crypto_buf.name);
|
||||
ret = base64_decode(iname->name, iname->len,
|
||||
fname->crypto_buf.name, false, BASE64_URLSAFE);
|
||||
if (ret < (int)offsetof(struct fscrypt_nokey_name, bytes[1]) ||
|
||||
(ret > offsetof(struct fscrypt_nokey_name, sha256) &&
|
||||
ret != FSCRYPT_NOKEY_NAME_MAX)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue