Skip to content

Commit e5221fa

Browse files
committed
KEYS: asymmetric: Move sm2 code into x509_public_key
The sm2 certificate requires a modified digest. Move the code for the hashing from the signature verification path into the code where we generate the digest. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent b6d0695 commit e5221fa

File tree

5 files changed

+94
-122
lines changed

5 files changed

+94
-122
lines changed

crypto/asymmetric_keys/public_key.c

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
#include <keys/asymmetric-subtype.h>
1919
#include <crypto/public_key.h>
2020
#include <crypto/akcipher.h>
21-
#include <crypto/sm2.h>
22-
#include <crypto/sm3_base.h>
2321

2422
MODULE_DESCRIPTION("In-software asymmetric public-key subtype");
2523
MODULE_AUTHOR("Red Hat, Inc.");
@@ -312,65 +310,6 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
312310
return ret;
313311
}
314312

315-
#if IS_REACHABLE(CONFIG_CRYPTO_SM2)
316-
static int cert_sig_digest_update(const struct public_key_signature *sig,
317-
struct crypto_akcipher *tfm_pkey)
318-
{
319-
struct crypto_shash *tfm;
320-
struct shash_desc *desc;
321-
size_t desc_size;
322-
unsigned char dgst[SM3_DIGEST_SIZE];
323-
int ret;
324-
325-
BUG_ON(!sig->data);
326-
327-
/* SM2 signatures always use the SM3 hash algorithm */
328-
if (!sig->hash_algo || strcmp(sig->hash_algo, "sm3") != 0)
329-
return -EINVAL;
330-
331-
ret = sm2_compute_z_digest(tfm_pkey, SM2_DEFAULT_USERID,
332-
SM2_DEFAULT_USERID_LEN, dgst);
333-
if (ret)
334-
return ret;
335-
336-
tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
337-
if (IS_ERR(tfm))
338-
return PTR_ERR(tfm);
339-
340-
desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
341-
desc = kzalloc(desc_size, GFP_KERNEL);
342-
if (!desc) {
343-
ret = -ENOMEM;
344-
goto error_free_tfm;
345-
}
346-
347-
desc->tfm = tfm;
348-
349-
ret = crypto_shash_init(desc);
350-
if (ret < 0)
351-
goto error_free_desc;
352-
353-
ret = crypto_shash_update(desc, dgst, SM3_DIGEST_SIZE);
354-
if (ret < 0)
355-
goto error_free_desc;
356-
357-
ret = crypto_shash_finup(desc, sig->data, sig->data_size, sig->digest);
358-
359-
error_free_desc:
360-
kfree(desc);
361-
error_free_tfm:
362-
crypto_free_shash(tfm);
363-
return ret;
364-
}
365-
#else
366-
static inline int cert_sig_digest_update(
367-
const struct public_key_signature *sig,
368-
struct crypto_akcipher *tfm_pkey)
369-
{
370-
return -ENOTSUPP;
371-
}
372-
#endif /* ! IS_REACHABLE(CONFIG_CRYPTO_SM2) */
373-
374313
/*
375314
* Verify a signature using a public key.
376315
*/
@@ -438,12 +377,6 @@ int public_key_verify_signature(const struct public_key *pkey,
438377
if (ret)
439378
goto error_free_key;
440379

441-
if (strcmp(pkey->pkey_algo, "sm2") == 0 && sig->data_size) {
442-
ret = cert_sig_digest_update(sig, tfm);
443-
if (ret)
444-
goto error_free_key;
445-
}
446-
447380
sg_init_table(src_sg, 2);
448381
sg_set_buf(&src_sg[0], sig->s, sig->s_size);
449382
sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);

crypto/asymmetric_keys/x509_public_key.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
*/
77

88
#define pr_fmt(fmt) "X.509: "fmt
9+
#include <crypto/hash.h>
10+
#include <crypto/sm2.h>
11+
#include <keys/asymmetric-parser.h>
12+
#include <keys/asymmetric-subtype.h>
13+
#include <keys/system_keyring.h>
914
#include <linux/module.h>
1015
#include <linux/kernel.h>
1116
#include <linux/slab.h>
12-
#include <keys/asymmetric-subtype.h>
13-
#include <keys/asymmetric-parser.h>
14-
#include <keys/system_keyring.h>
15-
#include <crypto/hash.h>
17+
#include <linux/string.h>
1618
#include "asymmetric_keys.h"
1719
#include "x509_parser.h"
1820

@@ -30,9 +32,6 @@ int x509_get_sig_params(struct x509_certificate *cert)
3032

3133
pr_devel("==>%s()\n", __func__);
3234

33-
sig->data = cert->tbs;
34-
sig->data_size = cert->tbs_size;
35-
3635
sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
3736
if (!sig->s)
3837
return -ENOMEM;
@@ -65,7 +64,21 @@ int x509_get_sig_params(struct x509_certificate *cert)
6564

