[PATCH v3 2/3] lib/digsig: Use scope-based resource management for two MPI variables in digsig_verify_rsa()

Markus Elfring posted 3 patches 1 month, 2 weeks ago
[PATCH v3 2/3] lib/digsig: Use scope-based resource management for two MPI variables in digsig_verify_rsa()
Posted by Markus Elfring 1 month, 2 weeks ago
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 12 Oct 2024 14:21:28 +0200

The support for scope-based resource management was extended.

* Thus use the attribute “__free(mpi_free)”.

* Reduce the scopes for the local variables “nret”, “in” and “res”.

* Omit two mpi_free() calls accordingly.

* Update jump targets.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---

V3:
Applications were added as requested (by Herbert Xu) for the proposed
programming interface extension.


 lib/digsig.c | 80 ++++++++++++++++++++++++++++------------------------
 1 file changed, 43 insertions(+), 37 deletions(-)

diff --git a/lib/digsig.c b/lib/digsig.c
index 04b5e55ed95f..2481120094ab 100644
--- a/lib/digsig.c
+++ b/lib/digsig.c
@@ -71,11 +71,11 @@ static int digsig_verify_rsa(struct key *key,
 	int err = -EINVAL;
 	unsigned long len;
 	unsigned long mlen, mblen;
-	unsigned nret, l;
+	unsigned int l;
 	int head, i;
 	unsigned char *out1 = NULL;
 	const char *m;
-	MPI in = NULL, res = NULL, pkey[2];
+	MPI pkey[2];
 	uint8_t *p, *datap;
 	const uint8_t *endp;
 	const struct user_key_payload *ukp;
@@ -112,7 +112,7 @@ static int digsig_verify_rsa(struct key *key,
 		pkey[i] = mpi_read_from_buffer(datap, &remaining);
 		if (IS_ERR(pkey[i])) {
 			err = PTR_ERR(pkey[i]);
-			goto err;
+			goto free_keys;
 		}
 		datap += remaining;
 	}
@@ -122,57 +122,63 @@ static int digsig_verify_rsa(struct key *key,

 	if (mlen == 0) {
 		err = -EINVAL;
-		goto err;
+		goto free_keys;
 	}

 	err = -ENOMEM;

 	out1 = kzalloc(mlen, GFP_KERNEL);
 	if (!out1)
-		goto err;
+		goto free_keys;

-	nret = siglen;
-	in = mpi_read_from_buffer(sig, &nret);
-	if (IS_ERR(in)) {
-		err = PTR_ERR(in);
-		goto err;
-	}
+	{
+		unsigned int nret = siglen;
+		MPI in __free(mpi_free) = mpi_read_from_buffer(sig, &nret);

-	res = mpi_alloc(mpi_get_nlimbs(in) * 2);
-	if (!res)
-		goto err;
+		if (IS_ERR(in)) {
+			err = PTR_ERR(in);
+			goto in_exit;
+		}

-	err = mpi_powm(res, in, pkey[1], pkey[0]);
-	if (err)
-		goto err;
+		{
+			MPI res __free(mpi_free) = mpi_alloc(mpi_get_nlimbs(in) * 2);

-	if (mpi_get_nlimbs(res) * BYTES_PER_MPI_LIMB > mlen) {
-		err = -EINVAL;
-		goto err;
-	}
+			if (!res)
+				goto res_exit;

-	p = mpi_get_buffer(res, &l, NULL);
-	if (!p) {
-		err = -EINVAL;
-		goto err;
-	}
+			err = mpi_powm(res, in, pkey[1], pkey[0]);
+			if (err)
+				goto res_exit;

-	len = mlen;
-	head = len - l;
-	memset(out1, 0, head);
-	memcpy(out1 + head, p, l);
+			if (mpi_get_nlimbs(res) * BYTES_PER_MPI_LIMB > mlen) {
+				err = -EINVAL;
+				goto res_exit;
+			}

-	kfree(p);
+			p = mpi_get_buffer(res, &l, NULL);
+			if (!p) {
+				err = -EINVAL;
+				goto res_exit;
+			}

-	m = pkcs_1_v1_5_decode_emsa(out1, len, mblen, &len);
+			len = mlen;
+			head = len - l;
+			memset(out1, 0, head);
+			memcpy(out1 + head, p, l);

-	if (!m || len != hlen || memcmp(m, h, hlen))
-		err = -EINVAL;
+			kfree(p);
+
+			m = pkcs_1_v1_5_decode_emsa(out1, len, mblen, &len);
+
+			if (!m || len != hlen || memcmp(m, h, hlen))
+				err = -EINVAL;
+res_exit:
+		}
+in_exit:
+	}

-err:
-	mpi_free(in);
-	mpi_free(res);
 	kfree(out1);
+free_keys:
 	while (--i >= 0)
 		mpi_free(pkey[i]);
 err1:
--
2.46.1
Re: [PATCH v3 2/3] lib/digsig: Use scope-based resource management for two MPI variables in digsig_verify_rsa()
Posted by kernel test robot 1 month, 1 week ago
Hi Markus,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-nonmm-unstable]
[also build test ERROR on herbert-crypto-2.6/master herbert-cryptodev-2.6/master linus/master v6.12-rc3 next-20241016]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Markus-Elfring/crypto-lib-mpi-Extend-support-for-scope-based-resource-management/20241012-231156
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-nonmm-unstable
patch link:    https://lore.kernel.org/r/300a0376-f003-4862-bb16-7e004733c9c1%40web.de
patch subject: [PATCH v3 2/3] lib/digsig: Use scope-based resource management for two MPI variables in digsig_verify_rsa()
config: hexagon-randconfig-r064-20241016 (https://download.01.org/0day-ci/archive/20241016/202410161914.lY62TWL3-lkp@intel.com/config)
compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241016/202410161914.lY62TWL3-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410161914.lY62TWL3-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from lib/digsig.c:25:
   In file included from include/linux/mpi.h:21:
   In file included from include/linux/scatterlist.h:9:
   In file included from arch/hexagon/include/asm/io.h:328:
   include/asm-generic/io.h:548:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:561:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from lib/digsig.c:25:
   In file included from include/linux/mpi.h:21:
   In file included from include/linux/scatterlist.h:9:
   In file included from arch/hexagon/include/asm/io.h:328:
   include/asm-generic/io.h:574:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from lib/digsig.c:25:
   In file included from include/linux/mpi.h:21:
   In file included from include/linux/scatterlist.h:9:
   In file included from arch/hexagon/include/asm/io.h:328:
   include/asm-generic/io.h:585:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:595:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:605:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
>> lib/digsig.c:176:3: error: expected statement
                   }
                   ^
   lib/digsig.c:178:2: error: expected statement
           }
           ^
   6 warnings and 2 errors generated.


