Skip to content

Commit d67c96f

Browse files
stefanbergerherbertx
authored andcommitted
crypto: ecdsa - Convert byte arrays with key coordinates to digits
For NIST P192/256/384 the public key's x and y parameters could be copied directly from a given array since both parameters filled 'ndigits' of digits (a 'digit' is a u64). For support of NIST P521 the key parameters need to have leading zeros prepended to the most significant digit since only 2 bytes of the most significant digit are provided. Therefore, implement ecc_digits_from_bytes 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. Suggested-by: Lukas Wunner <[email protected]> Tested-by: Lukas Wunner <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Stefan Berger <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 526d23f commit d67c96f

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

crypto/ecdsa.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,8 @@ static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx)
222222
static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
223223
{
224224
struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
225+
unsigned int digitlen, ndigits;
225226
const unsigned char *d = key;
226-
const u64 *digits = (const u64 *)&d[1];
227-
unsigned int ndigits;
228227
int ret;
229228

230229
ret = ecdsa_ecc_ctx_reset(ctx);
@@ -238,12 +237,17 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig
238237
return -EINVAL;
239238

240239
keylen--;
241-
ndigits = (keylen >> 1) / sizeof(u64);
240+
digitlen = keylen >> 1;
241+
242+
ndigits = DIV_ROUND_UP(digitlen, sizeof(u64));
242243
if (ndigits != ctx->curve->g.ndigits)
243244
return -EINVAL;
244245

245-
ecc_swap_digits(digits, ctx->pub_key.x, ndigits);
246-
ecc_swap_digits(&digits[ndigits], ctx->pub_key.y, ndigits);
246+
d++;
247+
248+
ecc_digits_from_bytes(d, digitlen, ctx->pub_key.x, ndigits);
249+
ecc_digits_from_bytes(&d[digitlen], digitlen, ctx->pub_key.y, ndigits);
250+
247251
ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key);
248252

249253
ctx->pub_key_set = ret == 0;

include/crypto/internal/ecc.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@ static inline void ecc_swap_digits(const void *in, u64 *out, unsigned int ndigit
5656
out[i] = get_unaligned_be64(&src[ndigits - 1 - i]);
5757
}
5858

59+
/**
60+
* ecc_digits_from_bytes() - Create ndigits-sized digits array from byte array
61+
* @in: Input byte array
62+
* @nbytes Size of input byte array
63+
* @out Output digits array
64+
* @ndigits: Number of digits to create from byte array
65+
*/
66+
static inline void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes,
67+
u64 *out, unsigned int ndigits)
68+
{
69+
unsigned int o = nbytes & 7;
70+
__be64 msd = 0;
71+
72+
if (o) {
73+
memcpy((u8 *)&msd + sizeof(msd) - o, in, o);
74+
out[--ndigits] = be64_to_cpu(msd);
75+
in += o;
76+
}
77+
ecc_swap_digits(in, out, ndigits);
78+
}
79+
5980
/**
6081
* ecc_is_key_valid() - Validate a given ECDH private key
6182
*

0 commit comments

Comments
 (0)