6665
desc->tfm = tfm;
6766

68-
ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest);
67+
if (strcmp(cert->pub->pkey_algo, "sm2") == 0) {
68+
ret = strcmp(sig->hash_algo, "sm3") != 0 ? -EINVAL :
69+
crypto_shash_init(desc) ?:
70+
sm2_compute_z_digest(desc, cert->pub->key,
71+
cert->pub->keylen, sig->digest) ?:
72+
crypto_shash_init(desc) ?:
73+
crypto_shash_update(desc, sig->digest,
74+
sig->digest_size) ?:
75+
crypto_shash_finup(desc, cert->tbs, cert->tbs_size,
76+
sig->digest);
77+
} else {
78+
ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size,
79+
sig->digest);
80+
}
81+
6982
if (ret < 0)
7083
goto error_2;
7184

crypto/sm2.c

Lines changed: 70 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
#include <crypto/internal/akcipher.h>
1414
#include <crypto/akcipher.h>
1515
#include <crypto/hash.h>
16-
#include <crypto/sm3.h>
1716
#include <crypto/rng.h>
1817
#include <crypto/sm2.h>
1918
#include "sm2signature.asn1.h"
2019

20+
/* The default user id as specified in GM/T 0009-2012 */
21+
#define SM2_DEFAULT_USERID "1234567812345678"
22+
#define SM2_DEFAULT_USERID_LEN 16
23+
2124
#define MPI_NBYTES(m) ((mpi_get_nbits(m) + 7) / 8)
2225

