From nobody Sun Dec 14 19:56:38 2025 Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F2E281FC0ED for ; Fri, 14 Nov 2025 06:00:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100054; cv=none; b=cnlY7/s01FkWbXl6rDKIlP/EzsRnT0LsPWKD2pIk57z0kqlahR1lYq4QHdcO8AKt8lmMiY6SNYDnbUdH6OwwtieigJJPSvMgNWpJROOKbblfc/nb5+iPK5K9NAh2DUiA6pHqH8+DC8nSWsOsiq7JSrQREGzGtoms4F/E44ZqST8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100054; c=relaxed/simple; bh=RzLjsaWNfd3c5UqNh11NB/OA761QgAhvGHx5EwD+vbQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GcA9qAs7FjfoU893SndoFVLScMmWdt5R+CZizc2PwFvmcCB7MVugIG/m4LvpVSPzgbsYgjsHVzUFBKmc3BuRQz/HLuCw9xNtfpvHeYXFGnF9GZT4G28ZpII6qwkrnFHsY73ez+1lSeEOXSzDBgJmjqLK5PB2oZno+Lwku03CM74= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw; spf=pass smtp.mailfrom=gms.tku.edu.tw; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b=gu25l7m6; arc=none smtp.client-ip=209.85.214.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b="gu25l7m6" Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-297dd95ffe4so13696685ad.3 for ; Thu, 13 Nov 2025 22:00:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1763100052; x=1763704852; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WmGe/VGuYfrow1+cTg8GsPpK6vNwvcURmH5IbRl3Ggw=; b=gu25l7m6wt/Llha2kslgGi3+p77A0XG+lShFoQvGb29yJusoNW+ur1zlKyaEBuevqk iZZsT4sB0ZK4HV75//byHqL7LJp/q0eoHSMeaf7XM68UIsANqEFtpGPyotRS3Xm797q7 d1nutPwaiabYWDlxJedY0LuYZ4TSMoI5QXekXVG5e0XQe6+vc3q03yGT73w285RStpNg zhWK0HnIBBvxPjK94AuQTkMRr5+XlUE1QZ3rZI7hP92nPeQhBvWwhRBx8et8X9QrAG2C i2CvOC8/5s58yPz4EbH/ZtM5E/aq7AFHAovOnxG0rvhlZz9sUUA8XyS2lgzeugGYiyHz 4UqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763100052; x=1763704852; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=WmGe/VGuYfrow1+cTg8GsPpK6vNwvcURmH5IbRl3Ggw=; b=eXYbw9zd4ZeOa/dMPkPqnAhOFc4IMEA8p44CgZySBdypw2NB7er/kLUud5SVH0KERm +XICXc/9W87WZKydQtjwsJTp3VfV6chrPZ4APmixip1U/IQjMjWEiyDkHNcm2U6u5S4O sofgYKf0YlBRzti6WyhmjYPXEdkB3aXFC3CfmKAZ/k9Jozv0ztzTpCesMpULw73DHSEE HnXwlfk/0B+N/UpMGRPyQVrd6LEZ4/h5yynhtIzhwZ3W0HNyeAaCpUBbEhqbUFmIIY3F r0goJlZhXq82kg8IXk7KESq3bvaRWX5vmNmqwHWcwdrdGNMtfTCD19CFZvY3AZqy/nUd 3cYQ== X-Forwarded-Encrypted: i=1; AJvYcCUhJMX5BPC+xBTYhI7xwXlz1GCIEuBBu/bjfCsfKM+ldW3fFpTmrYddCEplX4yzIOfquiNCQ6VBIyk4RW4=@vger.kernel.org X-Gm-Message-State: AOJu0YyDhLviW/VAh3ZL7VfqAMHHAUdTmyZ+/yzyKWbrBNX+7NqCBC8X BuZV5I7Y4zg7OBgNEMwdDfxZwTElrPF2nVK6O6avp88w+heLVcfG+iY/0Pl1v0Ig090= X-Gm-Gg: ASbGnctJOySU79HRScgpJZxyKjpem9oM7VPVIcYD6IPZHhfsBy9j8MjFF9EvULr3VHu Hzx6Ogc0MBp+6ajhTHd43Jql1e8cwj3YS6/QSO7XMj18Zf1Fm3vjSJ851T3Yg0EibxeJEvExfVh iXNShsuTC7iBRfdrxMAvVV8lnmUKSNyXSGsATg+U1oCoygclFw4+rxqexyRahawislUPYMo1L7m luidMpXzQnHyC4PLFHtEY3lGz35wO2OLeBsHiw4k99r4lRKi0MwqRKRLYoB1baYHdev236rXa+T FNyDPiJ7kGMhoxumxzlqeAGVmBSZVtJ86PDA8sjeBA+sYeGgSifb64I79BJhm9TxYJkAmVrTloO kmu9uNKdy6wD6AhFNBUGwEUTrFaeJLXVPxDDMDFuFeHHslEXwyR8p4HQdsDEaQzW4RJOuT9m2yI DB2BR1FtNSyG0jaQDc3J7fZWeZ X-Google-Smtp-Source: AGHT+IE7lHXKbSg0FY2N6GECOYDuJxXFgUxUajs+hyWaWoZbadwsoEmHcwEF6EJwnMXpyL4EQeUVcA== X-Received: by 2002:a17:903:2f0e:b0:298:485d:5571 with SMTP id d9443c01a7336-2986a75f1f6mr19001495ad.54.1763100052199; Thu, 13 Nov 2025 22:00:52 -0800 (PST) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:22d2:323c:497d:adbd]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-343e07b4b23sm7858577a91.13.2025.11.13.22.00.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 22:00:51 -0800 (PST) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, andriy.shevchenko@intel.com, axboe@kernel.dk, ceph-devel@vger.kernel.org, david.laight.linux@gmail.com, ebiggers@kernel.org, hch@lst.de, home7438072@gmail.com, idryomov@gmail.com, jaegeuk@kernel.org, kbusch@kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvme@lists.infradead.org, sagi@grimberg.me, tytso@mit.edu, visitorckw@gmail.com, xiubli@redhat.com Subject: [PATCH v5 1/6] lib/base64: Add support for multiple variants Date: Fri, 14 Nov 2025 14:00:45 +0800 Message-Id: <20251114060045.88792-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251114055829.87814-1-409411716@gms.tku.edu.tw> References: <20251114055829.87814-1-409411716@gms.tku.edu.tw> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kuan-Wei Chiu Extend the base64 API to support multiple variants (standard, URL-safe, and IMAP) as defined in RFC 4648 and RFC 3501. The API now takes a variant parameter and an option to control padding. Update NVMe auth code to use the new interface with BASE64_STD. Signed-off-by: Kuan-Wei Chiu Co-developed-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Reviewed-by: David Laight --- drivers/nvme/common/auth.c | 4 +-- include/linux/base64.h | 10 ++++-- lib/base64.c | 62 ++++++++++++++++++++++---------------- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/drivers/nvme/common/auth.c b/drivers/nvme/common/auth.c index 1f51fbebd9fa..e07e7d4bf8b6 100644 --- a/drivers/nvme/common/auth.c +++ b/drivers/nvme/common/auth.c @@ -178,7 +178,7 @@ struct nvme_dhchap_key *nvme_auth_extract_key(unsigned = char *secret, if (!key) return ERR_PTR(-ENOMEM); =20 - key_len =3D base64_decode(secret, allocated_len, key->key); + key_len =3D base64_decode(secret, allocated_len, key->key, true, BASE64_S= TD); if (key_len < 0) { pr_debug("base64 key decoding error %d\n", key_len); @@ -663,7 +663,7 @@ int nvme_auth_generate_digest(u8 hmac_id, u8 *psk, size= _t psk_len, if (ret) goto out_free_digest; =20 - ret =3D base64_encode(digest, digest_len, enc); + ret =3D base64_encode(digest, digest_len, enc, true, BASE64_STD); if (ret < hmac_len) { ret =3D -ENOKEY; goto out_free_digest; diff --git a/include/linux/base64.h b/include/linux/base64.h index 660d4cb1ef31..a2c6c9222da3 100644 --- a/include/linux/base64.h +++ b/include/linux/base64.h @@ -8,9 +8,15 @@ =20 #include =20 +enum base64_variant { + BASE64_STD, /* RFC 4648 (standard) */ + BASE64_URLSAFE, /* RFC 4648 (base64url) */ + BASE64_IMAP, /* RFC 3501 */ +}; + #define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) =20 -int base64_encode(const u8 *src, int len, char *dst); -int base64_decode(const char *src, int len, u8 *dst); +int base64_encode(const u8 *src, int len, char *dst, bool padding, enum ba= se64_variant variant); +int base64_decode(const char *src, int len, u8 *dst, bool padding, enum ba= se64_variant variant); =20 #endif /* _LINUX_BASE64_H */ diff --git a/lib/base64.c b/lib/base64.c index b736a7a431c5..a7c20a8e8e98 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -1,12 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 /* - * base64.c - RFC4648-compliant base64 encoding + * base64.c - Base64 with support for multiple variants * * Copyright (c) 2020 Hannes Reinecke, SUSE * * Based on the base64url routines from fs/crypto/fname.c - * (which are using the URL-safe base64 encoding), - * modified to use the standard coding table from RFC4648 section 4. + * (which are using the URL-safe Base64 encoding), + * modified to support multiple Base64 variants. */ =20 #include @@ -15,26 +15,31 @@ #include #include =20 -static const char base64_table[65] =3D - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char base64_tables[][65] =3D { + [BASE64_STD] =3D "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012= 3456789+/", + [BASE64_URLSAFE] =3D "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy= z0123456789-_", + [BASE64_IMAP] =3D "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01= 23456789+,", +}; =20 /** - * base64_encode() - base64-encode some binary data + * base64_encode() - Base64-encode some binary data * @src: the binary data to encode * @srclen: the length of @src in bytes - * @dst: (output) the base64-encoded string. Not NUL-terminated. + * @dst: (output) the Base64-encoded string. Not NUL-terminated. + * @padding: whether to append '=3D' padding characters + * @variant: which base64 variant to use * - * Encodes data using base64 encoding, i.e. the "Base 64 Encoding" specifi= ed - * by RFC 4648, including the '=3D'-padding. + * Encodes data using the selected Base64 variant. * - * Return: the length of the resulting base64-encoded string in bytes. + * Return: the length of the resulting Base64-encoded string in bytes. */ -int base64_encode(const u8 *src, int srclen, char *dst) +int base64_encode(const u8 *src, int srclen, char *dst, bool padding, enum= base64_variant variant) { u32 ac =3D 0; int bits =3D 0; int i; char *cp =3D dst; + const char *base64_table =3D base64_tables[variant]; =20 for (i =3D 0; i < srclen; i++) { ac =3D (ac << 8) | src[i]; @@ -48,44 +53,49 @@ int base64_encode(const u8 *src, int srclen, char *dst) *cp++ =3D base64_table[(ac << (6 - bits)) & 0x3f]; bits -=3D 6; } - while (bits < 0) { - *cp++ =3D '=3D'; - bits +=3D 2; + if (padding) { + while (bits < 0) { + *cp++ =3D '=3D'; + bits +=3D 2; + } } return cp - dst; } EXPORT_SYMBOL_GPL(base64_encode); =20 /** - * base64_decode() - base64-decode a string + * base64_decode() - Base64-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 + * @padding: whether to append '=3D' padding characters + * @variant: which base64 variant to use * - * Decodes a string using base64 encoding, i.e. the "Base 64 Encoding" - * specified by RFC 4648, including the '=3D'-padding. + * Decodes a string using the selected Base64 variant. * * 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 base64 string. + * or -1 if the string isn't a valid Base64 string. */ -int base64_decode(const char *src, int srclen, u8 *dst) +int base64_decode(const char *src, int srclen, u8 *dst, bool padding, enum= base64_variant variant) { u32 ac =3D 0; int bits =3D 0; int i; u8 *bp =3D dst; + const char *base64_table =3D base64_tables[variant]; =20 for (i =3D 0; i < srclen; i++) { const char *p =3D strchr(base64_table, src[i]); - - if (src[i] =3D=3D '=3D') { - ac =3D (ac << 6); - bits +=3D 6; - if (bits >=3D 8) - bits -=3D 8; - continue; + if (padding) { + if (src[i] =3D=3D '=3D') { + ac =3D (ac << 6); + bits +=3D 6; + if (bits >=3D 8) + bits -=3D 8; + continue; + } } if (p =3D=3D NULL || src[i] =3D=3D 0) return -1; --=20 2.34.1 From nobody Sun Dec 14 19:56:38 2025 Received: from mail-pf1-f181.google.com (mail-pf1-f181.google.com [209.85.210.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16CC723C50F for ; Fri, 14 Nov 2025 06:01:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100077; cv=none; b=s8jEMbqrgaONUGNuTs2DukCgc/o1rxqd0vmjKzEI/IwM8Z2yKN3LOuOBRayulYUK6yApvh6dGIQfmlg1IxIJj8VRGdg3eLrqXbQusUnuFyfwRFfApQhHHhe83vlZP7xMQTfM2+SlB0YS8hrjvsmHncHZgMYx6Ps3xxGxjFPtk1M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100077; c=relaxed/simple; bh=ebfhLZNEl5pO72lYrO9Xn1y4JHTAnC4DTnDbTXJruzM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TU6G/lqljzsI1FIy942W3MKBCcXrhVf6cuKEa3hgKUy7nUIIgWuWwbhCQvyhMaLZsLz1NPVKpJaESkoAvkqoBd2fmYJjxD9uyPx3J4D5QZq5Kqtn/Z8kTmx9dbzvC/WZRdcl4Bj0NcbQQyNnXpQQdaJAUbFoRhfBw61bXfmet5Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw; spf=pass smtp.mailfrom=gms.tku.edu.tw; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b=cMVPcvCX; arc=none smtp.client-ip=209.85.210.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b="cMVPcvCX" Received: by mail-pf1-f181.google.com with SMTP id d2e1a72fcca58-7aae5f2633dso1888428b3a.3 for ; Thu, 13 Nov 2025 22:01:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1763100074; x=1763704874; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lWS11xsgkFrNsAXlptIvYpGHMFNUcuv3AuLz0xI70Ao=; b=cMVPcvCXnMM511FrlzdK+cADV1Q9BS4r9uxsnAa1VKlsZ21c/NSk+17XzgOaPoEmy/ PwWmkqlJ4R5NOGUqUjjgam5heJ3tsMz5JvYrlQDpmVP3tleLwZ1/qa5rx1A04Q8iT4bD RbVEt8of6EtSRmz4ZXXtU+BAuBoSYw9GenaPfggwKN7qV/tzknII4JIYRuo6c053WDyn IP1/zaIilFE25RErv6XQ9SZh1VOoz11WT5QKXQUjwc4835r/qmSh63+o5FyRaNqAUx6o /ZTIElouDRm3r3SNr0ydUGzkqK5Y2L4yj2du4ET5XJVYEfYa3Xdf5xDgXa7t9U8/T/xL bUcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763100074; x=1763704874; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=lWS11xsgkFrNsAXlptIvYpGHMFNUcuv3AuLz0xI70Ao=; b=Zx1YC5G+AR+jt16FMWfbKpD+YVi7fOxQ8NgRjUDoUseJCQmB0hMbE9yWKgV+VrPd4B 04W85clawNDGKIC46MmXJssTPffBZ8qUykOjqr65X+Lpnop7zmPJM3J2CHnOIk4szQWK VwvXJLFsflWigtYG/0BYhvgaClXzvJ+hgzogahOshKD/SOxZ+NhJ49cp2XOo+qbMzDzL HNHIy4TpGugXkm9AcNSts7D/Y7rOMcYSbJKFfgRW1gRQ4pzjPPP7YplJ6xt09VIh5Fo5 LyW29wbjCi5dyYXuzAAue2ketmY9nIhBqtRI14PQMPYFTTM6dEvjNSwGyWQDaJ091YQs OXNg== X-Forwarded-Encrypted: i=1; AJvYcCV/TwpZmEHxqIoSyKjCPs6756kMDBzOWkqkxxs5AKW1z83SDS37ujKFI9zsHHPDvYWExDUFZAzBNXIHajM=@vger.kernel.org X-Gm-Message-State: AOJu0YwE/pspFee2ggABeMLlHO3ImY4czmJ22rPj/2NhI961Iip+rgx8 E+iiLRcWQTc2Kq/p0Tp04fZ/26WC8QzoZqB2CDfEbcOkYU2DIGb4qK6Ti5fkr4WdezU= X-Gm-Gg: ASbGncux0bFivZO4lyRXTzSH+VmjLX/0kZVUJYsXyZBtyCifqq81Iw1fMMcVXQ5gjwP 6mQNkBG6HLWabqWWzj1Qzt1a0MK3V3Kb3X6CVQvD0yDdt0yWzd+CkS/199r1Tr4SDOm1uYFPt89 phQkTx+ClUzEutAbXT0FKQLSgVFeik9gvynPKJfYbdzP6Y3cLboo2JKziMGiNnPrMxd4E+FW7w4 MwXR1YphQ++BFlquq7S1ZS+tItRp/YBQYeTYgE7Lct5IVQLvXUMhvuwyOmWLNC3OmXNibARMsva 8x84uJvKF+ifDJlOFxwRnD8mEg1jsoUGv9nNXnt06wIIQZs5nBDXmz2qDi8hKeAnVoan1K32ytX 4xCcS8rZ+53YjuIJFATHqqBMyIRoeLrL9F0JhA0PizZ/qflSDuiy+R/EkyKN0a4qTjI2k2lRJ1m GLcY+4/ESkhlvi0y32iSwKX3m/cFo/lXa5+KQ= X-Google-Smtp-Source: AGHT+IH5zqaJvOCHGyW2FJR2JlFHMBKlTKF05FN81/22NWKlZaSd+Pgu/afzXFlbWF1Pxh5Ir24tyA== X-Received: by 2002:a05:6a00:198d:b0:7b8:9d86:6d44 with SMTP id d2e1a72fcca58-7ba3a0be249mr2401481b3a.9.1763100074344; Thu, 13 Nov 2025 22:01:14 -0800 (PST) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:22d2:323c:497d:adbd]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7b924be368bsm4075198b3a.9.2025.11.13.22.01.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 22:01:14 -0800 (PST) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, andriy.shevchenko@intel.com, axboe@kernel.dk, ceph-devel@vger.kernel.org, david.laight.linux@gmail.com, ebiggers@kernel.org, hch@lst.de, home7438072@gmail.com, idryomov@gmail.com, jaegeuk@kernel.org, kbusch@kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvme@lists.infradead.org, sagi@grimberg.me, tytso@mit.edu, visitorckw@gmail.com, xiubli@redhat.com Subject: [PATCH v5 2/6] lib/base64: Optimize base64_decode() with reverse lookup tables Date: Fri, 14 Nov 2025 14:01:07 +0800 Message-Id: <20251114060107.89026-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251114055829.87814-1-409411716@gms.tku.edu.tw> References: <20251114055829.87814-1-409411716@gms.tku.edu.tw> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kuan-Wei Chiu Replace the use of strchr() in base64_decode() with precomputed reverse lookup tables for each variant. This avoids repeated string scans and improves performance. Use -1 in the tables to mark invalid characters. Decode: 64B ~1530ns -> ~80ns (~19.1x) 1KB ~27726ns -> ~1239ns (~22.4x) Signed-off-by: Kuan-Wei Chiu Co-developed-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Reviewed-by: David Laight --- lib/base64.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/lib/base64.c b/lib/base64.c index a7c20a8e8e98..9d1074bb821c 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -21,6 +21,49 @@ static const char base64_tables[][65] =3D { [BASE64_IMAP] =3D "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01= 23456789+,", }; =20 +/** + * Initialize the base64 reverse mapping for a single character + * This macro maps a character to its corresponding base64 value, + * returning -1 if the character is invalid. + * char 'A'-'Z' maps to 0-25, 'a'-'z' maps to 26-51, '0'-'9' maps to 52-61, + * ch_62 maps to 62, ch_63 maps to 63, and other characters return -1 + */ +#define INIT_1(v, ch_62, ch_63) \ + [v] =3D (v) >=3D 'A' && (v) <=3D 'Z' ? (v) - 'A' \ + : (v) >=3D 'a' && (v) <=3D 'z' ? (v) - 'a' + 26 \ + : (v) >=3D '0' && (v) <=3D '9' ? (v) - '0' + 52 \ + : (v) =3D=3D (ch_62) ? 62 : (v) =3D=3D (ch_63) ? 63 : -1 +/** + * Recursive macros to generate multiple Base64 reverse mapping table entr= ies. + * Each macro generates a sequence of entries in the lookup table: + * INIT_2 generates 2 entries, INIT_4 generates 4, INIT_8 generates 8, and= so on up to INIT_32. + */ +#define INIT_2(v, ...) INIT_1(v, __VA_ARGS__), INIT_1((v) + 1, __VA_ARGS__) +#define INIT_4(v, ...) INIT_2(v, __VA_ARGS__), INIT_2((v) + 2, __VA_ARGS__) +#define INIT_8(v, ...) INIT_4(v, __VA_ARGS__), INIT_4((v) + 4, __VA_ARGS__) +#define INIT_16(v, ...) INIT_8(v, __VA_ARGS__), INIT_8((v) + 8, __VA_ARGS_= _) +#define INIT_32(v, ...) INIT_16(v, __VA_ARGS__), INIT_16((v) + 16, __VA_AR= GS__) + +#define BASE64_REV_INIT(ch_62, ch_63) { \ + [0 ... 0x1f] =3D -1, \ + INIT_32(0x20, ch_62, ch_63), \ + INIT_32(0x40, ch_62, ch_63), \ + INIT_32(0x60, ch_62, ch_63), \ + [0x80 ... 0xff] =3D -1 } + +static const s8 base64_rev_maps[][256] =3D { + [BASE64_STD] =3D BASE64_REV_INIT('+', '/'), + [BASE64_URLSAFE] =3D BASE64_REV_INIT('-', '_'), + [BASE64_IMAP] =3D BASE64_REV_INIT('+', ',') +}; + +#undef BASE64_REV_INIT +#undef INIT_32 +#undef INIT_16 +#undef INIT_8 +#undef INIT_4 +#undef INIT_2 +#undef INIT_1 /** * base64_encode() - Base64-encode some binary data * @src: the binary data to encode @@ -84,10 +127,9 @@ int base64_decode(const char *src, int srclen, u8 *dst,= bool padding, enum base6 int bits =3D 0; int i; u8 *bp =3D dst; - const char *base64_table =3D base64_tables[variant]; + s8 ch; =20 for (i =3D 0; i < srclen; i++) { - const char *p =3D strchr(base64_table, src[i]); if (padding) { if (src[i] =3D=3D '=3D') { ac =3D (ac << 6); @@ -97,9 +139,10 @@ int base64_decode(const char *src, int srclen, u8 *dst,= bool padding, enum base6 continue; } } - if (p =3D=3D NULL || src[i] =3D=3D 0) + ch =3D base64_rev_maps[variant][(u8)src[i]]; + if (ch =3D=3D -1) return -1; - ac =3D (ac << 6) | (p - base64_table); + ac =3D (ac << 6) | ch; bits +=3D 6; if (bits >=3D 8) { bits -=3D 8; --=20 2.34.1 From nobody Sun Dec 14 19:56:38 2025 Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 76B282DAFA5 for ; Fri, 14 Nov 2025 06:01:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100102; cv=none; b=iRySjjxlNSyAbGY7W8T8cYSHbu1kyWykvGv8wcdWbY+EMfXkjmdR4u6ADNROExWkZphbXuGiJIlHpbaWgxDOdXsRibDlmSNYJpC1azFrPJQvgH5ez2RZpvwHyRVe27y9BoOGamOMLuHQ1+/9/BWlCEHT5tK7CPCEBLJcmfV7e8s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100102; c=relaxed/simple; bh=iA2hBVRXx0YemEHPsh/s0OtYYJaZyVmkN06w/iID+7o=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nrzuWv6sgsdqLhGI1iceh6LUPKWKZEdQj0p8w3VsYp8FCSTtNa49SAXnfuD9fQvy8GblqvGWvU/li79uw5rffUXhthU+we8Qj1wvg71WC7jrGU67zHU7rZe/pS5lV1WKjUvCzyIau1+5nYxMGG9qLGT+L6R8q8BJRe8v5OrQ/Ho= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw; spf=pass smtp.mailfrom=gms.tku.edu.tw; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b=wX58QEpg; arc=none smtp.client-ip=209.85.216.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b="wX58QEpg" Received: by mail-pj1-f51.google.com with SMTP id 98e67ed59e1d1-3437ea05540so1641415a91.0 for ; Thu, 13 Nov 2025 22:01:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1763100100; x=1763704900; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Q1IGQOBRzs6BjZdUR3pYUPttP+jjYEqCfWUHv2cldxw=; b=wX58QEpg7f1aY5M0lu5SBt44yNLnb40/gCOEIdgMqbpCPJGFtCYK+To/agDuQcqKlz xxoH/Y0FMmFpDTi53SkNCbUoD07QK+09VMpAGI3hNz3iUanCMVAP+8CRvu7aFb74x4GD 26fK3uhsryfDX9bV5BY42J3su/1po5juWRY1XHH1uEbAdJQi0BF9KxjjU2eSBSoBdyPl k1NjFg2MwXvsiz8yg9Iccw61ivsu/Lu6wF4Zbn6/OFcWM/XIG9qEuFNd+vm1pnolpraw IWKXIU8YMX8TV8rAdYM1NnPN04Kp1Y/ClzZUS1ceeqxEzLZzN0aFkG+9OWhpbZiyLXkJ B86A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763100100; x=1763704900; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Q1IGQOBRzs6BjZdUR3pYUPttP+jjYEqCfWUHv2cldxw=; b=Eh4kgiFSVxjidUcstkiJP9Wnpkd/MO0+93HCSmKAmHj0OPKjfdJADs8kknevFObAWn T7d6IUkXJyVLTG3Tv04Uv6lH7SaJ2yEQ69UKC/SobnndZCCtO4dkJ24yaKKqT34dJg2o bf67XIlCr2o5IpK5QzE+oyHO+CUk6uTzU8XKYjQrc/+dSHcVW6UcasDxlxU1vWDLOBWu qqxBCwAdvSVTUdieuiGbCeGBx37pF4x0ix9wovFYWvPY7pU9OAKBj7GmLIoFJGJp6tqm AbuShEY3fTtNa6fbtA7ME3y2HEPqAF97UaAXVcnDzNP9HwXnw6o2OL/s66G6oD+EQirq XPUw== X-Forwarded-Encrypted: i=1; AJvYcCUaYGSumApgXYtGg7O8wHqIEEaDAO4d/EeS5Vh/8arWQw6q3mQhGF3TSp/AxgLgynEqcZyyYXAcWMwdlQk=@vger.kernel.org X-Gm-Message-State: AOJu0YzbQolE8SrCuxPN1YCN7NMeMOTL7X42f10pDyGseC46rXCjQc41 ckWQ3G9YXRKQREjy0oy/gPja41Fq9szsM1rwmWhZROxMJ8cLm2D60q6jT+7lbOu+hfs= X-Gm-Gg: ASbGnctni74C+2RD6FMHTJvYCLogc0wenzfW91XgsSHHYJNVzgdPlFcsebJ9F+jGyuE mmHltAvZB14W0lh35rIdBcm8EvkjP6T3ziDG8ujqLkfrVCojMFCAR97OURXZC4qUqEZbwSyU2C+ X/P7AcvihLAlfZEZu24mG0MxnkbfFbiz8E0U/j0JoTyJMoDAb1+28lSrWBppeskJOKlKcu16MVq jgwoI95IEr/ospdtK2IK9Gtff/q82ESKyXLRptAz+qw0kJR99UFA+beLfLqlSOUo1ZtR2liCAvi XLXpIsRxP4ZvsjRi8cbrHLerECDHp76VHtrsh37Va0d1HcJdSWxdlsUsvdlOvfxYsCmzn+x0/4d 2Y3eYp138UWNyLVyeBh6q28akG63SkQwAqiOW7dIfwUdLLCH5DjJWejQxhd2GLGZ5j+cDl3hk39 j5avRMhVtZ9Gi8S0SolFxiXF5T X-Google-Smtp-Source: AGHT+IGm/DcFCjii9Cj0HeKdnayirMai9hbtcC7DKvoxz9MTk6adf+dWGrkM2fl+VogccyRz+p4CTA== X-Received: by 2002:a17:90b:3b4b:b0:343:a631:28a8 with SMTP id 98e67ed59e1d1-343fa754b6emr2387408a91.37.1763100098951; Thu, 13 Nov 2025 22:01:38 -0800 (PST) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:22d2:323c:497d:adbd]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-343ed55564dsm4354199a91.13.2025.11.13.22.01.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 22:01:38 -0800 (PST) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, andriy.shevchenko@intel.com, axboe@kernel.dk, ceph-devel@vger.kernel.org, david.laight.linux@gmail.com, ebiggers@kernel.org, hch@lst.de, home7438072@gmail.com, idryomov@gmail.com, jaegeuk@kernel.org, kbusch@kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvme@lists.infradead.org, sagi@grimberg.me, tytso@mit.edu, visitorckw@gmail.com, xiubli@redhat.com Subject: [PATCH v5 3/6] lib/base64: rework encode/decode for speed and stricter validation Date: Fri, 14 Nov 2025 14:01:32 +0800 Message-Id: <20251114060132.89279-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251114055829.87814-1-409411716@gms.tku.edu.tw> References: <20251114055829.87814-1-409411716@gms.tku.edu.tw> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The old base64 implementation relied on a bit-accumulator loop, which was slow for larger inputs and too permissive in validation. It would accept extra '=3D', missing '=3D', or even '=3D' appearing in the middle of the in= put, allowing malformed strings to pass. This patch reworks the internals to improve performance and enforce stricter validation. Changes: - Encoder: * Process input in 3-byte blocks, mapping 24 bits into four 6-bit symbols, avoiding bit-by-bit shifting and reducing loop iterations. * Handle the final 1-2 leftover bytes explicitly and emit '=3D' only when requested. - Decoder: * Based on the reverse lookup tables from the previous patch, decode input in 4-character groups. * Each group is looked up directly, converted into numeric values, and combined into 3 output bytes. * Explicitly handle padded and unpadded forms: - With padding: input length must be a multiple of 4, and '=3D' is allowed only in the last two positions. Reject stray or early '=3D'. - Without padding: validate tail lengths (2 or 3 chars) and require unused low bits to be zero. * Removed the bit-accumulator style loop to reduce loop iterations. Performance (x86_64, Intel Core i7-10700 @ 2.90GHz, avg over 1000 runs, KUnit): Encode: 64B ~90ns -> ~32ns (~2.8x) 1KB ~1332ns -> ~510ns (~2.6x) Decode: 64B ~1530ns -> ~35ns (~43.7x) 1KB ~27726ns -> ~530ns (~52.3x) Co-developed-by: Kuan-Wei Chiu Signed-off-by: Kuan-Wei Chiu Co-developed-by: Yu-Sheng Huang Signed-off-by: Yu-Sheng Huang Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Reviewed-by: David Laight --- lib/base64.c | 109 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 41 deletions(-) diff --git a/lib/base64.c b/lib/base64.c index 9d1074bb821c..1a6d8fe37eda 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -79,28 +79,38 @@ static const s8 base64_rev_maps[][256] =3D { int base64_encode(const u8 *src, int srclen, char *dst, bool padding, enum= base64_variant variant) { u32 ac =3D 0; - int bits =3D 0; - int i; char *cp =3D dst; const char *base64_table =3D base64_tables[variant]; =20 - for (i =3D 0; i < srclen; i++) { - ac =3D (ac << 8) | src[i]; - bits +=3D 8; - do { - bits -=3D 6; - *cp++ =3D base64_table[(ac >> bits) & 0x3f]; - } while (bits >=3D 6); - } - if (bits) { - *cp++ =3D base64_table[(ac << (6 - bits)) & 0x3f]; - bits -=3D 6; + while (srclen >=3D 3) { + ac =3D (u32)src[0] << 16 | (u32)src[1] << 8 | (u32)src[2]; + *cp++ =3D base64_table[ac >> 18]; + *cp++ =3D base64_table[(ac >> 12) & 0x3f]; + *cp++ =3D base64_table[(ac >> 6) & 0x3f]; + *cp++ =3D base64_table[ac & 0x3f]; + + src +=3D 3; + srclen -=3D 3; } - if (padding) { - while (bits < 0) { + + switch (srclen) { + case 2: + ac =3D (u32)src[0] << 16 | (u32)src[1] << 8; + *cp++ =3D base64_table[ac >> 18]; + *cp++ =3D base64_table[(ac >> 12) & 0x3f]; + *cp++ =3D base64_table[(ac >> 6) & 0x3f]; + if (padding) + *cp++ =3D '=3D'; + break; + case 1: + ac =3D (u32)src[0] << 16; + *cp++ =3D base64_table[ac >> 18]; + *cp++ =3D base64_table[(ac >> 12) & 0x3f]; + if (padding) { + *cp++ =3D '=3D'; *cp++ =3D '=3D'; - bits +=3D 2; } + break; } return cp - dst; } @@ -116,41 +126,58 @@ EXPORT_SYMBOL_GPL(base64_encode); * * Decodes a string using the selected Base64 variant. * - * 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 Base64 string. */ int base64_decode(const char *src, int srclen, u8 *dst, bool padding, enum= base64_variant variant) { - u32 ac =3D 0; - int bits =3D 0; - int i; u8 *bp =3D dst; - s8 ch; + s8 input[4]; + s32 val; + const u8 *s =3D (const u8 *)src; + const s8 *base64_rev_tables =3D base64_rev_maps[variant]; =20 - for (i =3D 0; i < srclen; i++) { - if (padding) { - if (src[i] =3D=3D '=3D') { - ac =3D (ac << 6); - bits +=3D 6; - if (bits >=3D 8) - bits -=3D 8; - continue; - } - } - ch =3D base64_rev_maps[variant][(u8)src[i]]; - if (ch =3D=3D -1) - return -1; - ac =3D (ac << 6) | ch; - bits +=3D 6; - if (bits >=3D 8) { - bits -=3D 8; - *bp++ =3D (u8)(ac >> bits); + while (srclen >=3D 4) { + input[0] =3D base64_rev_tables[s[0]]; + input[1] =3D base64_rev_tables[s[1]]; + input[2] =3D base64_rev_tables[s[2]]; + input[3] =3D base64_rev_tables[s[3]]; + + val =3D input[0] << 18 | input[1] << 12 | input[2] << 6 | input[3]; + + if (unlikely(val < 0)) { + if (!padding || srclen !=3D 4 || s[3] !=3D '=3D') + return -1; + padding =3D 0; + srclen =3D s[2] =3D=3D '=3D' ? 2 : 3; + break; } + + *bp++ =3D val >> 16; + *bp++ =3D val >> 8; + *bp++ =3D val; + + s +=3D 4; + srclen -=3D 4; } - if (ac & ((1 << bits) - 1)) + + if (likely(!srclen)) + return bp - dst; + if (padding || srclen =3D=3D 1) return -1; + + val =3D (base64_rev_tables[s[0]] << 12) | (base64_rev_tables[s[1]] << 6); + *bp++ =3D val >> 10; + + if (srclen =3D=3D 2) { + if (val & 0x800003ff) + return -1; + } else { + val |=3D base64_rev_tables[s[2]]; + if (val & 0x80000003) + return -1; + *bp++ =3D val >> 2; + } return bp - dst; } EXPORT_SYMBOL_GPL(base64_decode); --=20 2.34.1 From nobody Sun Dec 14 19:56:38 2025 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D73DA2DAFCC for ; Fri, 14 Nov 2025 06:02:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100128; cv=none; b=ELWr+kINLaoMuDQ55lpltsckuIVaM1Lw4PcaUpLtdmPRtnzrOSsTEp+1SwpYUPR44AEJq4zOKQxJwCUgs1DMI/XGCsq4iLV6ZB9GwxcjMnHWS8VgZ7cCTyaynDq8tYKqRHBvbS1NAqotOQKaimQAOxKPpQy/DR4awRp9YBdIZD8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100128; c=relaxed/simple; bh=uqCZHWXfubRIGcGUdgi2SCXRusjZcak1XApIJ5f67MQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=bqyHFP7YvSJ00Jm7np7OBjdlgMGcYKXhHo1EC4/bjgbSYY2revHrgEd9eKv729X8j5RTiAcOoQP8NYbwWbItY36eMoVLDh2YpxLxqOOWClws9DOYiTEgUmGqx/XFwMiUbnujhBqRfsyLgA9VB2PuqniFm2HGrHuxGLxMBIvyjc4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw; spf=pass smtp.mailfrom=gms.tku.edu.tw; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b=twWJBgst; arc=none smtp.client-ip=209.85.214.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b="twWJBgst" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-297e264528aso16345125ad.2 for ; Thu, 13 Nov 2025 22:02:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1763100123; x=1763704923; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fkpDCor2TUF5YyGMpKqZC7jfjMqxofNFoS0oYVpIUCs=; b=twWJBgstQzHaUJU1SXOox+Vd+gGyZf5KelB2kmt5eILUwmq+j9Rmcrtr0ik0FLAyoy O2+oUljSxCrL9L9+m0qYdJQgcoQ7YCqbekz71B11eCJPYJzq5K58kZy2T7Fc3paVekTN zyb7lBEox1snDeABPb5S0VpIS1pmyQ5m2/oYOZk5d6y9P0PosSScMQ4xsCJRAxg4TpVd osLINc2Irhw/0wlk82FA+fgFt35lZCYXNvMd4tq4OL5GmsP4LcukMA1Mr21ypZ7Juqx2 7AkKS5xALFnvaXa/IA3ABjPCGnnsbNA0WDcLZC8M5wC0KBV4Ljsl6Gn4T5DWh330PIBm NqTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763100123; x=1763704923; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=fkpDCor2TUF5YyGMpKqZC7jfjMqxofNFoS0oYVpIUCs=; b=phoNQUszk/jOgIpZdHjR0qtjMosJn83JYTnGxfO94ey/fkXffvHiiMI4kwqcN6BGDK k2D3wChgBtIqyL73mnwFXeaPPyUxyKbj7FGUeYpvObl0G9yv1P3GspLlCRQoYGA7h8xf /2ZAcQbbi6g5W1BG+LSTgW+8nMV/IdU3cWHafINVDgVoURyTKsYnuROsIkU1UidhVNRq M9B6xbssSG20w3+JUSCli0CjtMsNULIjBTcGopgNFDFJLnpp11guwUu0wmVGvC+5MGO8 8X+9mDqyKYvqWZu5I8oZR3S3ugyvWxX/Cj2suTa8BReP1VeHsIe8+0yP8BoaT0XgPSSU HXyA== X-Forwarded-Encrypted: i=1; AJvYcCUqyE74n5LBJEHwtzKwt8P+RG5he8odwHjGad4hhge5wsgoFQSWkbeo/u+2otHjd7jVvsgxZ+CFlB51r2k=@vger.kernel.org X-Gm-Message-State: AOJu0YypKeLcA65VXMTNWTmvm0GCNs9oFe9LHCzRSxysSjKpIFwpV/H+ Lb3Jd0a0fAJrN6BVXMZ53dcBAjrBlVqKUfHKymRYFcXAqhVEDtuN+NdLeQF44u96+J0= X-Gm-Gg: ASbGncuVktemDJfIYdyQ38oP0T0bibFm0OchVjFqj7nAOxCm6h1X31qc0NJrcusoPix Ny336NuUL8+LiIan9msrl1MJwWxv6P/3xiq4o4iNp9kF0O7Z1kb1Z7nRi9S1i1KBeUeUcoC6CPJ 5xBswIj9I/pGkFgIvzZGDgs85uE+HjQYKZB4neSDYw/BBmhS8Ilsdzq34FX3enDxTcM0yJLzFUA 7OGyjiVMgtxv1fDecyhK+DnPXd3k3DhKiybkzihqFBi72x+oVHNQ6kWK88O07/fQ0nb6H+QCdM9 6d1ZmcdD/OZLUDQuFn58AMCE9CmTXTY6eMDFZ0zwRLwQg+YTa6HNL+92JxJIaBFk0oIpPjzs9fw PsJdRuGHXccbZjDM/KkhdeRVQHXvAUD4pNjof2YG7ZJWW4rkk6FcaxBEvL9QTiDbC1kZfQSLWeZ 5TFSf2If2y238UCA4/9HBk6seCCQRZLiCrKSg= X-Google-Smtp-Source: AGHT+IHLJt5qiCwb1wnjqHRtAhuTOw76Mt+9zbvgqBMEi2RYv1ifLlCn1RvArWxwlI1zOXFfjIoqWw== X-Received: by 2002:a17:903:b0d:b0:295:70cc:8ec4 with SMTP id d9443c01a7336-2986a74b360mr22444965ad.51.1763100122945; Thu, 13 Nov 2025 22:02:02 -0800 (PST) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:22d2:323c:497d:adbd]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2985c2b0c35sm43342225ad.52.2025.11.13.22.01.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 22:02:02 -0800 (PST) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, andriy.shevchenko@intel.com, axboe@kernel.dk, ceph-devel@vger.kernel.org, david.laight.linux@gmail.com, ebiggers@kernel.org, hch@lst.de, home7438072@gmail.com, idryomov@gmail.com, jaegeuk@kernel.org, kbusch@kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvme@lists.infradead.org, sagi@grimberg.me, tytso@mit.edu, visitorckw@gmail.com, xiubli@redhat.com Subject: [PATCH v5 4/6] lib: add KUnit tests for base64 encoding/decoding Date: Fri, 14 Nov 2025 14:01:57 +0800 Message-Id: <20251114060157.89507-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251114055829.87814-1-409411716@gms.tku.edu.tw> References: <20251114055829.87814-1-409411716@gms.tku.edu.tw> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a KUnit test suite to validate the base64 helpers. The tests cover both encoding and decoding, including padded and unpadded forms as defined by RFC 4648 (standard base64), and add negative cases for malformed inputs and padding errors. The test suite also validates other variants (URLSAFE, IMAP) to ensure their correctness. In addition to functional checks, the suite includes simple microbenchmarks which report average encode/decode latency for small (64B) and larger (1KB) inputs. These numbers are informational only and do not gate the tests. Kconfig (BASE64_KUNIT) and lib/tests/Makefile are updated accordingly. Sample KUnit output: KTAP version 1 # Subtest: base64 # module: base64_kunit 1..4 # base64_performance_tests: [64B] encode run : 32ns # base64_performance_tests: [64B] decode run : 35ns # base64_performance_tests: [1KB] encode run : 510ns # base64_performance_tests: [1KB] decode run : 530ns ok 1 base64_performance_tests ok 2 base64_std_encode_tests ok 3 base64_std_decode_tests ok 4 base64_variant_tests # base64: pass:4 fail:0 skip:0 total:4 # Totals: pass:4 fail:0 skip:0 total:4 Reviewed-by: Kuan-Wei Chiu Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> --- lib/Kconfig.debug | 19 ++- lib/tests/Makefile | 1 + lib/tests/base64_kunit.c | 294 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 lib/tests/base64_kunit.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 3034e294d50d..8f55ab41d62a 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2815,8 +2815,25 @@ config CMDLINE_KUNIT_TEST =20 If unsure, say N. =20 +config BASE64_KUNIT + tristate "KUnit test for base64 decoding and encoding" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + This builds the base64 unit tests. + + The tests cover the encoding and decoding logic of Base64 functions + in the kernel. + In addition to correctness checks, simple performance benchmarks + for both encoding and decoding are also included. + + For more information on KUnit and unit tests in general please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. + config BITS_TEST - tristate "KUnit test for bits.h" if !KUNIT_ALL_TESTS + tristate "KUnit test for bit functions and macros" if !KUNIT_ALL_TESTS depends on KUNIT default KUNIT_ALL_TESTS help diff --git a/lib/tests/Makefile b/lib/tests/Makefile index f7460831cfdd..601dba4b7d96 100644 --- a/lib/tests/Makefile +++ b/lib/tests/Makefile @@ -4,6 +4,7 @@ =20 # KUnit tests CFLAGS_bitfield_kunit.o :=3D $(DISABLE_STRUCTLEAK_PLUGIN) +obj-$(CONFIG_BASE64_KUNIT) +=3D base64_kunit.o obj-$(CONFIG_BITFIELD_KUNIT) +=3D bitfield_kunit.o obj-$(CONFIG_BITS_TEST) +=3D test_bits.o obj-$(CONFIG_BLACKHOLE_DEV_KUNIT_TEST) +=3D blackhole_dev_kunit.o diff --git a/lib/tests/base64_kunit.c b/lib/tests/base64_kunit.c new file mode 100644 index 000000000000..f7252070c359 --- /dev/null +++ b/lib/tests/base64_kunit.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * base64_kunit_test.c - KUnit tests for base64 encoding and decoding func= tions + * + * Copyright (c) 2025, Guan-Chun Wu <409411716@gms.tku.edu.tw> + */ + +#include +#include + +/* ---------- Benchmark helpers ---------- */ +static u64 bench_encode_ns(const u8 *data, int len, char *dst, int reps, + enum base64_variant variant) +{ + u64 t0, t1; + + t0 =3D ktime_get_ns(); + for (int i =3D 0; i < reps; i++) + base64_encode(data, len, dst, true, variant); + t1 =3D ktime_get_ns(); + + return div64_u64(t1 - t0, (u64)reps); +} + +static u64 bench_decode_ns(const char *data, int len, u8 *dst, int reps, + enum base64_variant variant) +{ + u64 t0, t1; + + t0 =3D ktime_get_ns(); + for (int i =3D 0; i < reps; i++) + base64_decode(data, len, dst, true, variant); + t1 =3D ktime_get_ns(); + + return div64_u64(t1 - t0, (u64)reps); +} + +static void run_perf_and_check(struct kunit *test, const char *label, int = size, + enum base64_variant variant) +{ + const int reps =3D 1000; + size_t outlen =3D DIV_ROUND_UP(size, 3) * 4; + u8 *in =3D kmalloc(size, GFP_KERNEL); + char *enc =3D kmalloc(outlen, GFP_KERNEL); + u8 *decoded =3D kmalloc(size, GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, in); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, enc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, decoded); + + get_random_bytes(in, size); + int enc_len =3D base64_encode(in, size, enc, true, variant); + int dec_len =3D base64_decode(enc, enc_len, decoded, true, variant); + + /* correctness sanity check */ + KUNIT_EXPECT_EQ(test, dec_len, size); + KUNIT_EXPECT_MEMEQ(test, decoded, in, size); + + /* benchmark encode */ + + u64 t1 =3D bench_encode_ns(in, size, enc, reps, variant); + + kunit_info(test, "[%s] encode run : %lluns", label, t1); + + u64 t2 =3D bench_decode_ns(enc, enc_len, decoded, reps, variant); + + kunit_info(test, "[%s] decode run : %lluns", label, t2); + + kfree(in); + kfree(enc); + kfree(decoded); +} + +static void base64_performance_tests(struct kunit *test) +{ + /* run on STD variant only */ + run_perf_and_check(test, "64B", 64, BASE64_STD); + run_perf_and_check(test, "1KB", 1024, BASE64_STD); +} + +/* ---------- Helpers for encode ---------- */ +static void expect_encode_ok(struct kunit *test, const u8 *src, int srclen, + const char *expected, bool padding, + enum base64_variant variant) +{ + char buf[128]; + int encoded_len =3D base64_encode(src, srclen, buf, padding, variant); + + buf[encoded_len] =3D '\0'; + + KUNIT_EXPECT_EQ(test, encoded_len, strlen(expected)); + KUNIT_EXPECT_STREQ(test, buf, expected); +} + +/* ---------- Helpers for decode ---------- */ +static void expect_decode_ok(struct kunit *test, const char *src, + const u8 *expected, int expected_len, bool padding, + enum base64_variant variant) +{ + u8 buf[128]; + int decoded_len =3D base64_decode(src, strlen(src), buf, padding, variant= ); + + KUNIT_EXPECT_EQ(test, decoded_len, expected_len); + KUNIT_EXPECT_MEMEQ(test, buf, expected, expected_len); +} + +static void expect_decode_err(struct kunit *test, const char *src, + int srclen, bool padding, + enum base64_variant variant) +{ + u8 buf[64]; + int decoded_len =3D base64_decode(src, srclen, buf, padding, variant); + + KUNIT_EXPECT_EQ(test, decoded_len, -1); +} + +/* ---------- Encode Tests ---------- */ +static void base64_std_encode_tests(struct kunit *test) +{ + /* With padding */ + expect_encode_ok(test, (const u8 *)"", 0, "", true, BASE64_STD); + expect_encode_ok(test, (const u8 *)"f", 1, "Zg=3D=3D", true, BASE64_STD); + expect_encode_ok(test, (const u8 *)"fo", 2, "Zm8=3D", true, BASE64_STD); + expect_encode_ok(test, (const u8 *)"foo", 3, "Zm9v", true, BASE64_STD); + expect_encode_ok(test, (const u8 *)"foob", 4, "Zm9vYg=3D=3D", true, BASE6= 4_STD); + expect_encode_ok(test, (const u8 *)"fooba", 5, "Zm9vYmE=3D", true, BASE64= _STD); + expect_encode_ok(test, (const u8 *)"foobar", 6, "Zm9vYmFy", true, BASE64_= STD); + + /* Extra cases with padding */ + expect_encode_ok(test, (const u8 *)"Hello, world!", 13, "SGVsbG8sIHdvcmxk= IQ=3D=3D", + true, BASE64_STD); + expect_encode_ok(test, (const u8 *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26, + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=3D", true, BASE64_STD); + expect_encode_ok(test, (const u8 *)"abcdefghijklmnopqrstuvwxyz", 26, + "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=3D", true, BASE64_STD); + expect_encode_ok(test, (const u8 *)"0123456789+/", 12, "MDEyMzQ1Njc4OSsv", + true, BASE64_STD); + + /* Without padding */ + expect_encode_ok(test, (const u8 *)"", 0, "", false, BASE64_STD); + expect_encode_ok(test, (const u8 *)"f", 1, "Zg", false, BASE64_STD); + expect_encode_ok(test, (const u8 *)"fo", 2, "Zm8", false, BASE64_STD); + expect_encode_ok(test, (const u8 *)"foo", 3, "Zm9v", false, BASE64_STD); + expect_encode_ok(test, (const u8 *)"foob", 4, "Zm9vYg", false, BASE64_STD= ); + expect_encode_ok(test, (const u8 *)"fooba", 5, "Zm9vYmE", false, BASE64_S= TD); + expect_encode_ok(test, (const u8 *)"foobar", 6, "Zm9vYmFy", false, BASE64= _STD); + + /* Extra cases without padding */ + expect_encode_ok(test, (const u8 *)"Hello, world!", 13, "SGVsbG8sIHdvcmxk= IQ", + false, BASE64_STD); + expect_encode_ok(test, (const u8 *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26, + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", false, BASE64_STD); + expect_encode_ok(test, (const u8 *)"abcdefghijklmnopqrstuvwxyz", 26, + "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo", false, BASE64_STD); + expect_encode_ok(test, (const u8 *)"0123456789+/", 12, "MDEyMzQ1Njc4OSsv", + false, BASE64_STD); +} + +/* ---------- Decode Tests ---------- */ +static void base64_std_decode_tests(struct kunit *test) +{ + /* -------- With padding --------*/ + expect_decode_ok(test, "", (const u8 *)"", 0, true, BASE64_STD); + expect_decode_ok(test, "Zg=3D=3D", (const u8 *)"f", 1, true, BASE64_STD); + expect_decode_ok(test, "Zm8=3D", (const u8 *)"fo", 2, true, BASE64_STD); + expect_decode_ok(test, "Zm9v", (const u8 *)"foo", 3, true, BASE64_STD); + expect_decode_ok(test, "Zm9vYg=3D=3D", (const u8 *)"foob", 4, true, BASE6= 4_STD); + expect_decode_ok(test, "Zm9vYmE=3D", (const u8 *)"fooba", 5, true, BASE64= _STD); + expect_decode_ok(test, "Zm9vYmFy", (const u8 *)"foobar", 6, true, BASE64_= STD); + expect_decode_ok(test, "SGVsbG8sIHdvcmxkIQ=3D=3D", (const u8 *)"Hello, wo= rld!", 13, + true, BASE64_STD); + expect_decode_ok(test, "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=3D", + (const u8 *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26, true, BASE64_STD); + expect_decode_ok(test, "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=3D", + (const u8 *)"abcdefghijklmnopqrstuvwxyz", 26, true, BASE64_STD); + + /* Error cases */ + expect_decode_err(test, "Zg=3D!", 4, true, BASE64_STD); + expect_decode_err(test, "Zm$=3D", 4, true, BASE64_STD); + expect_decode_err(test, "Z=3D=3D=3D", 4, true, BASE64_STD); + expect_decode_err(test, "Zg", 2, true, BASE64_STD); + expect_decode_err(test, "Zm9v=3D=3D=3D=3D", 8, true, BASE64_STD); + expect_decode_err(test, "Zm=3D=3DA", 5, true, BASE64_STD); + + { + char with_nul[4] =3D { 'Z', 'g', '\0', '=3D' }; + + expect_decode_err(test, with_nul, 4, true, BASE64_STD); + } + + /* -------- Without padding --------*/ + expect_decode_ok(test, "", (const u8 *)"", 0, false, BASE64_STD); + expect_decode_ok(test, "Zg", (const u8 *)"f", 1, false, BASE64_STD); + expect_decode_ok(test, "Zm8", (const u8 *)"fo", 2, false, BASE64_STD); + expect_decode_ok(test, "Zm9v", (const u8 *)"foo", 3, false, BASE64_STD); + expect_decode_ok(test, "Zm9vYg", (const u8 *)"foob", 4, false, BASE64_STD= ); + expect_decode_ok(test, "Zm9vYmE", (const u8 *)"fooba", 5, false, BASE64_S= TD); + expect_decode_ok(test, "Zm9vYmFy", (const u8 *)"foobar", 6, false, BASE64= _STD); + expect_decode_ok(test, "TWFu", (const u8 *)"Man", 3, false, BASE64_STD); + expect_decode_ok(test, "SGVsbG8sIHdvcmxkIQ", (const u8 *)"Hello, world!",= 13, + false, BASE64_STD); + expect_decode_ok(test, "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", + (const u8 *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26, false, BASE64_STD); + expect_decode_ok(test, "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo", + (const u8 *)"abcdefghijklmnopqrstuvwxyz", 26, false, BASE64_STD); + expect_decode_ok(test, "MDEyMzQ1Njc4OSsv", (const u8 *)"0123456789+/", 12, + false, BASE64_STD); + + /* Error cases */ + expect_decode_err(test, "Zg=3D!", 4, false, BASE64_STD); + expect_decode_err(test, "Zm$=3D", 4, false, BASE64_STD); + expect_decode_err(test, "Z=3D=3D=3D", 4, false, BASE64_STD); + expect_decode_err(test, "Zg=3D", 3, false, BASE64_STD); + expect_decode_err(test, "Zm9v=3D=3D=3D=3D", 8, false, BASE64_STD); + expect_decode_err(test, "Zm=3D=3Dv", 4, false, BASE64_STD); + + { + char with_nul[4] =3D { 'Z', 'g', '\0', '=3D' }; + + expect_decode_err(test, with_nul, 4, false, BASE64_STD); + } +} + +/* ---------- Variant tests (URLSAFE / IMAP) ---------- */ +static void base64_variant_tests(struct kunit *test) +{ + const u8 sample1[] =3D { 0x00, 0xfb, 0xff, 0x7f, 0x80 }; + char std_buf[128], url_buf[128], imap_buf[128]; + u8 back[128]; + int n_std, n_url, n_imap, m; + int i; + + n_std =3D base64_encode(sample1, sizeof(sample1), std_buf, false, BASE64_= STD); + n_url =3D base64_encode(sample1, sizeof(sample1), url_buf, false, BASE64_= URLSAFE); + std_buf[n_std] =3D '\0'; + url_buf[n_url] =3D '\0'; + + for (i =3D 0; i < n_std; i++) { + if (std_buf[i] =3D=3D '+') + std_buf[i] =3D '-'; + else if (std_buf[i] =3D=3D '/') + std_buf[i] =3D '_'; + } + KUNIT_EXPECT_STREQ(test, std_buf, url_buf); + + m =3D base64_decode(url_buf, n_url, back, false, BASE64_URLSAFE); + KUNIT_EXPECT_EQ(test, m, (int)sizeof(sample1)); + KUNIT_EXPECT_MEMEQ(test, back, sample1, sizeof(sample1)); + + n_std =3D base64_encode(sample1, sizeof(sample1), std_buf, false, BASE64= _STD); + n_imap =3D base64_encode(sample1, sizeof(sample1), imap_buf, false, BASE6= 4_IMAP); + std_buf[n_std] =3D '\0'; + imap_buf[n_imap] =3D '\0'; + + for (i =3D 0; i < n_std; i++) + if (std_buf[i] =3D=3D '/') + std_buf[i] =3D ','; + KUNIT_EXPECT_STREQ(test, std_buf, imap_buf); + + m =3D base64_decode(imap_buf, n_imap, back, false, BASE64_IMAP); + KUNIT_EXPECT_EQ(test, m, (int)sizeof(sample1)); + KUNIT_EXPECT_MEMEQ(test, back, sample1, sizeof(sample1)); + + { + const char *bad =3D "Zg=3D=3D"; + u8 tmp[8]; + + m =3D base64_decode(bad, strlen(bad), tmp, false, BASE64_URLSAFE); + KUNIT_EXPECT_EQ(test, m, -1); + + m =3D base64_decode(bad, strlen(bad), tmp, false, BASE64_IMAP); + KUNIT_EXPECT_EQ(test, m, -1); + } +} + +/* ---------- Test registration ---------- */ +static struct kunit_case base64_test_cases[] =3D { + KUNIT_CASE(base64_performance_tests), + KUNIT_CASE(base64_std_encode_tests), + KUNIT_CASE(base64_std_decode_tests), + KUNIT_CASE(base64_variant_tests), + {} +}; + +static struct kunit_suite base64_test_suite =3D { + .name =3D "base64", + .test_cases =3D base64_test_cases, +}; + +kunit_test_suite(base64_test_suite); + +MODULE_AUTHOR("Guan-Chun Wu <409411716@gms.tku.edu.tw>"); +MODULE_DESCRIPTION("KUnit tests for Base64 encoding/decoding, including pe= rformance checks"); +MODULE_LICENSE("GPL"); --=20 2.34.1 From nobody Sun Dec 14 19:56:38 2025 Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B63822DCC06 for ; Fri, 14 Nov 2025 06:02:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100149; cv=none; b=smjHmzGtLRlF1Xn6OjuG9T8YxR6X8dD65UdXcT/ICRCzVGU347kw4JU868vxTFKzXWBbj+tkHtR0DNoaoy/eyrYZchaqNUXFnG9wZ2yN3dLRM3fuVVkkVgfmastqu25A+QkgchQjZCy13UEl9MpI2EIXZbJ2LCfJuWvHjDJ2XrM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100149; c=relaxed/simple; bh=I6hn5XyUpnrWRuQcjJdlpYH7Q9/3VAy8I4U1WzKLW0k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GiL0WU74AWl4ZzjJky43dD2VmC+gNgJF+PIK2J/Cs5iVTDMLKfCslI3+RINDsuifWOBxzGv5diXfBncIjL0cePGcZ/UzC6XFcqJe/RQLf4MKmRhIV0gv0RmVeDB7AkG0sS3b5Ujaes/lQrmaWvNjVFKuyRjXvWcaz9TQSObFnyo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw; spf=pass smtp.mailfrom=gms.tku.edu.tw; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b=KXYUukLq; arc=none smtp.client-ip=209.85.214.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b="KXYUukLq" Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-298039e00c2so19941245ad.3 for ; Thu, 13 Nov 2025 22:02:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1763100147; x=1763704947; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ERv4XtgoXPP2dPnpwcSEeS4AUqPV+CdFVlWhf34t39A=; b=KXYUukLqInLfvVAR8TiBnG8x2Q85rxVFmReEBqT7PAsEV3RUlxmViDSpKUJG30Pc+B jwnbGcunncfo82I3xk5tbH6J6PwbPZ09pydzcfB2peyKakQ+NYv1ffuZbPLThVYxRGFB 2W3y2OUIqngzCaNjsxzEwJsFkN/WCelB7f0dJQVoLJuL5B9zuxOCTCE0zV5lCLq+I+v8 8VcYP6HAszg8US8rz4QI1tAnYjMybTDBM0SRF6l7tTKvCEPIjVT/jVmIlSR31bk9Mqn4 tcsfB69z3x/+Yp77fKmUJHsAkaamPsIeviNtT05YMFx5+8Q30p4q9y3dsngWQKPxnJ5H 22Dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763100147; x=1763704947; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ERv4XtgoXPP2dPnpwcSEeS4AUqPV+CdFVlWhf34t39A=; b=pKyJOrfUNWp/GXk3fIMECJXHwiSRxeSMlWA0rYMNxBvFDMJrL0HfH8xisRjfp07GBe XvyUk69mTkVy4qK2CdqSWGes57/ahN+Is9MkEa+YkbBzxKh1vuZqLxHFkBS8MALNMpBE RFF954Vn1ojpeQx6JvrxznASqrn8KlCZj5pP+u+JLEx4pdQ58MEukUAQvlJYrL+qSzC0 yXi766PSxQ2VdTu3k4bk7TnQ0dvM9HyODxcfeTZTNVzpNCCRjQI75UAfUXIufEC8z2yT 2/b73Al7OYUFWICk5uXjOWZe9QNy2I5Fvgguhf+/7EAgSJTVKCCBQnG9I6qS8v8bBV+f pXoA== X-Forwarded-Encrypted: i=1; AJvYcCWndQQWslVTlEgPB6lW14TNgwsUcX2U4kiCV4dADxXfq4ahTtA8uTLnI6U1YvQOgS58jE1DH8rLl5wiOuc=@vger.kernel.org X-Gm-Message-State: AOJu0YynVCakUKnYggHcprJOlOmDriqH5OKrvWOJUdsJz+IE/d4M1mXw nSYwiLtbPEU8DQXvGBEF8ORrLaXos65i5ulX2st39/ePeIq+ShJYOtRj8Gd5vp2a/bo= X-Gm-Gg: ASbGnctS0EQjhJBFerb9uwGafaPAbHT/L2OmeCNlucDlBI/mYOGiqwEt5Gqpa0uQKX9 HCBTW2OtCdvxen1gJnGBzWd5Q99hkXgCSlkpjg3mhoM9PNfmb0S4bisTrekvmoh1U+6SBp7elVh BP6/TguQCvH9xUH1VQI27aXl9je4QA2w6TpZi1lb2V7PwfQRPWAGbCPru0X6sjK7coCy97QnxiP eb35QjNlRXdqtbxzb31jpOcBzQ8vTi4isBBl5jieGrOdwaKLyWXUJBIAa1B4w/DNKVZlG4nv1mx naed6OI3moBr/Qei04XV71Um5TMTfFAkDMB+/zthN4QExflf/zGix20zQb+WKAy8/MnJZEdAkb8 tJQcdpQOVcH//qyzohsy6bZDPOzjEClXAcdLdMwVh/wwI34hYZ42s2AxDB+FGphqbxGmIvhDUyj hIw1kfSi4PHTitbx7gBVYL3Cim X-Google-Smtp-Source: AGHT+IFs317cxuw2DDSKPoB1op+RLqXuzE2pstLiig2tLA8KeXhRrXBdYzwc2MB74Tur9nS/jMyR0Q== X-Received: by 2002:a17:902:cf08:b0:265:47:a7bd with SMTP id d9443c01a7336-2986a6bcff3mr20918665ad.4.1763100146747; Thu, 13 Nov 2025 22:02:26 -0800 (PST) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:22d2:323c:497d:adbd]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2985c2bf17dsm42818665ad.94.2025.11.13.22.02.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 22:02:26 -0800 (PST) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, andriy.shevchenko@intel.com, axboe@kernel.dk, ceph-devel@vger.kernel.org, david.laight.linux@gmail.com, ebiggers@kernel.org, hch@lst.de, home7438072@gmail.com, idryomov@gmail.com, jaegeuk@kernel.org, kbusch@kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvme@lists.infradead.org, sagi@grimberg.me, tytso@mit.edu, visitorckw@gmail.com, xiubli@redhat.com Subject: [PATCH v5 5/6] fscrypt: replace local base64url helpers with lib/base64 Date: Fri, 14 Nov 2025 14:02:21 +0800 Message-Id: <20251114060221.89734-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251114055829.87814-1-409411716@gms.tku.edu.tw> References: <20251114055829.87814-1-409411716@gms.tku.edu.tw> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Reviewed-by: Kuan-Wei Chiu Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> --- fs/crypto/fname.c | 89 ++++------------------------------------------- 1 file changed, 6 insertions(+), 83 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 8e4c213d418b..a9a4432d12ba 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -16,6 +16,7 @@ #include #include #include +#include =20 #include "fscrypt_private.h" =20 @@ -71,7 +72,7 @@ struct fscrypt_nokey_name { =20 /* 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) =20 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; } =20 -static const char base64url_table[65] =3D - "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. '=3D'-padding isn't= used, - * as it's unneeded and not required by the RFC. base64url is used instea= d 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 =3D 0; - int bits =3D 0; - int i; - char *cp =3D dst; - - for (i =3D 0; i < srclen; i++) { - ac =3D (ac << 8) | src[i]; - bits +=3D 8; - do { - bits -=3D 6; - *cp++ =3D base64url_table[(ac >> bits) & 0x3f]; - } while (bits >=3D 6); - } - if (bits) - *cp++ =3D 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 w= ith - * URL and Filename Safe Alphabet" specified by RFC 4648. '=3D'-padding i= sn'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 =3D 0; - int bits =3D 0; - int i; - u8 *bp =3D dst; - - for (i =3D 0; i < srclen; i++) { - const char *p =3D strchr(base64url_table, src[i]); - - if (p =3D=3D NULL || src[i] =3D=3D 0) - return -1; - ac =3D (ac << 6) | (p - base64url_table); - bits +=3D 6; - if (bits >=3D 8) { - bits -=3D 8; - *bp++ =3D (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 =3D FSCRYPT_NOKEY_NAME_MAX; } - oname->len =3D fscrypt_base64url_encode((const u8 *)&nokey_name, size, - oname->name); + oname->len =3D 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 str= uct qstr *iname, if (fname->crypto_buf.name =3D=3D NULL) return -ENOMEM; =20 - ret =3D fscrypt_base64url_decode(iname->name, iname->len, - fname->crypto_buf.name); + ret =3D 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 !=3D FSCRYPT_NOKEY_NAME_MAX)) { --=20 2.34.1 From nobody Sun Dec 14 19:56:38 2025 Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 822992EB5B4 for ; Fri, 14 Nov 2025 06:02:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100170; cv=none; b=mjYD41NR7jCceAIKPTvGvYnalQUwreNKoKygJyBdBb1c4S2xm4mH9kXTED6Gr4sXSrMJcCwdDH1xm4jH6gFmEqIvddGeNhq6ccxn72Xj0XsPRXttSQOHboRnjc5Vs4nEADcYmV6IUwf4lH/2YdE8ddA17yze/epDBRUH4OpMENA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763100170; c=relaxed/simple; bh=gDlG7kblX5YeTHlzPrAqnEVGCYQCrx9weplGIGbrDpA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cmA65ppKeVgZRvScQQT/tSbHTT+KSeFIxOyaOaDBq0WQoD+Fp5A0tIFLK6K5crFkiZFIZKqS3N98z0qEaNZIz3Y5HgnjA2SG3Jek/Rcw9xEBP07VB3YQK654IiD8a38MckxHvwVK3I1CPNMOgq7Pl6hFWH8CoP/zF+YVLC7GXMU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw; spf=pass smtp.mailfrom=gms.tku.edu.tw; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b=ZFGM+JFR; arc=none smtp.client-ip=209.85.210.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gms.tku.edu.tw Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20230601.gappssmtp.com header.i=@gms-tku-edu-tw.20230601.gappssmtp.com header.b="ZFGM+JFR" Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-7a9c64dfa8aso1434316b3a.3 for ; Thu, 13 Nov 2025 22:02:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1763100168; x=1763704968; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=y3VNVy+UYeqY3IVTtkh/AbSvZ3E8GHu4GINXGK2iL3Y=; b=ZFGM+JFRrpC2719pwW9w3/ChjvaR2tTMKgsVK1oUWlePszG4GrKOiWk4H6P550LKI+ DVgEquE55pjrW/0WvmBeCsojIMDM579HC3DUxxr4lr1i+90jIcFC6hosyEv5UtoacMXj i2Xr0IZPS1DlN0KGWj0Rx6cH603C31FKKw9kBlH28bID43dBfVX4Ra5W0D2kD7dDaDUI 9CmLM44Tb/5+7ES85BTSXL5AWcKJtxDkDfn6Xj4ISpsnHDLpI8eTwUShWX+gCevZt//0 SagegkvypNQ4tWRpD7SOzLU1cCijbVanaP0sd97xQQy11RTV7dMUnu2pWwbgcOHWrLU+ zgjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763100168; x=1763704968; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=y3VNVy+UYeqY3IVTtkh/AbSvZ3E8GHu4GINXGK2iL3Y=; b=e4xSbKrkHfxV5Ai4gG2vkIEivOfa17uqNp8MI0GRsx/QX1MityF0KFDU1ZNuAIAfnu QfxEK3PB5AJVeoNflAXqr4UuuwEAjySskVV83BHxFAzmwxkwLc2iO+vNyuliUuSFBio7 bycSzMqhJsfrHXLLRS2juZWpaTGslXN65PeQOpngStNJTutQIxP1nTTj+8S8USQbXL/Z Y03CHIIAp/FgBUyyHQnnZqoqjADpp2s6/HU4f3KXeDBUFwkLzz8g6m1T80oBdDepw0L7 9pVUssjUcO5YCafcN/tTH4srldxarY4N0QT/GFyDSe/8aWxr4g0H0FrT0uJMmAqGtnnP Brrg== X-Forwarded-Encrypted: i=1; AJvYcCWHgNqX54xsmH2JRTYbIbWnW3OwnsA8FkNRcOEgFYyjW+BNKgG6S06LPs8um3ZnW0Ujqugk/W7w862ZdSw=@vger.kernel.org X-Gm-Message-State: AOJu0Yynoz+f/O6/yPmt880QUWhpB6cqrzEK5EmNdoguKVmBpbv/UkBx 7k13EH4to+HjcG1dnkMpazJnvfBZG3yF/obqiZ8rXM/k8tRh1ik//ZPCy7MjwoYppc0= X-Gm-Gg: ASbGnctaapYFiyds8yVT95TgaMDqCWQL+4Gf12VX7mqKhZJbewgDabTbLjo6dEEvUgW FLZIAkJTqZ0gQi5tjndweTMVuWoJOCqTxJnBMSBtcS/UnRxLF70EGQqZXu4zUYvns8qS1cVuGPE 1VPUf0ewN9VY5hTAHpuy0hKM/Gzu44+8HaqzvFYo3Km+1uoay7t7hkn5rG//RehKOxWux6wOgAY pJt2VWDIuSVNkv2yhroRy3/hk0AbiaYeTnVEJZhanSUl+V/nyxcd6O6dpa2i8QDw3xkRvuM0Rfa VdcFdIXuQeQrkkHIxHj/W3rlLG5/cgL+pX/wVPt+IA1hI40NordVsDUzmS7ct5o0fjDvf3HWnvQ 221hMXY2w0TEkTGwBhTwy83HMV8Twqh+2nSPnyZbYTJQGWCoEV86Q5N/88SJitRIAJp9NPRyVDg SjpLfJsNSf5x0CNG2aXOUySifNXqOafjY8yWM= X-Google-Smtp-Source: AGHT+IFu12NV5C3ZMb+GzTshy782WYZvWJoPnURdrRS7I9I9BogTqLlIkKyKPKA2EoshONrHEKmUHw== X-Received: by 2002:a05:6a00:4b12:b0:7a4:f552:b522 with SMTP id d2e1a72fcca58-7ba3c669976mr2406190b3a.27.1763100167825; Thu, 13 Nov 2025 22:02:47 -0800 (PST) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:22d2:323c:497d:adbd]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7ba438bed8csm1236316b3a.53.2025.11.13.22.02.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 22:02:47 -0800 (PST) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, andriy.shevchenko@intel.com, axboe@kernel.dk, ceph-devel@vger.kernel.org, david.laight.linux@gmail.com, ebiggers@kernel.org, hch@lst.de, home7438072@gmail.com, idryomov@gmail.com, jaegeuk@kernel.org, kbusch@kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvme@lists.infradead.org, sagi@grimberg.me, tytso@mit.edu, visitorckw@gmail.com, xiubli@redhat.com Subject: [PATCH v5 6/6] ceph: replace local base64 helpers with lib/base64 Date: Fri, 14 Nov 2025 14:02:40 +0800 Message-Id: <20251114060240.89965-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251114055829.87814-1-409411716@gms.tku.edu.tw> References: <20251114055829.87814-1-409411716@gms.tku.edu.tw> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Remove the ceph_base64_encode() and ceph_base64_decode() functions and replace their usage with the generic base64_encode() and base64_decode() helpers from lib/base64. This eliminates the custom implementation in Ceph, reduces code duplication, and relies on the shared Base64 code in lib. The helpers preserve RFC 3501-compliant 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 local implementation. Reviewed-by: Kuan-Wei Chiu Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Reviewed-by: Viacheslav Dubeyko Tested-by: Viacheslav Dubeyko --- fs/ceph/crypto.c | 60 ++++-------------------------------------------- fs/ceph/crypto.h | 6 +---- fs/ceph/dir.c | 5 ++-- fs/ceph/inode.c | 2 +- 4 files changed, 9 insertions(+), 64 deletions(-) diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c index 7026e794813c..b6016dcffbb6 100644 --- a/fs/ceph/crypto.c +++ b/fs/ceph/crypto.c @@ -15,59 +15,6 @@ #include "mds_client.h" #include "crypto.h" =20 -/* - * The base64url encoding used by fscrypt includes the '_' character, whic= h may - * cause problems in snapshot names (which can not start with '_'). Thus,= we - * used the base64 encoding defined for IMAP mailbox names (RFC 3501) inst= ead, - * which replaces '-' and '_' by '+' and ','. - */ -static const char base64_table[65] =3D - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; - -int ceph_base64_encode(const u8 *src, int srclen, char *dst) -{ - u32 ac =3D 0; - int bits =3D 0; - int i; - char *cp =3D dst; - - for (i =3D 0; i < srclen; i++) { - ac =3D (ac << 8) | src[i]; - bits +=3D 8; - do { - bits -=3D 6; - *cp++ =3D base64_table[(ac >> bits) & 0x3f]; - } while (bits >=3D 6); - } - if (bits) - *cp++ =3D base64_table[(ac << (6 - bits)) & 0x3f]; - return cp - dst; -} - -int ceph_base64_decode(const char *src, int srclen, u8 *dst) -{ - u32 ac =3D 0; - int bits =3D 0; - int i; - u8 *bp =3D dst; - - for (i =3D 0; i < srclen; i++) { - const char *p =3D strchr(base64_table, src[i]); - - if (p =3D=3D NULL || src[i] =3D=3D 0) - return -1; - ac =3D (ac << 6) | (p - base64_table); - bits +=3D 6; - if (bits >=3D 8) { - bits -=3D 8; - *bp++ =3D (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 l= en) { struct ceph_inode_info *ci =3D ceph_inode(inode); @@ -318,7 +265,7 @@ int ceph_encode_encrypted_dname(struct inode *parent, c= har *buf, int elen) } =20 /* base64 encode the encrypted name */ - elen =3D ceph_base64_encode(cryptbuf, len, p); + elen =3D base64_encode(cryptbuf, len, p, false, BASE64_IMAP); doutc(cl, "base64-encoded ciphertext name =3D %.*s\n", elen, p); =20 /* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */ @@ -412,7 +359,8 @@ int ceph_fname_to_usr(const struct ceph_fname *fname, s= truct fscrypt_str *tname, tname =3D &_tname; } =20 - declen =3D ceph_base64_decode(name, name_len, tname->name); + declen =3D base64_decode(name, name_len, + tname->name, false, BASE64_IMAP); if (declen <=3D 0) { ret =3D -EIO; goto out; @@ -426,7 +374,7 @@ int ceph_fname_to_usr(const struct ceph_fname *fname, s= truct fscrypt_str *tname, =20 ret =3D fscrypt_fname_disk_to_usr(dir, 0, 0, &iname, oname); if (!ret && (dir !=3D fname->dir)) { - char tmp_buf[CEPH_BASE64_CHARS(NAME_MAX)]; + char tmp_buf[BASE64_CHARS(NAME_MAX)]; =20 name_len =3D snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%ld", oname->len, oname->name, dir->i_ino); diff --git a/fs/ceph/crypto.h b/fs/ceph/crypto.h index 23612b2e9837..b748e2060bc9 100644 --- a/fs/ceph/crypto.h +++ b/fs/ceph/crypto.h @@ -8,6 +8,7 @@ =20 #include #include +#include =20 #define CEPH_FSCRYPT_BLOCK_SHIFT 12 #define CEPH_FSCRYPT_BLOCK_SIZE (_AC(1, UL) << CEPH_FSCRYPT_BLOCK_SHIFT) @@ -89,11 +90,6 @@ static inline u32 ceph_fscrypt_auth_len(struct ceph_fscr= ypt_auth *fa) */ #define CEPH_NOHASH_NAME_MAX (180 - SHA256_DIGEST_SIZE) =20 -#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); =20 void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc); diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index d18c0eaef9b7..0fa7c7777242 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -998,13 +998,14 @@ static int prep_encrypted_symlink_target(struct ceph_= mds_request *req, if (err) goto out; =20 - req->r_path2 =3D kmalloc(CEPH_BASE64_CHARS(osd_link.len) + 1, GFP_KERNEL); + req->r_path2 =3D kmalloc(BASE64_CHARS(osd_link.len) + 1, GFP_KERNEL); if (!req->r_path2) { err =3D -ENOMEM; goto out; } =20 - len =3D ceph_base64_encode(osd_link.name, osd_link.len, req->r_path2); + len =3D base64_encode(osd_link.name, osd_link.len, + req->r_path2, false, BASE64_IMAP); req->r_path2[len] =3D '\0'; out: fscrypt_fname_free_buffer(&osd_link); diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index a6e260d9e420..b691343cb7f1 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -958,7 +958,7 @@ static int decode_encrypted_symlink(struct ceph_mds_cli= ent *mdsc, if (!sym) return -ENOMEM; =20 - declen =3D ceph_base64_decode(encsym, enclen, sym); + declen =3D base64_decode(encsym, enclen, sym, false, BASE64_IMAP); if (declen < 0) { pr_err_client(cl, "can't decode symlink (%d). Content: %.*s\n", --=20 2.34.1