[01/14] crypto: ecdsa - Convert byte arrays with key coordinates to digits
Commit Message
For NIST P192/256/384 the public key's x and y parameters could be copied
directly from a given array since both parameters each filled 'ndigits'
of digits (a 'digit' is a u64). For support of NIST P521 the key parameters
first have to be copied right-aligned into a temporary byte array and can
then be copied into the final digit array using ecc_swap_digits.
Implement ecc_digits_from_array to convert a byte array into an array of
digits and use this function in ecdsa_set_pub_key where an input byte array
needs to be converted into digits.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecdsa.c | 15 ++++++++++-----
include/crypto/internal/ecc.h | 19 +++++++++++++++++++
2 files changed, 29 insertions(+), 5 deletions(-)
Comments
Hi Stefan,
kernel test robot noticed the following build warnings:
[auto build test WARNING on herbert-cryptodev-2.6/master]
[also build test WARNING on herbert-crypto-2.6/master linus/master v6.8-rc3 next-20240209]
[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/Stefan-Berger/crypto-ecdsa-Convert-byte-arrays-with-key-coordinates-to-digits/20240209-062415
base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
patch link: https://lore.kernel.org/r/20240208221840.3665874-2-stefanb%40linux.ibm.com
patch subject: [PATCH 01/14] crypto: ecdsa - Convert byte arrays with key coordinates to digits
config: x86_64-randconfig-101-20240209 (https://download.01.org/0day-ci/archive/20240210/202402100352.1TagPxg9-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240210/202402100352.1TagPxg9-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/202402100352.1TagPxg9-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> crypto/ecdsa.c:225:34: warning: variable 'nbytes' set but not used [-Wunused-but-set-variable]
225 | unsigned int digitlen, ndigits, nbytes;
| ^
1 warning generated.
vim +/nbytes +225 crypto/ecdsa.c
216
217 /*
218 * Set the public key given the raw uncompressed key data from an X509
219 * certificate. The key data contain the concatenated X and Y coordinates of
220 * the public key.
221 */
222 static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
223 {
224 struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
> 225 unsigned int digitlen, ndigits, nbytes;
226 const unsigned char *d = key;
227 int ret;
228
229 ret = ecdsa_ecc_ctx_reset(ctx);
230 if (ret < 0)
231 return ret;
232
233 if (keylen < 1 || (((keylen - 1) >> 1) % sizeof(u64)) != 0)
234 return -EINVAL;
235 /* we only accept uncompressed format indicated by '4' */
236 if (d[0] != 4)
237 return -EINVAL;
238
239 keylen--;
240 digitlen = keylen >> 1;
241
242 ndigits = digitlen / sizeof(u64);
243 if (ndigits != ctx->curve->g.ndigits)
244 return -EINVAL;
245
246 nbytes = ndigits * sizeof(u64);
247 d++;
248
249 ecc_digits_from_array(d, digitlen, ctx->pub_key.x, ndigits);
250 ecc_digits_from_array(&d[digitlen], digitlen, ctx->pub_key.y, ndigits);
251
252 ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key);
253
254 ctx->pub_key_set = ret == 0;
255
256 return ret;
257 }
258
@@ -222,9 +222,8 @@ static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx)
static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
{
struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ unsigned int digitlen, ndigits, nbytes;
const unsigned char *d = key;
- const u64 *digits = (const u64 *)&d[1];
- unsigned int ndigits;
int ret;
ret = ecdsa_ecc_ctx_reset(ctx);
@@ -238,12 +237,18 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig
return -EINVAL;
keylen--;
- ndigits = (keylen >> 1) / sizeof(u64);
+ digitlen = keylen >> 1;
+
+ ndigits = digitlen / sizeof(u64);
if (ndigits != ctx->curve->g.ndigits)
return -EINVAL;
- ecc_swap_digits(digits, ctx->pub_key.x, ndigits);
- ecc_swap_digits(&digits[ndigits], ctx->pub_key.y, ndigits);
+ nbytes = ndigits * sizeof(u64);
+ d++;
+
+ ecc_digits_from_array(d, digitlen, ctx->pub_key.x, ndigits);
+ ecc_digits_from_array(&d[digitlen], digitlen, ctx->pub_key.y, ndigits);
+
ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key);
ctx->pub_key_set = ret == 0;
@@ -56,6 +56,25 @@ static inline void ecc_swap_digits(const void *in, u64 *out, unsigned int ndigit
out[i] = get_unaligned_be64(&src[ndigits - 1 - i]);
}
+/**
+ * ecc_digits_from_array() - Create ndigits from a byte array of nbytes
+ * @in: Input byte array
+ * @nbytes Size of input byte array
+ * @out Output digits array
+ * @ndigits: Number of digits to create from byte array
+ */
+static inline void ecc_digits_from_array(const u8 *in, unsigned int nbytes,
+ u64 *out, unsigned int ndigits)
+{
+ unsigned int sz = ndigits * sizeof(u64);
+ u8 tmp[ECC_MAX_DIGITS * sizeof(u64)];
+ unsigned int o = sz - nbytes;
+
+ memset(tmp, 0, o);
+ memcpy(&tmp[o], in, nbytes);
+ ecc_swap_digits(tmp, out, ndigits);
+}
+
/**
* ecc_is_key_valid() - Validate a given ECDH private key
*