2326
struct ecc_domain_parms {
@@ -60,6 +63,9 @@ static const struct ecc_domain_parms sm2_ecp = {
6063
.h = 1
6164
};
6265

66+
static int __sm2_set_pub_key(struct mpi_ec_ctx *ec,
67+
const void *key, unsigned int keylen);
68+
6369
static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec)
6470
{
6571
const struct ecc_domain_parms *ecp = &sm2_ecp;
@@ -213,85 +219,105 @@ int sm2_get_signature_s(void *context, size_t hdrlen, unsigned char tag,
213219
return 0;
214220
}
215221

216-
static int sm2_z_digest_update(struct sm3_state *sctx,
217-
MPI m, unsigned int pbytes)
222+
static int sm2_z_digest_update(struct shash_desc *desc,
223+
MPI m, unsigned int pbytes)
218224
{
219225
static const unsigned char zero[32];
220226
unsigned char *in;
221227
unsigned int inlen;
228+
int err;
222229

223230
in = mpi_get_buffer(m, &inlen, NULL);
224231
if (!in)
225232
return -EINVAL;
226233

227234
if (inlen < pbytes) {
228235
/* padding with zero */
229-
sm3_update(sctx, zero, pbytes - inlen);
230-
sm3_update(sctx, in, inlen);
236+
err = crypto_shash_update(desc, zero, pbytes - inlen) ?:
237+
crypto_shash_update(desc, in, inlen);
231238
} else if (inlen > pbytes) {
232239
/* skip the starting zero */
233-
sm3_update(sctx, in + inlen - pbytes, pbytes);
240+
err = crypto_shash_update(desc, in + inlen - pbytes, pbytes);
234241
} else {
235-
sm3_update(sctx, in, inlen);
242+
err = crypto_shash_update(desc, in, inlen);
236243
}
237244

238245
kfree(in);
239-
return 0;
246+
return err;
240247
}
241248

242-
static int sm2_z_digest_update_point(struct sm3_state *sctx,
243-
MPI_POINT point, struct mpi_ec_ctx *ec, unsigned int pbytes)
249+
static int sm2_z_digest_update_point(struct shash_desc *desc,
250+
MPI_POINT point, struct mpi_ec_ctx *ec,
251+
unsigned int pbytes)
244252
{
245253
MPI x, y;
246254
int ret = -EINVAL;
247255

248256
x = mpi_new(0);
249257
y = mpi_new(0);
250258

251-
if (!mpi_ec_get_affine(x, y, point, ec) &&
252-
!sm2_z_digest_update(sctx, x, pbytes) &&
253-
!sm2_z_digest_update(sctx, y, pbytes))
254-
ret = 0;
259+
ret = mpi_ec_get_affine(x, y, point, ec) ? -EINVAL :
260+
sm2_z_digest_update(desc, x, pbytes) ?:
261+
sm2_z_digest_update(desc, y, pbytes);
255262

256263
mpi_free(x);
257264
mpi_free(y);
258265
return ret;
259266
}
260267

261-
int sm2_compute_z_digest(struct crypto_akcipher *tfm,
262-
const unsigned char *id, size_t id_len,
263-
unsigned char dgst[SM3_DIGEST_SIZE])
268+
int sm2_compute_z_digest(struct shash_desc *desc,
269+
const void *key, unsigned int keylen, void *dgst)
264270
{
265-
struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
266-
uint16_t bits_len;
267-
unsigned char entl[2];
268-
struct sm3_state sctx;
271+
struct mpi_ec_ctx *ec;
272+
unsigned int bits_len;
269273
unsigned int pbytes;
274+
u8 entl[2];
275+
int err;
270276

271-
if (id_len > (USHRT_MAX / 8) || !ec->Q)
272-
return -EINVAL;
277+
ec = kmalloc(sizeof(*ec), GFP_KERNEL);
278+
if (!ec)
279+
return -ENOMEM;
280+
281+
err = __sm2_set_pub_key(ec, key, keylen);
282+
if (err)
283+
goto out_free_ec;
273284

274-
bits_len = (uint16_t)(id_len * 8);
285+
bits_len = SM2_DEFAULT_USERID_LEN * 8;
275286
entl[0] = bits_len >> 8;
276287
entl[1] = bits_len & 0xff;
277288

278289
pbytes = MPI_NBYTES(ec->p);
279290

280291
/* ZA = H256(ENTLA | IDA | a | b | xG | yG | xA | yA) */
281-
sm3_init(&sctx);
282-
sm3_update(&sctx, entl, 2);
283-
sm3_update(&sctx, id, id_len);
284-
285-
if (sm2_z_digest_update(&sctx, ec->a, pbytes) ||
286-
sm2_z_digest_update(&sctx, ec->b, pbytes) ||
287-
sm2_z_digest_update_point(&sctx, ec->G, ec, pbytes) ||
288-
sm2_z_digest_update_point(&sctx, ec->Q, ec, pbytes))
289-
return -EINVAL;
292+
err = crypto_shash_init(desc);
293+
if (err)
294+
goto out_deinit_ec;
290295

291-
sm3_final(&sctx, dgst);
292-
return 0;
296+
err = crypto_shash_update(desc, entl, 2);
297+
if (err)
298+
goto out_deinit_ec;
299+
300+
err = crypto_shash_update(desc, SM2_DEFAULT_USERID,
301+
SM2_DEFAULT_USERID_LEN);
302+
if (err)
303+
goto out_deinit_ec;
304+
305+
err = sm2_z_digest_update(desc, ec->a, pbytes) ?:
306+
sm2_z_digest_update(desc, ec->b, pbytes) ?:
307+
sm2_z_digest_update_point(desc, ec->G, ec, pbytes) ?:
308+
sm2_z_digest_update_point(desc, ec->Q, ec, pbytes);
309+
if (err)
310+
goto out_deinit_ec;
311+
312+
err = crypto_shash_final(desc, dgst);
313+
314+
out_deinit_ec:
315+
sm2_ec_ctx_deinit(ec);
316+
out_free_ec:
317+
kfree(ec);
318+
return err;
293319
}
294-
EXPORT_SYMBOL(sm2_compute_z_digest);
320+
EXPORT_SYMBOL_GPL(sm2_compute_z_digest);
295321

296322
static int _sm2_verify(struct mpi_ec_ctx *ec, MPI hash, MPI sig_r, MPI sig_s)
297323
{
@@ -391,6 +417,14 @@ static int sm2_set_pub_key(struct crypto_akcipher *tfm,
391417
const void *key, unsigned int keylen)
392418
{
393419
struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
420+
421+
return __sm2_set_pub_key(ec, key, keylen);
422+
423+
}
424+
425+
static int __sm2_set_pub_key(struct mpi_ec_ctx *ec,
426+
const void *key, unsigned int keylen)
427+
{
394428
MPI a;
395429
int rc;
396430

include/crypto/public_key.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ struct public_key_signature {
4848
const char *pkey_algo;
4949
const char *hash_algo;
5050
const char *encoding;
51-
const void *data;
52-
unsigned int data_size;
5351
};
5452

5553
extern void public_key_signature_free(struct public_key_signature *sig);

include/crypto/sm2.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,9 @@
1111
#ifndef _CRYPTO_SM2_H
1212
#define _CRYPTO_SM2_H
1313

14-
#include <crypto/sm3.h>
15-
#include <crypto/akcipher.h>
14+
struct shash_desc;
1615

17-
/* The default user id as specified in GM/T 0009-2012 */
18-
#define SM2_DEFAULT_USERID "1234567812345678"
19-
#define SM2_DEFAULT_USERID_LEN 16
20-
21-
extern int sm2_compute_z_digest(struct crypto_akcipher *tfm,
22-
const unsigned char *id, size_t id_len,
23-
unsigned char dgst[SM3_DIGEST_SIZE]);
16+
int sm2_compute_z_digest(struct shash_desc *desc,
17+
const void *key, unsigned int keylen, void *dgst);
2418

2519
#endif /* _CRYPTO_SM2_H */

0 commit comments

Comments
 (0)