vim +176 lib/digsig.c

    63	
    64	/*
    65	 * RSA Signature verification with public key
    66	 */
    67	static int digsig_verify_rsa(struct key *key,
    68			    const char *sig, int siglen,
    69			       const char *h, int hlen)
    70	{
    71		int err = -EINVAL;
    72		unsigned long len;
    73		unsigned long mlen, mblen;
    74		unsigned int l;
    75		int head, i;
    76		unsigned char *out1 = NULL;
    77		const char *m;
    78		MPI pkey[2];
    79		uint8_t *p, *datap;
    80		const uint8_t *endp;
    81		const struct user_key_payload *ukp;
    82		struct pubkey_hdr *pkh;
    83	
    84		down_read(&key->sem);
    85		ukp = user_key_payload_locked(key);
    86	
    87		if (!ukp) {
    88			/* key was revoked before we acquired its semaphore */
    89			err = -EKEYREVOKED;
    90			goto err1;
    91		}
    92	
    93		if (ukp->datalen < sizeof(*pkh))
    94			goto err1;
    95	
    96		pkh = (struct pubkey_hdr *)ukp->data;
    97	
    98		if (pkh->version != 1)
    99			goto err1;
   100	
   101		if (pkh->algo != PUBKEY_ALGO_RSA)
   102			goto err1;
   103	
   104		if (pkh->nmpi != 2)
   105			goto err1;
   106	
   107		datap = pkh->mpi;
   108		endp = ukp->data + ukp->datalen;
   109	
   110		for (i = 0; i < pkh->nmpi; i++) {
   111			unsigned int remaining = endp - datap;
   112			pkey[i] = mpi_read_from_buffer(datap, &remaining);
   113			if (IS_ERR(pkey[i])) {
   114				err = PTR_ERR(pkey[i]);
   115				goto free_keys;
   116			}
   117			datap += remaining;
   118		}
   119	
   120		mblen = mpi_get_nbits(pkey[0]);
   121		mlen = DIV_ROUND_UP(mblen, 8);
   122	
   123		if (mlen == 0) {
   124			err = -EINVAL;
   125			goto free_keys;
   126		}
   127	
   128		err = -ENOMEM;
   129	
   130		out1 = kzalloc(mlen, GFP_KERNEL);
   131		if (!out1)
   132			goto free_keys;
   133	
   134		{
   135			unsigned int nret = siglen;
   136			MPI in __free(mpi_free) = mpi_read_from_buffer(sig, &nret);
   137	
   138			if (IS_ERR(in)) {
   139				err = PTR_ERR(in);
   140				goto in_exit;
   141			}
   142	
   143			{
   144				MPI res __free(mpi_free) = mpi_alloc(mpi_get_nlimbs(in) * 2);
   145	
   146				if (!res)
   147					goto res_exit;
   148	
   149				err = mpi_powm(res, in, pkey[1], pkey[0]);
   150				if (err)
   151					goto res_exit;
   152	
   153				if (mpi_get_nlimbs(res) * BYTES_PER_MPI_LIMB > mlen) {
   154					err = -EINVAL;
   155					goto res_exit;
   156				}
   157	
   158				p = mpi_get_buffer(res, &l, NULL);
   159				if (!p) {
   160					err = -EINVAL;
   161					goto res_exit;
   162				}
   163	
   164				len = mlen;
   165				head = len - l;
   166				memset(out1, 0, head);
   167				memcpy(out1 + head, p, l);
   168	
   169				kfree(p);
   170	
   171				m = pkcs_1_v1_5_decode_emsa(out1, len, mblen, &len);
   172	
   173				if (!m || len != hlen || memcmp(m, h, hlen))
   174					err = -EINVAL;
   175	res_exit:
 > 176			}
   177	in_exit:
   178		}
   179	
   180		kfree(out1);
   181	free_keys:
   182		while (--i >= 0)
   183			mpi_free(pkey[i]);
   184	err1:
   185		up_read(&key->sem);
   186	
   187		return err;
   188	}
   189	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v3 2/3] lib/digsig: Use scope-based resource management for two MPI variables in digsig_verify_rsa()
