From nobody Wed Oct 1 23:36:03 2025 Received: from mail-pl1-f176.google.com (mail-pl1-f176.google.com [209.85.214.176]) (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 2DD1C2AE8D for ; Fri, 26 Sep 2025 06:55:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869723; cv=none; b=o77M5SQGt4v/3nqx05zGjQUfuUoSHNMuikfQTmAD0ZhXyB6sBngpej2XFPsp/r20LsWKU+flDUFJrOotQ0i8IwaRAvSNEf6uIvQ8YX3jx9Ab0qShrv5r+/CagNRCInelRYWbfvuJmY8p4i/4qNrrJo+0rFkvmvGikU8f281SSR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869723; c=relaxed/simple; bh=aeR0jKC5/gtxKlaD5MnxYFmC8w01kOImtqSZxxRwN6g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=JCq0QO/T0dd9CWQqr54CThCrX7+hVpI3aIwkxnJP1jHySzOerwqvGaZzeygPgerSkoUaGbtz3beRVahdtBHXaxTeHHDmKdiMC16LdDquaGCLhyNczZ+xh1hhD2x5S5PbsFsXX420MlPkdcvzITEoX2vAgr3sleNqUgP/VGx48Lw= 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=ojqeY5vJ; arc=none smtp.client-ip=209.85.214.176 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="ojqeY5vJ" Received: by mail-pl1-f176.google.com with SMTP id d9443c01a7336-269639879c3so17860115ad.2 for ; Thu, 25 Sep 2025 23:55:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1758869720; x=1759474520; 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=vj5UPqG+5RgyX7bCn1GnWx3nhSDF8xeGhtJtpVZ8+PA=; b=ojqeY5vJGVrUy2066SXDaV8raKhpMZSwysegw5Yl0pXwi0STOOE574Kgk4r/8OOv0y 2OosDwp5iGcV1GS58X/KkNfaafyDZoSIQdaRYUBZvHO4yFVCXKlQss33DrOSSlPL3EKb zFlNNbct5luuMocyzL+4x7oGGYzOuS+uIrlTCGirmwadB1STmcZk4HCGSgsL2lLlh6+K d5S9yq+UTkFwcUk4YiscsPPlbf1PxKwywywEf7wb7R5vWVNwY/Q8unoNP2ugVVt70IX2 NCdtDKzmdCdM7VgKlKsc7Ljz0LgNElGTj7sqvFECllind2tFL+LEfyxQDS+8Bz1G/iej YvcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758869720; x=1759474520; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vj5UPqG+5RgyX7bCn1GnWx3nhSDF8xeGhtJtpVZ8+PA=; b=qEQxXO6ZCIfmDOQKPvrsbqBpN3D5Bhdu7QQ3YYabG18nEFTLFeXsfpz5ZhRj05mZmw tNNYFu1ilAjcEJz3+6nFvcsKBWLuJwfkNl2w68CD7spOQMgZy+t1ge4Eq2GMi6rSVPTz AV8+rJEHiAaGp3EV4PndXmwqSl0D6Xjj/BybWhhUDMh0xEGxpEA4v5sGst96C1rPERmf w9csPG1/OfpP8EVoAV4s1C3vSp1aAsXbEvhnroIhIsRmZuU5IDm8ckWoErEpn2avvPiv M9iMj7QxQ2PAHK69ZMDe/BzxfMeXKeUfNjwcuqo9rMukwe3Cj0sXOmJTrITv1Qu6eAP2 bUwg== X-Forwarded-Encrypted: i=1; AJvYcCUE/OnFxu/m2a1Qp8OHv7Un8LOs0kcei8RJ3Wa1xliRgEnNZHFYAu2q8ful36djButXgfMZM2uebWs1muk=@vger.kernel.org X-Gm-Message-State: AOJu0YzCKXHOWWKbWw90dBle5m6oIp2hGyg0s64E2EdqbDbgedLG9AI5 YjQE2b5MJs3ThwQgPcbI8QLjWbCJm3lb6lwuJmtDu3nyO+BTC+IoY9V3f6kFjzLf/UY= X-Gm-Gg: ASbGncsnjKnK6AlMP7jmSqRG1WX6C6wEFZTwB96mhUQzd014lNZzxm1KZyCOk6AgLSt igPiTLes8FlDtwfEMVuGjpbbcK2cOF/UopgXulNTXSz4SMBUJjPWJCX4qQ3RgUSegBZke/SLkmD ts+p9R54KtqfbL3lRnQNz31HVnww2R2nBSb6rEmmsh2PmT1VeIHmEu/erWjiDrcc0kMTa/TcjXS ixLFfYiJlafOu0yHW4B9viZBfDWBViyJ78jQbPh+iRrDMykOE59Z5kvnAWSYCTIXmLHYuyt4xTe 4KS9ZLhR9/KdVw3z2vL0yBewI1gX+KB57E8nONbyMjLmLcW04FucV/7LzcGQt+ph3vyjzPi6X11 Li1Llt4GKY8CFnpCYFK9jnP3gMAt6lU4ryyTCm1sFRbpEVg8= X-Google-Smtp-Source: AGHT+IEkWnB3Y/bobVLXTDCV7iCFw6lqnV0G3iUe38ErBh+GUhNpr3gTNCP4/CRqqoUyTcF+cvJjXA== X-Received: by 2002:a17:902:f647:b0:269:a8a8:4029 with SMTP id d9443c01a7336-27ed49df2c1mr81059935ad.5.1758869720526; Thu, 25 Sep 2025 23:55:20 -0700 (PDT) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:94ad:363a:4161:464c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-27ed6882227sm44681455ad.82.2025.09.25.23.55.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Sep 2025 23:55:19 -0700 (PDT) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, axboe@kernel.dk, ceph-devel@vger.kernel.org, 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 v3 1/6] lib/base64: Add support for multiple variants Date: Fri, 26 Sep 2025 14:55:12 +0800 Message-Id: <20250926065512.13881-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250926065235.13623-1-409411716@gms.tku.edu.tw> References: <20250926065235.13623-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> --- drivers/nvme/common/auth.c | 4 ++-- include/linux/base64.h | 10 ++++++++-- lib/base64.c | 39 ++++++++++++++++++++++---------------- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/nvme/common/auth.c b/drivers/nvme/common/auth.c index 91e273b89..5fecb53cb 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 660d4cb1e..a2c6c9222 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 b736a7a43..1af557785 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]; @@ -57,25 +62,27 @@ int base64_encode(const u8 *src, int srclen, char *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]); --=20 2.34.1 From nobody Wed Oct 1 23:36:03 2025 Received: from mail-pf1-f179.google.com (mail-pf1-f179.google.com [209.85.210.179]) (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 1232C27E040 for ; Fri, 26 Sep 2025 06:56:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869765; cv=none; b=PWKhYkI9UVZTmQxKJrljkVydnjNYWmQhC20Sj14y/IdG4pt45EYvtJn1ajZKLJvziCSxRCfD4Xwb/6PUegjuhTQvfc0JFLuEU8M0ZZlJ8+07xn0DAlRRj6xVkgu+YJfMKuahwllszHSb/R5HAgCs4TjlHfQNbCR5DOUyyg+71hM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869765; c=relaxed/simple; bh=+4YCN2dmmyfb7+Hl1S6/hlw/+FbPhHYA7RWFcIkHebg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TiBRXZYXQ3sWmt93dVistcgdw21kx1qTraC1DqXOIzMPkLgtSbQGWHV7mBPExxmAZ/9iuOJkIMXLUImGkca3ikwCHPYtVoxr87KHOli0p+UCmpj0qknIiTwZ0u4nNIAe1WEgwe+r9At0zv0og6c/YHmKoc7IT9bDTASg4AeY2mk= 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=JN7Jyh35; arc=none smtp.client-ip=209.85.210.179 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="JN7Jyh35" Received: by mail-pf1-f179.google.com with SMTP id d2e1a72fcca58-77f7da24397so1668565b3a.2 for ; Thu, 25 Sep 2025 23:56:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1758869763; x=1759474563; 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=eoUrxrA1gUNwCBEXabdQA4Jiv6vtYFchaTivJjmbSzM=; b=JN7Jyh35hvJxqKA0eciejU9HR/AggXWfxW842Us2/elza8ebZl/M6tJUk52hsdIqBW W9IS4Xp8Pmwht4WnmsBpoUkWYsIaf9NgkaqfoHv7yzgRQU0alsC7PXfOQEDm6ztWlcLR D8hXDXByInnZymjNFQEi7JhMcfOasIcjNRMqgKpPIYweTZlekjs45IDHAjYQCRCRmE6u PuM1043istvCMg45FJxoFhOwPscckrfvPXLKoEnw6i43TDTDMjHqJB3oBUGVYJOvqZFF zxFY/AC2EuU186MUEDhdxVWbKcgnNyj8dDVeBtg1ZfwxG7gml+pwFKYvbZk8uiKL/fJT dqhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758869763; x=1759474563; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eoUrxrA1gUNwCBEXabdQA4Jiv6vtYFchaTivJjmbSzM=; b=ImQ+d8d/IgveSVm3piIFvnpaEKMzWTpta7NmyihWYpX+sGlrBlPZYn6aBi9lIkAFdo 8Na7yB77AoeH1OrRVbYmfKEXoL2wFasbvC8ShQfrcdEU59v4fx9mO0h/fI/enP0HphJT dQMqEwaDgMdsMfF8g9vGIfgiVqMge4j+pKvh0KGeJXrqp5OpnM3ROn/UBsnZ0PeezOKl Mhb7rb/TMK1hnQHa6Nf8WAv7DEZktmM7ueHcx9RZuHkyd29VL00/x/uxioIB5wycVxim DNlxRIBqSHuKg7cco7K1+5pPVF+w9H8wPuPa/+RCOhna10Nrx26ruFWqUFzt53Vw1wra R0+Q== X-Forwarded-Encrypted: i=1; AJvYcCWtbt4di6xc5Qhjp+m3BblM0HnoSV2IrJ4RM700Qm2cYS/zD45hHIt/0/hcCut39sgmKbRDy/ASG3iyeE8=@vger.kernel.org X-Gm-Message-State: AOJu0YyOsAi+VhAVja3Gt+tH3NQJt9M0yDGy7uZ5CjrIEJOc0b7P3sGP VJ6smDDN/tCMMzyqW1eZeGMmzUoijoImnOW9CZWCuBKwcPsHEPSkxOo77awFNp7YE/w= X-Gm-Gg: ASbGncvQV2IbVs3EMC3pGqt2BOOa5xpI8b4kLyJReEaIloLlEqW3b+X259yVm5Y5fko khs+t3EVt0JJspK82r+OoIGhQFRFAicXYoZrx94Yowl313Dq0ZvoWXwfMB8NxVIwKNBFr5u8r7o qvOyFyqhd+TkmWcoHgUJl3poxHDNimA9wAQh/fxwvEKqafoQlyFYckavx6rJPFnq8j3eA+lVx4P XN0+Mc9zKwgsqmBmAkZlIxehruAxGlk06TBpf9ad/ifeGbFvzoZBwUaq5cVluZ9Rmg8iBsFJTDs s5nMJ0ZwIQvR+1qECx4QdMrBRdCl2JRT645bD1kqNbC9+EQmeIESKvD2MoeK7Nu+l3FuSlciuc+ WBReXym67K+RAKIZCVFEF0323NCLSIndaKXzm7DS+h62dnYw= X-Google-Smtp-Source: AGHT+IGYm5AiCHUG81wKjmGsOZM0oMcXTABlIBjc3hApVwgc3SyeCPuiUQVrAgnYuzKJCyjqVgplKg== X-Received: by 2002:a17:902:d4c8:b0:24c:ed95:2725 with SMTP id d9443c01a7336-27ed4a06ca7mr77835285ad.4.1758869763210; Thu, 25 Sep 2025 23:56:03 -0700 (PDT) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:94ad:363a:4161:464c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-27ed672aa0asm45307415ad.62.2025.09.25.23.55.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Sep 2025 23:56:02 -0700 (PDT) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, axboe@kernel.dk, ceph-devel@vger.kernel.org, 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 v3 2/6] lib/base64: Optimize base64_decode() with reverse lookup tables Date: Fri, 26 Sep 2025 14:55:56 +0800 Message-Id: <20250926065556.14250-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250926065235.13623-1-409411716@gms.tku.edu.tw> References: <20250926065235.13623-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 -> ~75ns (~20.4x) 1KB ~27726ns -> ~1165ns (~23.8x) 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> --- lib/base64.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/lib/base64.c b/lib/base64.c index 1af557785..b20fdf168 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -21,6 +21,63 @@ static const char base64_tables[][65] =3D { [BASE64_IMAP] =3D "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01= 23456789+,", }; =20 +static const s8 base64_rev_tables[][256] =3D { + [BASE64_STD] =3D { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1= , 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1= , -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13= , 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1= , -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39= , 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + }, + [BASE64_URLSAFE] =3D { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1= , -1, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1= , -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13= , 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1= , 63, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39= , 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + }, + [BASE64_IMAP] =3D { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, 63, -1, -1= , -1, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1= , -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13= , 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1= , -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39= , 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1= , -1, + }, +}; + /** * base64_encode() - Base64-encode some binary data * @src: the binary data to encode @@ -82,11 +139,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 (src[i] =3D=3D '=3D') { ac =3D (ac << 6); bits +=3D 6; @@ -94,9 +149,10 @@ int base64_decode(const char *src, int srclen, u8 *dst,= bool padding, enum base6 bits -=3D 8; continue; } - if (p =3D=3D NULL || src[i] =3D=3D 0) + ch =3D base64_rev_tables[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 Wed Oct 1 23:36:03 2025 Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.174]) (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 4828327D784 for ; Fri, 26 Sep 2025 06:56:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869792; cv=none; b=Qu+iX8wGz3aJgZC/lGgfP+GHGSKPLRpREjVzDvQm3ZLU4haLdX+P8C77/Pb0/U8KDxl9lTLVd66xwu5QpbNco8dO6Pr098qcI6lA2RL/m8H5NJzPN9unRB0PPUWRbDn2/VYG/W7KsDlzrdjha848hoBJpbe5eZOm0iuM4onSBAM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869792; c=relaxed/simple; bh=vqUhPyP3EAx7UTCOLjBS/l0UBAlATt2TeWv7PAH1DPA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=l/jfdKeLINOgULB6kRZJeDUdrUNeI4/QiOcIEiEQdBJTpT0T8fpiW3+ZjyFL48eSNM0q1twKhJtyqID3gusTMVTV9OaZ3nzUnzhNBtxWNRv6kiA52C3wkoFnocZb2m/OrEEi1ZIZ59+TAOg4nuyDW2xzzU6L4YmzLff2+AQNkM4= 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=sURpY7JL; arc=none smtp.client-ip=209.85.215.174 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="sURpY7JL" Received: by mail-pg1-f174.google.com with SMTP id 41be03b00d2f7-b55517e74e3so1876983a12.2 for ; Thu, 25 Sep 2025 23:56:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1758869789; x=1759474589; 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=ThTjOOxGShK1kR2Ph7c8m2+KgdD3vN1MOztiSeQNOJs=; b=sURpY7JLXY8YUth5tw5T92oUzihhGdAX9tp8D8sdfF0+Mz7APULPZ02RHeb0prPf7t OY36HA6iPrJGeecfdF/VfC8PZoxjy/IV8qeexH43aXSelkEVj49/pkaSRJB6p826lcar CJWSjxX1Ib9g8UrvY0LvQG/LGRAN2aXolszsGgeFXU0IHWIdjG3D09aT7fNrkgggMUv/ 1PLH8VLq+Wn7Pb1g1t+hv8Lc9ADEUk64VV4vBYFg8zsnagDu1BpB5kyDhIUCU4sFOcqT c08VRT6kPKfJXg0aNtYRry8TEYTVfhkWnOWI7SrpsXK8z92jHbuGEdvlCAZ1H2IsPcaw /92A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758869789; x=1759474589; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ThTjOOxGShK1kR2Ph7c8m2+KgdD3vN1MOztiSeQNOJs=; b=Y4S4153ZL2MnYYbBBmOM0UwbVGDPNtL0jVUlQhTE9jkU4eF+CK/YGqZzOMLb5NvALU pgyi9EP+pADsBpFUXCda289ECnAwAUXrycwHJfQb1IrlL336ReFsuszUw3yYdBeeVqun idKfOJYGduaFVhmvF1DLi6d/qQQ9tNVYcF5iHhxHyv6qBc8om7uxoj2das/U2U4s7riK g2r4H26QPZoPWd2lYD7T80PD5j0sx1q+3iWdzW3J+xcayl0QoN6Ga73S9+/AZwwk2xXn C9vjlJhGNx6Lmlv8NZdp8RN9CUue7lUj49wW+rHK07c6nfzSmuJAPcoMG5pTphAXaCgn a17A== X-Forwarded-Encrypted: i=1; AJvYcCV7+192ABMANa+MU6vfWRaAD7FgKvbpqlrV/LAraFf/z+fR3TrqfDMJGhFerqxFNqLDnh8FpQjMf6amVDk=@vger.kernel.org X-Gm-Message-State: AOJu0Yx3hjAu3Mhrm3VuHTAWWiDSt6quLm5gSb85A3GYfcMAWLZe8L13 dkExBTLGglD0h0Bi28nBNwE6Q636ENOTdtgpPun4TI6hR7TnOgywLsyk8RqTBM3uMsU= X-Gm-Gg: ASbGncuWL2UB1iEYIqqM6P35SW16Usg4KE4lO8ankbHczRwVDHc6KsXKS3klB+ipzZh mUmVb0OuVVIgD/OoAss0jJzPiaypX1x3EVzQJpXhXhNfeKq1bZan2tZzpRUK8B3jsOFimLUZc7D l9bWgsJ/bobpdguLgjDlW7PZYZjtM+cbkjIL617w+X7yWqz20g4rWfx0nmXYwL92XQ/X+b4k/3v OpBptxf/fiFo1yKz5Qu2F8pOeTWk4TBSEZX/TJ19uE27hf13/ClxlC44/TwWE7oV0c9cFE6c9aB l0wum//lB/62bpNvzcEli6SsD0mkTUK4a4coO9PCa/5bNCIgn0KunSZkN0bYtBcdjfkxx6OBr7w 1pQLbGfZ98FveNPjY7kilRv7uhdzrLZYL6t3o6XNDcErIRlU= X-Google-Smtp-Source: AGHT+IGNpOwteifS+VbNOKUqfaBSeov0n2k+u3WDmS4hQZBlmCUZXdh+j4DU1NlYFPlw0rxIClUO8A== X-Received: by 2002:a17:902:e5c9:b0:24b:e55:360 with SMTP id d9443c01a7336-27ed4a0a053mr69081205ad.23.1758869783030; Thu, 25 Sep 2025 23:56:23 -0700 (PDT) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:94ad:363a:4161:464c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-27ed66cfdcfsm45203655ad.26.2025.09.25.23.56.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Sep 2025 23:56:22 -0700 (PDT) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, axboe@kernel.dk, ceph-devel@vger.kernel.org, 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 v3 3/6] lib/base64: rework encode/decode for speed and stricter validation Date: Fri, 26 Sep 2025 14:56:17 +0800 Message-Id: <20250926065617.14361-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250926065235.13623-1-409411716@gms.tku.edu.tw> References: <20250926065235.13623-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 -> ~64ns (~23.9x) 1KB ~27726ns -> ~982ns (~28.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> --- lib/base64.c | 150 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 110 insertions(+), 40 deletions(-) diff --git a/lib/base64.c b/lib/base64.c index b20fdf168..fd1db4611 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -93,26 +93,43 @@ static const s8 base64_rev_tables[][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; } - while (bits < 0) { - *cp++ =3D '=3D'; - bits +=3D 2; + + 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'; + } + break; } return cp - dst; } @@ -128,39 +145,92 @@ 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; - - for (i =3D 0; i < srclen; i++) { - 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_tables[variant][(u8)src[i]]; - if (ch =3D=3D -1) + s8 input1, input2, input3, input4; + u32 val; + + if (srclen =3D=3D 0) + return 0; + + /* Validate the input length for padding */ + if (unlikely(padding && (srclen & 0x03) !=3D 0)) + return -1; + + while (srclen >=3D 4) { + /* Decode the next 4 characters */ + input1 =3D base64_rev_tables[variant][(u8)src[0]]; + input2 =3D base64_rev_tables[variant][(u8)src[1]]; + input3 =3D base64_rev_tables[variant][(u8)src[2]]; + input4 =3D base64_rev_tables[variant][(u8)src[3]]; + + /* Return error if any Base64 character is invalid */ + if (unlikely(input1 < 0 || input2 < 0 || (!padding && (input3 < 0 || inp= ut4 < 0)))) + return -1; + + /* Handle padding */ + if (unlikely(padding && ((input3 < 0 && input4 >=3D 0) || + (input3 < 0 && src[2] !=3D '=3D') || + (input4 < 0 && src[3] !=3D '=3D') || + (srclen > 4 && (input3 < 0 || input4 < 0))))) + return -1; + val =3D ((u32)input1 << 18) | + ((u32)input2 << 12) | + ((u32)((input3 < 0) ? 0 : input3) << 6) | + (u32)((input4 < 0) ? 0 : input4); + + *bp++ =3D (u8)(val >> 16); + + if (input3 >=3D 0) + *bp++ =3D (u8)(val >> 8); + if (input4 >=3D 0) + *bp++ =3D (u8)val; + + src +=3D 4; + srclen -=3D 4; + } + + /* Handle leftover characters when padding is not used */ + if (!padding && srclen > 0) { + switch (srclen) { + case 2: + input1 =3D base64_rev_tables[variant][(u8)src[0]]; + input2 =3D base64_rev_tables[variant][(u8)src[1]]; + if (unlikely(input1 < 0 || input2 < 0)) + return -1; + + val =3D ((u32)input1 << 6) | (u32)input2; /* 12 bits */ + if (unlikely(val & 0x0F)) + return -1; /* low 4 bits must be zero */ + + *bp++ =3D (u8)(val >> 4); + break; + case 3: + input1 =3D base64_rev_tables[variant][(u8)src[0]]; + input2 =3D base64_rev_tables[variant][(u8)src[1]]; + input3 =3D base64_rev_tables[variant][(u8)src[2]]; + if (unlikely(input1 < 0 || input2 < 0 || input3 < 0)) + return -1; + + val =3D ((u32)input1 << 12) | + ((u32)input2 << 6) | + (u32)input3; /* 18 bits */ + + if (unlikely(val & 0x03)) + return -1; /* low 2 bits must be zero */ + + *bp++ =3D (u8)(val >> 10); + *bp++ =3D (u8)((val >> 2) & 0xFF); + break; + default: return -1; - ac =3D (ac << 6) | ch; - 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; } EXPORT_SYMBOL_GPL(base64_decode); --=20 2.34.1 From nobody Wed Oct 1 23:36:03 2025 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (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 6269E25DAEA for ; Fri, 26 Sep 2025 06:56:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869808; cv=none; b=TWaJTwQsvRVRpdUA2iNLA6zdZbnkCQkmIXE7gNka7atW4bAhcp5uYMKWccmHo4aVLKvdP18lpsqZdkRb9U74b7uKds4fYPQlNae2fypOkB3HNm14/AGUj9LFsgTEdBkBECzrLE4f4EM8+iCl9+0WpaORiKC44qF1R+TsZN+95mM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869808; c=relaxed/simple; bh=jdYdTn1+hvqCTOO8QO1zlfLzErWnI3zWGLknU8FBx8w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=czO3I/UyvsXJ163I++4IBZRWP/n8cu7RiwORMSshWw+wPunAEnPLQa5CarnEQTsSughf3YWn1G1qfkCqcXbRDJA9AfUxyksLEdOX3Go0TKkvNpV+5OsnR+VR6LrU7P/p6IgAs1rk5DxCJwnOrnLpKntqlai91WspczXZ2GqB2Ws= 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=f7Z4MxIs; arc=none smtp.client-ip=209.85.214.179 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="f7Z4MxIs" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-27eceb38eb1so21522835ad.3 for ; Thu, 25 Sep 2025 23:56:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1758869806; x=1759474606; 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=TtMxni3UZTcKUY99mN8/6WhaPozi7K0URxKXIhOzWGU=; b=f7Z4MxIsYjpClhSQKi7i+C8iMoHszGu/gxwOKJymLF0HIdyE1YS6MJAuUtr37u4STP Kg5yWfLYTbzro7IoSWF/YdOAZjQ4ACJgeZIDEcnM6ywJR+Y2wI7eejKFVXF4PW8vwhYK MJDYf0Ka2hsx0yd1NDvjec0dKGGQRp3rQuqRAY/Mu487/IJ74tKUSLve1YHXII1bQRPA OzNo9TXecvPAFT9ikNa+/N4wbgEarQ+0vi7jgZfZ150TsLLyiOPJ/SjA0FXNIumWtvTC 124GpqGWLPCbLRTGnyfSB4fUEfOdVO0B5/XchbdEhpzlCUChb/kGtMj5ojE4SUZ671XX tcDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758869806; x=1759474606; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TtMxni3UZTcKUY99mN8/6WhaPozi7K0URxKXIhOzWGU=; b=i2ZVlEemY4nFfIuSUQRXkKHXSP8SAg+LkeY2NNXY5PH9uQGKN5duYs6PpA+dB87pVI 3XFsNnAgLraOs//mZ4PE/kiwZWoAbTc80ntXDmwYfN1ZZpzN81Bq/uVDDHN2WsKfFQET 4przMTd7Z1rZqsunNbM7fwBIJNNxAu3MmHgNTfA9QKAzbUmEMYh0zLc7zZIcyV7Hsf5j GtHCSEpSHdYedUHdOXIUvJL77b3Gw5CL1gR41ZvyHHudkp+v1CSzqsPjnPIYeElwh40W wmSXc86kdfVXYd6P5NMgf+d566lLkf5gNc/AKa18/6jti39ASOXuATaS2P3OE01pWhsy CM3g== X-Forwarded-Encrypted: i=1; AJvYcCUzU+6kC4tdZVJtZfRIvkBQaK9smyBKp95IfarkT5QKhE7kFEK04w/oGZ34s5a/+rCkMjvKAc/ShCPWyVs=@vger.kernel.org X-Gm-Message-State: AOJu0YzIxysDcCRWChOzqhi1NEBC3ZLgAxnv0kbt8fM0FGWmBzxl3pP9 a5HsWP33RJwRzuRytMhlqTwCT2vmbTV3Rwwunyi5e+YZHoa75eCJFZDPYvlwfRh2tr0= X-Gm-Gg: ASbGncv51ItRJeR9C8divBeVipmLQxrvVMlk3F2IACib7ngXIcuFUnKG+eYGxrS4GGy z2FEFCux9iTZnKwnjn5LhU93ojGEjJNCffD5r/koVsKyBoOAzHmcQ/9bia+G4e5uIeTrt94v1BP uMWyoaCeAcAn5wSvIUosWQSYuh7sDLDs0EjxCuYwMaWHXP20xty58lFYWZ0q+fUIR1b6YunomD7 4eIBnCgUlAs2jaBMOu2PlE0JE8F92nLvAX7Xwx4uq4Y9+koMkypoG8NSjAKg+6cjym3B85lGuyE zmAdsTPpAW7X1ImCgq4ADqFWETvrLIbDNmdxeSgSDMDqjgPxBpdhhBid597lbkTeqHi0AQ9E5gA hKA6V4zsbJ/SX6Rf2KedxZaBv3bGr1dqNbtOwNm2g3vI0MTQ= X-Google-Smtp-Source: AGHT+IE4JrK/hVqmOvlFOQG3KOukxxPTgXT7tn0oKkRM/rsF9Q+oUR1eHke18YdvIWt0KHYTrSPSPA== X-Received: by 2002:a17:902:d4c3:b0:265:57dc:977b with SMTP id d9443c01a7336-27ed4aea9d1mr66943015ad.61.1758869805711; Thu, 25 Sep 2025 23:56:45 -0700 (PDT) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:94ad:363a:4161:464c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-27ed6882133sm45029085ad.89.2025.09.25.23.56.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Sep 2025 23:56:44 -0700 (PDT) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, axboe@kernel.dk, ceph-devel@vger.kernel.org, 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 v3 4/6] lib: add KUnit tests for base64 encoding/decoding Date: Fri, 26 Sep 2025 14:56:39 +0800 Message-Id: <20250926065639.14455-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250926065235.13623-1-409411716@gms.tku.edu.tw> References: <20250926065235.13623-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 : 64ns # base64_performance_tests: [1KB] encode run : 510ns # base64_performance_tests: [1KB] decode run : 980ns 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 Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Reviewed-by: Kuan-Wei Chiu --- 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 dc0e0c6ed..1cfb12d02 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2794,8 +2794,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 fa6d728a8..6593a2873 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 000000000..f7252070c --- /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 Wed Oct 1 23:36:03 2025 Received: from mail-pf1-f169.google.com (mail-pf1-f169.google.com [209.85.210.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 4872427E05B for ; Fri, 26 Sep 2025 06:57:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869825; cv=none; b=MiNq5S/6HtsY+zLC57+FEoQbx880niEJW9lG7dfIuYnOEWW5SLdsktrkziN9ETsw9SbSsSSIquPBo5/Nv9bNZ2KNndsq2FjnjCwGKJk7XcVZbaovMmPJi1CIvBbK5HWvmDVLTHj+OBW3D/H5PFprZIn52vlbNeyWitW8DLh2Bqc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869825; c=relaxed/simple; bh=OGjdQW2fPGuYQ5EHej/4NhFa8z1IHIEgYJSvEvOJ/h4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NloLn2pHeP/oFPy7XO88ulhkmYafLoo6ALhpEgn9jyFvYVH0JxRIiGQEqWCz2JEliRdbAlbKn8TaeVnuZJLY5HpdZ1WdptNmBAD5RN9XJXBLDBfSS9JvaQMeaqhase1o2Pqc39HQRKw9u502w+CA+prpUt5fwqvWNFaW/bQb6UM= 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=X1aLK2eW; arc=none smtp.client-ip=209.85.210.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="X1aLK2eW" Received: by mail-pf1-f169.google.com with SMTP id d2e1a72fcca58-77f605f22easo1644004b3a.2 for ; Thu, 25 Sep 2025 23:57:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1758869822; x=1759474622; 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=QX1AvjPYqPc07VyrXJLPNqN7Y76elCWsekCNrFr22Ew=; b=X1aLK2eWhl4PdjusXxGMjAFblRu51kKwaiLrZONuDCLo4V9OwHbVAEKHfbvJfT6N+Q AEzEI5VwGxMAwrlegVYHI3P9D9cciOJxwiU7bX+9X4NRR4xKWa6xm+FPGQtk9zKxtGB/ XMYWvjv+9P9ckSu3ZmMpI33pQFz0LY71UJZu+iWo9pqtK6HIn6lYpIUrld5A/RwtYvQU bVk7daTOZaDCQRHYLX4kC6zDDI63e0Tb74Rw5aV4DCJhG09ynfbQaLNb+HETHx2JgPrk Hl5MpSe5jRKRcDnhOfZlHOypf15fWdxZfF+f+p4u4l9Ij1sz9UzNl1GRzZ9/OYXjb2MS Ja7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758869822; x=1759474622; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QX1AvjPYqPc07VyrXJLPNqN7Y76elCWsekCNrFr22Ew=; b=l2vUReFBmeFFEhKqXMTRAF38cSvwME5j3hkanIwXjx0svoLxUeWlW1SCpxV7UXpKQX yauK6K/VdJ80eTttLMbBxpNzEy3xhCOzb/P7VDCVQSPVKR8owmGbE7EoxiHIfnubBNKq I6IK47sOSX8UVS1Xtdos5FJsZD/lc9nVc0UO9mFXjjnYJhplAE8WZa+y0p7JiiY9buHK l5EhHM1OfidLPELf+NDrxDFlX72qUYG/wXkqv3LZyldkRAQd7StS3yU7UEP9mkVGkuTr g/+ltxJPoX2iUTNz8QlMljxpN+Oe/OT4aPIY19u/nzIXeErHccyg1sP84Ux34njnHoP2 pN5Q== X-Forwarded-Encrypted: i=1; AJvYcCWZldGr0W+CohcYVE4iuoPBhA41c9J24X6NXYoY8LECTovcO0QAj3+E4JRMf1aCB72gwn1T/cuDmOwoMZw=@vger.kernel.org X-Gm-Message-State: AOJu0Ywn5q8ffeD7bx6UtgiKF2ZQr6qK7MWzv2GXxY8zroQCzYMLfXWH en1uLSA9ymW/2LgMYBYVDOyzakRdE9F9UC3ScZcaA5pUJlEbrf0FIQx6S+ihTHgPBB0= X-Gm-Gg: ASbGnctzTWEHOmvhtbpDKp+/b5LiHD7onrak+9KuBrqCawmpWakThanHU6xXFnUez0e kFuHiJxjRsZYafVywsvIVBrPC/NDdls7/34ULwiF06Pjr1BEF0+uCCbO2PMGoy9LyGvWibmBKxN vIDRIrfh+PFGOyWNzM6dNgLk0aFEcVbAmF3FqiAlPIMIset9CTCY+7g/olHhr10pLEcLeDZ5OWR pWE6D0Bx2shp42zblFNOosdKqkB5JZfEb9wSpubU+10jrXtL7WSCa9VVYE7VVlk6qCoxRRFdiKU bRt95/5AP5V+qc34XvL06fDNDQZAcfwPsnB6e4lFy4a+/gKkIwhscZ1kBS8DC9Xjt8Ok3ETD7VE 55zD+KTZwx01+1qdOpDprqrVPNLsuib6P2gw4TqdM8delJPsT+xD3od0ifw== X-Google-Smtp-Source: AGHT+IEJuoFu3AqWz+6Ia84gW9VhTEjnQyT1iUNvqk+U9XhDT4f46dcSlDiMFRq3zQJq5LoCWNwKLA== X-Received: by 2002:a05:6a00:853:b0:772:3ea3:3218 with SMTP id d2e1a72fcca58-780fcec0a66mr5554818b3a.23.1758869822399; Thu, 25 Sep 2025 23:57:02 -0700 (PDT) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:94ad:363a:4161:464c]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-781023c158fsm3654182b3a.24.2025.09.25.23.56.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Sep 2025 23:57:01 -0700 (PDT) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, axboe@kernel.dk, ceph-devel@vger.kernel.org, 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 v3 5/6] fscrypt: replace local base64url helpers with lib/base64 Date: Fri, 26 Sep 2025 14:56:56 +0800 Message-Id: <20250926065656.14522-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250926065235.13623-1-409411716@gms.tku.edu.tw> References: <20250926065235.13623-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 23-28x speedups compared to the previous implementation. Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Reviewed-by: Kuan-Wei Chiu --- 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 f9f6713e1..dcf7cff70 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -17,6 +17,7 @@ #include #include #include +#include =20 #include "fscrypt_private.h" =20 @@ -72,7 +73,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) { @@ -163,84 +164,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 Wed Oct 1 23:36:03 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 892F227E054 for ; Fri, 26 Sep 2025 06:57:18 +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=1758869840; cv=none; b=Fkmk7Zib2OGfDtaCInpUD1x7ANwbWpIkoB/EUZRkg8TTIq5rJO2BhGlarSGqIEPqFm8tzVORKMkJLEmxe89L6NPIYcxbZKXYHw8gewGo1UHXhf3rIpxtVv3Fq5GButm1YwsFT7q/RVFv3am30DVK+vpp3QcjiGf4JjSqyQu66Tw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758869840; c=relaxed/simple; bh=CAGiyfQcjLEBYWF2D4ZxF9et3ubh52B6JUIxa3MQPOA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MTTVwr0hPBjfMxRWoRrGsD1ZKBrOB2HZr9eFvrGtSjNicWzfo2b+vgs2xM5LfZL1w+0c9Iuiz8aBRDDdYhmGRKY8o6FxADs9ukFnE2vConY01ifJEHNCnX/3bN5V+fkVu8rS35IqlBWNGoEzNxwecHdJjieJaj7mMjKj0Kpy4tc= 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=WDwJuxmo; 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="WDwJuxmo" Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-25669596921so19293805ad.1 for ; Thu, 25 Sep 2025 23:57:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gms-tku-edu-tw.20230601.gappssmtp.com; s=20230601; t=1758869838; x=1759474638; 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=igTUGl2eyyaTZ+rlOxfJOLC6Xg0h3npTvJ/qhTpvyus=; b=WDwJuxmo7sZV6UeYvTdAuoixPueN8JpadMvfPxPBNvCOZnRtc41bdbocBNU+eQIOkL FnNZVExPj3qdXhh7oCw3jyk0QUYeqJpCQgDyqWLwnomGBeTHT9cBvcO+jisXORiviAs0 FrFAA3GXWxi/cIDQPZb5w2R4XXjnJCrlu3JJXSrZXDk4nb8XZ34Ek3ebybJuX7/XZxm1 GmVMeRqHj1SqhghJjZnj7IA+RUe5bqNbnM4Zmk4+57JqfSXoVSKOtixxelPAEBLlVai4 a3zg3yUtwjr6nBeFbrnqGSRhaISdHwnEsbl+WJdLMKn4vEPi89vdLo+IrMcJ8gKz0vWJ 7aWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758869838; x=1759474638; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=igTUGl2eyyaTZ+rlOxfJOLC6Xg0h3npTvJ/qhTpvyus=; b=Ba0VQQ1z5PUsQn9dcfa8M0Cw6Q6R/4mfkDgsHXsnl7fbcOBKOL1MzINSOIOTnCyzRp Uv5PEijhcCXm/yrQ0O6M1AIu94OwOb0VZkwl1RaQ3Cr0H3aZm/NKKP5P20in3+PpqQEd 3p5PGa9LtOOn/VXPHjjnrd2S7q62g4dQjjyH0/QcNeyXhJGveCNDlPlVJ4xOl4JZ+iPk /Hj84LgFBy+HcKonZ+a3iM2JM2TH3zQTbaezmFHqatDRqeI1jqndedrGsuEl/RmgZrOC NbR2XmquG0+9BFPr9Z5+lfR3zwvNnADwM69p5UFFgvAOu4CgOOAJMpsp12IzjAC2QofP 3Fhw== X-Forwarded-Encrypted: i=1; AJvYcCVA3FfdrYkPtMoaH3DjloBHA2HRveKSnoqylIcB+qjthY+KW+SBc98Iag8MjR5mbwV18YuAvndJBE5FiBk=@vger.kernel.org X-Gm-Message-State: AOJu0YxqNWjBTU1slopQVGudhmeuu0rMnTeZYvaFpfKxisOsZZ31Z9XR N8vv7czYSnG7RelelLpduSdq1QR0MD7t9xr+nFCqSXzdLVR+FMFWvplGcL2agWwBz2k= X-Gm-Gg: ASbGncs+aRBlQ22oBDC4Ov0hcn6nkkSr8qpKjW2+8NA5MIuiBOosGBDrDb/dNwEPhfB 4vXX9xl2V4/+aFrb2S6bti/cUsFdrsVoxdvK8YdVaDi/Byw4PJYFi0oStuAkbd3S0xSzl6NcdAS 8IJCY8XS0ebfLb/m/RfSuq/G/bl1kFDNm2+4Wf8AwoYnpufFQeqB6+9AYjEiPsgJEA4zqA5Ku2y Wdo62wDEaIDU7Sc1ZtJcsJcurS0Bvi7wZmPN0fk6V75uKA05bvmqNflgccM6Hx7N3VE6WVcWETG QZ1FS2z5ejPrndRDgIn6/Nb8XdLWGBBcfe441wDQcPCGcJHjIkRGT7UgCZ47c4bqX/8CrEgcCxv Hba8iVpR4WAYxbqsDlTddVHLcSZx1pMHX8CSN/LapnUFq2HI= X-Google-Smtp-Source: AGHT+IGsJ29z77Si0Jc2Vb5pCBLTmliotaWTgWM2zePJsxVuTaOzYIGurW3Xrr0Nqo5g1PeamIKvSw== X-Received: by 2002:a17:902:d54e:b0:24a:a6c8:d6c4 with SMTP id d9443c01a7336-27ed4a0e8d9mr69217065ad.26.1758869838002; Thu, 25 Sep 2025 23:57:18 -0700 (PDT) Received: from wu-Pro-E500-G6-WS720T.. ([2001:288:7001:2703:94ad:363a:4161:464c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-27ed688238esm44612135ad.94.2025.09.25.23.57.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Sep 2025 23:57:17 -0700 (PDT) From: Guan-Chun Wu <409411716@gms.tku.edu.tw> To: 409411716@gms.tku.edu.tw Cc: akpm@linux-foundation.org, axboe@kernel.dk, ceph-devel@vger.kernel.org, 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 v3 6/6] ceph: replace local base64 helpers with lib/base64 Date: Fri, 26 Sep 2025 14:57:11 +0800 Message-Id: <20250926065711.14620-1-409411716@gms.tku.edu.tw> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250926065235.13623-1-409411716@gms.tku.edu.tw> References: <20250926065235.13623-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 23-28x speedups compared to the previous local implementation. Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Reviewed-by: Kuan-Wei Chiu --- 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 cab722619..9bb0f320b 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); @@ -316,7 +263,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 */ @@ -410,7 +357,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; @@ -424,7 +372,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 23612b2e9..b748e2060 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 8478e7e75..25045d817 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 fc543075b..d06fb76fc 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -911,7 +911,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