ceph: add base64 endcoding routines for encrypted names
The base64url encoding used by fscrypt includes the '_' character, which may cause problems in snapshot names (if the name starts with '_'). Thus, use the base64 encoding defined for IMAP mailbox names (RFC 3501), which uses '+' and ',' instead of '-' and '_'. Signed-off-by: Luís Henriques <lhenriques@suse.de> Reviewed-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Xiubo Li <xiubli@redhat.com> Reviewed-by: Milind Changire <mchangir@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
b7b53361c8
commit
64e86f632b
|
@ -1,4 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* The base64 encode/decode code was copied from fscrypt:
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
* Copyright (C) 2015, Motorola Mobility
|
||||
* Written by Uday Savagaonkar, 2014.
|
||||
* Modified by Jaegeuk Kim, 2015.
|
||||
*/
|
||||
#include <linux/ceph/ceph_debug.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/fscrypt.h>
|
||||
|
@ -7,6 +14,59 @@
|
|||
#include "mds_client.h"
|
||||
#include "crypto.h"
|
||||
|
||||
/*
|
||||
* The base64url encoding used by fscrypt includes the '_' character, which may
|
||||
* cause problems in snapshot names (which can not start with '_'). Thus, we
|
||||
* used the base64 encoding defined for IMAP mailbox names (RFC 3501) instead,
|
||||
* which replaces '-' and '_' by '+' and ','.
|
||||
*/
|
||||
static const char base64_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
|
||||
|
||||
int ceph_base64_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++ = base64_table[(ac >> bits) & 0x3f];
|
||||
} while (bits >= 6);
|
||||
}
|
||||
if (bits)
|
||||
*cp++ = base64_table[(ac << (6 - bits)) & 0x3f];
|
||||
return cp - dst;
|
||||
}
|
||||
|
||||
int ceph_base64_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(base64_table, src[i]);
|
||||
|
||||
if (p == NULL || src[i] == 0)
|
||||
return -1;
|
||||
ac = (ac << 6) | (p - base64_table);
|
||||
bits += 6;
|
||||
if (bits >= 8) {
|
||||
bits -= 8;
|
||||
*bp++ = (u8)(ac >> bits);
|
||||
}
|
||||
}
|
||||
if (ac & ((1 << bits) - 1))
|
||||
return -1;
|
||||
return bp - dst;
|
||||
}
|
||||
|
||||
static int ceph_crypt_get_context(struct inode *inode, void *ctx, size_t len)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
|
|
|
@ -27,6 +27,38 @@ static inline u32 ceph_fscrypt_auth_len(struct ceph_fscrypt_auth *fa)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
/*
|
||||
* We want to encrypt filenames when creating them, but the encrypted
|
||||
* versions of those names may have illegal characters in them. To mitigate
|
||||
* that, we base64 encode them, but that gives us a result that can exceed
|
||||
* NAME_MAX.
|
||||
*
|
||||
* Follow a similar scheme to fscrypt itself, and cap the filename to a
|
||||
* smaller size. If the ciphertext name is longer than the value below, then
|
||||
* sha256 hash the remaining bytes.
|
||||
*
|
||||
* For the fscrypt_nokey_name struct the dirhash[2] member is useless in ceph
|
||||
* so the corresponding struct will be:
|
||||
*
|
||||
* struct fscrypt_ceph_nokey_name {
|
||||
* u8 bytes[157];
|
||||
* u8 sha256[SHA256_DIGEST_SIZE];
|
||||
* }; // 180 bytes => 240 bytes base64-encoded, which is <= NAME_MAX (255)
|
||||
*
|
||||
* (240 bytes is the maximum size allowed for snapshot names to take into
|
||||
* account the format: '_<SNAPSHOT-NAME>_<INODE-NUMBER>'.)
|
||||
*
|
||||
* Note that for long names that end up having their tail portion hashed, we
|
||||
* must also store the full encrypted name (in the dentry's alternate_name
|
||||
* field).
|
||||
*/
|
||||
#define CEPH_NOHASH_NAME_MAX (180 - SHA256_DIGEST_SIZE)
|
||||
|
||||
#define CEPH_BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3)
|
||||
|
||||
int ceph_base64_encode(const u8 *src, int srclen, char *dst);
|
||||
int ceph_base64_decode(const char *src, int srclen, u8 *dst);
|
||||
|
||||
void ceph_fscrypt_set_ops(struct super_block *sb);
|
||||
|
||||
void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc);
|
||||
|
|
Loading…
Reference in New Issue