Posted by kernel test robot 1 month, 1 week ago
Hi Markus,

kernel test robot noticed the following build warnings:

[auto build test WARNING on akpm-mm/mm-nonmm-unstable]
[also build test WARNING on herbert-crypto-2.6/master herbert-cryptodev-2.6/master linus/master v6.12-rc3 next-20241015]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Markus-Elfring/crypto-lib-mpi-Extend-support-for-scope-based-resource-management/20241012-231156
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-nonmm-unstable
patch link:    https://lore.kernel.org/r/300a0376-f003-4862-bb16-7e004733c9c1%40web.de
patch subject: [PATCH v3 2/3] lib/digsig: Use scope-based resource management for two MPI variables in digsig_verify_rsa()
config: arm-randconfig-002-20241016 (https://download.01.org/0day-ci/archive/20241016/202410160438.SOIZeFku-lkp@intel.com/config)
compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project 70e0a7e7e6a8541bcc46908c592eed561850e416)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241016/202410160438.SOIZeFku-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410160438.SOIZeFku-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from lib/digsig.c:25:
   In file included from include/linux/mpi.h:21:
   In file included from include/linux/scatterlist.h:8:
   In file included from include/linux/mm.h:2213:
   include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     518 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
>> lib/digsig.c:176:3: warning: label at end of compound statement is a C23 extension [-Wc23-extensions]
     176 |                 }
         |                 ^
   lib/digsig.c:178:2: warning: label at end of compound statement is a C23 extension [-Wc23-extensions]
     178 |         }
         |         ^
   3 warnings generated.


vim +176 lib/digsig.c

    16	
    17	#include <linux/err.h>
    18	#include <linux/module.h>
    19	#include <linux/slab.h>
    20	#include <linux/key.h>
    21	#include <linux/crypto.h>
    22	#include <crypto/hash.h>
    23	#include <crypto/sha1.h>
    24	#include <keys/user-type.h>
  > 25	#include <linux/mpi.h>
    26	#include <linux/digsig.h>
    27	
    28	static struct crypto_shash *shash;
    29	
    30	static const char *pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
    31							unsigned long  msglen,
    32							unsigned long  modulus_bitlen,
    33							unsigned long *outlen)
    34	{
    35		unsigned long modulus_len, ps_len, i;
    36	
    37		modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
    38	
    39		/* test message size */
    40		if ((msglen > modulus_len) || (modulus_len < 11))
    41			return NULL;
    42	
    43		/* separate encoded message */
    44		if (msg[0] != 0x00 || msg[1] != 0x01)
    45			return NULL;
    46	
    47		for (i = 2; i < modulus_len - 1; i++)
    48			if (msg[i] != 0xFF)
    49				break;
    50	
    51		/* separator check */
    52		if (msg[i] != 0)
    53			/* There was no octet with hexadecimal value 0x00
    54			to separate ps from m. */
    55			return NULL;
    56	
    57		ps_len = i - 2;
    58	
    59		*outlen = (msglen - (2 + ps_len + 1));
    60	
    61		return msg + 2 + ps_len + 1;
    62	}
    63	
    64	/*
    65	 * RSA Signature verification with public key
    66	 */
    67	static int digsig_verify_rsa(struct key *key,
    68			    const char *sig, int siglen,
    69			       const char *h, int hlen)
    70	{
    71		int err = -EINVAL;
    72		unsigned long len;
    73		unsigned long mlen, mblen;
    74		unsigned int l;
    75		int head, i;
    76		unsigned char *out1 = NULL;
    77		const char *m;
    78		MPI pkey[2];
    79		uint8_t *p, *datap;
    80		const uint8_t *endp;
    81		const struct user_key_payload *ukp;
    82		struct pubkey_hdr *pkh;
    83	
    84		down_read(&key->sem);
    85		ukp = user_key_payload_locked(key);
    86	
    87		if (!ukp) {
    88			/* key was revoked before we acquired its semaphore */
    89			err = -EKEYREVOKED;
    90			goto err1;
    91		}
    92	
    93		if (ukp->datalen < sizeof(*pkh))
    94			goto err1;
    95	
    96		pkh = (struct pubkey_hdr *)ukp->data;
    97	
    98		if (pkh->version != 1)
    99			goto err1;
   100	
   101		if (pkh->algo != PUBKEY_ALGO_RSA)
   102			goto err1;
   103	
   104		if (pkh->nmpi != 2)
   105			goto err1;
   106	
   107		datap = pkh->mpi;
   108		endp = ukp->data + ukp->datalen;
   109	
   110		for (i = 0; i < pkh->nmpi; i++) {
   111			unsigned int remaining = endp - datap;
   112			pkey[i] = mpi_read_from_buffer(datap, &remaining);
   113			if (IS_ERR(pkey[i])) {
   114				err = PTR_ERR(pkey[i]);
   115				goto free_keys;
   116			}
   117			datap += remaining;
   118		}
   119	
   120		mblen = mpi_get_nbits(pkey[0]);
   121		mlen = DIV_ROUND_UP(mblen, 8);
   122	
   123		if (mlen == 0) {
   124			err = -EINVAL;
   125			goto free_keys;
   126		}
   127	
   128		err = -ENOMEM;
   129	
   130		out1 = kzalloc(mlen, GFP_KERNEL);
   131		if (!out1)
   132			goto free_keys;
   133	
   134		{
   135			unsigned int nret = siglen;
   136			MPI in __free(mpi_free) = mpi_read_from_buffer(sig, &nret);
   137	
   138			if (IS_ERR(in)) {
   139				err = PTR_ERR(in);
   140				goto in_exit;
   141			}
   142	
   143			{
   144				MPI res __free(mpi_free) = mpi_alloc(mpi_get_nlimbs(in) * 2);
   145	
   146				if (!res)
   147					goto res_exit;
   148	
   149				err = mpi_powm(res, in, pkey[1], pkey[0]);
   150				if (err)
   151					goto res_exit;
   152	
   153				if (mpi_get_nlimbs(res) * BYTES_PER_MPI_LIMB > mlen) {
   154					err = -EINVAL;
   155					goto res_exit;
   156				}
   157	
   158				p = mpi_get_buffer(res, &l, NULL);
   159				if (!p) {
   160					err = -EINVAL;
   161					goto res_exit;
   162				}
   163	
   164				len = mlen;
   165				head = len - l;
   166				memset(out1, 0, head);
   167				memcpy(out1 + head, p, l);
   168	
   169				kfree(p);
   170	
   171				m = pkcs_1_v1_5_decode_emsa(out1, len, mblen, &len);
   172	
   173				if (!m || len != hlen || memcmp(m, h, hlen))
   174					err = -EINVAL;
   175	res_exit:
 > 176			}
   177	in_exit:
   178		}
   179	
   180		kfree(out1);
   181	free_keys:
   182		while (--i >= 0)
   183			mpi_free(pkey[i]);
   184	err1:
   185		up_read(&key->sem);
   186	
   187		return err;
   188	}
   189	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki