Skip to content

Commit 7a2891f

Browse files
committed
Refactor SubjectPublicKeyInfo import
Slightly minimize both space and time when importing a SubjectPublicKeyInfo. Time for ECC keys stays the same. Those tests were done with X.509 support already available, but later these commits were split up to be independent of the X.509 feature. Running the entire set of pem files through `x509_verify` via [0] resp. the timing app via [1] resulted in the following data: Before this patch: [0] ``` ==1031519== HEAP SUMMARY: ==1031519== in use at exit: 0 bytes in 0 blocks ==1031519== total heap usage: 424,057 allocs, 424,057 frees, 73,527,730 bytes allocated ``` [1] ``` x509 cert-rsa-pss.pem : 50021 cycles x509 LTC_CA.pem : 10335 cycles x509 LTC_S0.pem : 47284 cycles x509 LTC_SS0.pem : 36687 cycles x509 secp384r1.pem : 1985416 cycles x509 secp521r1.pem : 3287773 cycles x509 LTC_SSS0.pem : 25086 cycles x509 secp224r1.pem : 775807 cycles ``` After this patch: [0] ``` ==1043548== HEAP SUMMARY: ==1043548== in use at exit: 0 bytes in 0 blocks ==1043548== total heap usage: 337,244 allocs, 337,244 frees, 65,047,463 bytes allocated ``` [1] ``` x509 cert-rsa-pss.pem : 32568 cycles x509 LTC_CA.pem : 5478 cycles x509 LTC_S0.pem : 36093 cycles x509 LTC_SS0.pem : 23351 cycles x509 secp384r1.pem : 1984030 cycles x509 secp521r1.pem : 3303396 cycles x509 LTC_SSS0.pem : 13220 cycles x509 secp224r1.pem : 781534 cycles ``` [0] find tests/x509 -name '*.pem' -exec valgrind --leak-check=full --show-leak-kinds=all './x509_verify' {} \+ [1] ./timing x509 Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent aeec5ea commit 7a2891f

File tree

6 files changed

+198
-89
lines changed

6 files changed

+198
-89
lines changed

src/headers/tomcrypt_private.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e,
426426
rsa_key *key); /* used by op-tee */
427427
int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key);
428428
int rsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, rsa_key *key);
429+
int rsa_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key);
430+
int rsa_decode_parameters(const ltc_asn1_list *parameters, ltc_rsa_parameters *rsa_params);
429431
#endif /* LTC_MRSA */
430432

431433
/* ---- DH Routines ---- */
@@ -533,8 +535,8 @@ int dsa_int_validate(const dsa_key *key, int *stat);
533535
int dsa_int_validate_xy(const dsa_key *key, int *stat);
534536
int dsa_int_validate_pqg(const dsa_key *key, int *stat);
535537
int dsa_int_validate_primes(const dsa_key *key, int *stat);
536-
int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key);
537538
int dsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dsa_key *key);
539+
int dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_key *key);
538540
#endif /* LTC_MDSA */
539541

540542

@@ -649,17 +651,17 @@ int der_teletex_value_decode(int v);
649651

650652
int der_utf8_valid_char(const wchar_t c);
651653

652-
typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *ctx);
654+
typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *key);
653655

654656
int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
655657
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
656658
ltc_asn1_list* parameters, unsigned long *parameters_len,
657-
public_key_decode_cb callback, void *ctx);
659+
public_key_decode_cb callback, void *key);
658660
int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, const ltc_asn1_list **spki);
659661
int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen,
660662
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
661663
ltc_asn1_list* parameters, unsigned long *parameters_len,
662-
public_key_decode_cb callback, void *ctx);
664+
public_key_decode_cb callback, void *key);
663665

664666
/* SUBJECT PUBLIC KEY INFO */
665667
int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,

src/pk/asn1/x509/x509_decode_public_key_from_certificate.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen,
2525
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
2626
ltc_asn1_list* parameters, unsigned long *parameters_len,
27-
public_key_decode_cb callback, void *ctx)
27+
public_key_decode_cb callback, void *key)
2828
{
2929
int err;
3030
unsigned char *tmpbuf = NULL;
@@ -34,7 +34,7 @@ int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inl
3434
LTC_ARGCHK(callback != NULL);
3535

3636
if (algorithm == LTC_OID_EC) {
37-
err = callback(in, inlen, ctx);
37+
err = callback(in, inlen, key);
3838
} else {
3939

4040
tmpbuf_len = inlen;
@@ -47,7 +47,7 @@ int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inl
4747
algorithm, tmpbuf, &tmpbuf_len,
4848
param_type, parameters, parameters_len);
4949
if (err == CRYPT_OK) {
50-
err = callback(tmpbuf, tmpbuf_len, ctx);
50+
err = callback(tmpbuf, tmpbuf_len, key);
5151
}
5252
}
5353

@@ -73,7 +73,7 @@ int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inl
7373
int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
7474
enum ltc_oid_id algorithm, ltc_asn1_type param_type,
7575
ltc_asn1_list* parameters, unsigned long *parameters_len,
76-
public_key_decode_cb callback, void *ctx)
76+
public_key_decode_cb callback, void *key)
7777
{
7878
int err;
7979
ltc_asn1_list *decoded_list;
@@ -90,7 +90,7 @@ int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned lo
9090
err = x509_process_public_key_from_spki(spki->data, spki->size,
9191
algorithm, param_type,
9292
parameters, parameters_len,
93-
callback, ctx);
93+
callback, key);
9494

9595
if (decoded_list) der_free_sequence_flexi(decoded_list);
9696

src/pk/asn1/x509/x509_import_spki.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,48 @@
99

1010
#ifdef LTC_DER
1111

12-
typedef int (*import_fn)(const unsigned char *, unsigned long, void*);
12+
typedef int (*import_fn)(const unsigned char *, unsigned long, void *);
1313

14-
static const import_fn s_import_x509_fns[LTC_PKA_NUM] = {
14+
#ifdef LTC_CURVE25519
15+
static int s_x25519_import_pub(const unsigned char *in, unsigned long inlen, void *key)
16+
{
17+
return x25519_import_raw(in, inlen, PK_PUBLIC, key);
18+
}
19+
static int s_x25519_import_spki(const unsigned char *in, unsigned long inlen, void *key)
20+
{
21+
return x509_process_public_key_from_spki(in, inlen,
22+
LTC_OID_X25519,
23+
LTC_ASN1_EOL, NULL, NULL,
24+
s_x25519_import_pub, key);
25+
}
26+
27+
static int s_ed25519_import_pub(const unsigned char *in, unsigned long inlen, void *key)
28+
{
29+
return ed25519_import_raw(in, inlen, PK_PUBLIC, key);
30+
}
31+
static int s_ed25519_import_spki(const unsigned char *in, unsigned long inlen, void *key)
32+
{
33+
return x509_process_public_key_from_spki(in, inlen,
34+
LTC_OID_ED25519,
35+
LTC_ASN1_EOL, NULL, NULL,
36+
s_ed25519_import_pub, key);
37+
}
38+
#endif
39+
40+
static const import_fn s_import_spki_fns[LTC_PKA_NUM] = {
1541
#ifdef LTC_MRSA
16-
[LTC_PKA_RSA] = (import_fn)rsa_import_x509,
17-
[LTC_PKA_RSA_PSS] = (import_fn)rsa_import_x509,
42+
[LTC_PKA_RSA] = (import_fn)rsa_import_spki,
43+
[LTC_PKA_RSA_PSS] = (import_fn)rsa_import_spki,
1844
#endif
1945
#ifdef LTC_MDSA
20-
[LTC_PKA_DSA] = (import_fn)dsa_import,
46+
[LTC_PKA_DSA] = (import_fn)dsa_import_spki,
2147
#endif
2248
#ifdef LTC_MECC
23-
[LTC_PKA_EC] = (import_fn)ecc_import_x509,
49+
[LTC_PKA_EC] = (import_fn)ecc_import_subject_public_key_info,
2450
#endif
2551
#ifdef LTC_CURVE25519
26-
[LTC_PKA_X25519] = (import_fn)x25519_import_x509,
27-
[LTC_PKA_ED25519] = (import_fn)ed25519_import_x509,
52+
[LTC_PKA_X25519] = (import_fn)s_x25519_import_spki,
53+
[LTC_PKA_ED25519] = (import_fn)s_ed25519_import_spki,
2854
#endif
2955
};
3056

@@ -41,12 +67,12 @@ int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc
4167
goto err_out;
4268
}
4369
if (pka < 0
44-
|| pka > LTC_ARRAY_SIZE(s_import_x509_fns)
45-
|| s_import_x509_fns[pka] == NULL) {
70+
|| pka > LTC_ARRAY_SIZE(s_import_spki_fns)
71+
|| s_import_spki_fns[pka] == NULL) {
4672
err = CRYPT_PK_INVALID_TYPE;
4773
goto err_out;
4874
}
49-
if ((err = s_import_x509_fns[pka](asn1_cert, asn1_len, &k->u)) == CRYPT_OK) {
75+
if ((err = s_import_spki_fns[pka](spki->data, spki->size, &k->u)) == CRYPT_OK) {
5076
k->id = pka;
5177
}
5278
err_out:

src/pk/dsa/dsa_import.c

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
#ifdef LTC_MDSA
1111

12-
int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key)
12+
static int s_dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key)
1313
{
1414
int err;
1515
unsigned long zero = 0;
@@ -33,14 +33,32 @@ static int s_dsa_import_y(const unsigned char *in, unsigned long inlen, dsa_key
3333
return der_decode_integer(in, inlen, key->y);
3434
}
3535

36-
LTC_INLINE static int s_dsa_set_params(dsa_key *key, ltc_asn1_list *params)
36+
static LTC_INLINE int s_dsa_set_params(dsa_key *key, ltc_asn1_list *params)
3737
{
3838
LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL);
3939
LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL);
4040
LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL);
4141
return 3;
4242
}
4343

44+
static LTC_INLINE int s_dsa_validate(dsa_key *key)
45+
{
46+
int err, stat;
47+
key->qord = ltc_mp_unsigned_bin_size(key->q);
48+
49+
/* quick p, q, g validation, without primality testing
50+
* + x, y validation */
51+
if ((err = dsa_int_validate(key, &stat)) != CRYPT_OK) {
52+
return err;
53+
}
54+
55+
if (stat == 0) {
56+
return CRYPT_INVALID_PACKET;
57+
}
58+
59+
return CRYPT_OK;
60+
}
61+
4462
static int s_dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_key *key)
4563
{
4664
int err;
@@ -72,6 +90,28 @@ static int s_dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_k
7290
return err;
7391
}
7492

93+
int dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_key *key)
94+
{
95+
int err;
96+
97+
LTC_ARGCHK(in != NULL);
98+
99+
/* init key */
100+
if ((err = dsa_int_init(key)) != CRYPT_OK) return err;
101+
102+
if ((err = s_dsa_import_spki(in, inlen, key)) != CRYPT_OK) {
103+
goto LBL_ERR;
104+
}
105+
if ((err = s_dsa_validate(key)) != CRYPT_OK) {
106+
goto LBL_ERR;
107+
}
108+
109+
return CRYPT_OK;
110+
LBL_ERR:
111+
dsa_free(key);
112+
return err;
113+
}
114+
75115
static int s_dsa_import_x509(const unsigned char *in, unsigned long inlen, dsa_key *key)
76116
{
77117
int err;
@@ -100,7 +140,7 @@ static int s_dsa_import_x509(const unsigned char *in, unsigned long inlen, dsa_k
100140
*/
101141
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
102142
{
103-
int err, stat;
143+
int err;
104144
unsigned char flags[1];
105145

106146
LTC_ARGCHK(in != NULL);
@@ -148,26 +188,18 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
148188
}
149189
}
150190

151-
if (dsa_import_pkcs1(in, inlen, key) == CRYPT_OK) {
191+
if (s_dsa_import_pkcs1(in, inlen, key) == CRYPT_OK) {
152192
goto LBL_OK;
153193
}
154-
if ((err = s_dsa_import_spki(in, inlen, key)) == CRYPT_OK) {
194+
if (s_dsa_import_spki(in, inlen, key) == CRYPT_OK) {
155195
goto LBL_OK;
156196
}
157197
if ((err = s_dsa_import_x509(in, inlen, key)) != CRYPT_OK) {
158198
goto LBL_ERR;
159199
}
160200

161201
LBL_OK:
162-
key->qord = ltc_mp_unsigned_bin_size(key->q);
163-
164-
/* quick p, q, g validation, without primality testing
165-
* + x, y validation */
166-
if ((err = dsa_int_validate(key, &stat)) != CRYPT_OK) {
167-
goto LBL_ERR;
168-
}
169-
if (stat == 0) {
170-
err = CRYPT_INVALID_PACKET;
202+
if ((err = s_dsa_validate(key)) != CRYPT_OK) {
171203
goto LBL_ERR;
172204
}
173205

src/pk/rsa/rsa_import.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,23 +99,18 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
9999
LTC_ARGCHK(key != NULL);
100100
LTC_ARGCHK(ltc_mp.name != NULL);
101101

102-
if ((err = rsa_import_x509(in, inlen, key)) == CRYPT_OK) { /* SubjectPublicKeyInfo format */
102+
/* SubjectPublicKeyInfo or X.509 certificate format */
103+
if (rsa_import_x509(in, inlen, key) == CRYPT_OK) {
103104
return CRYPT_OK;
104105
}
105106

106107
/* init key */
107108
if ((err = rsa_init(key)) != CRYPT_OK) {
108109
return err;
109110
}
110-
111-
if ((err = x509_process_public_key_from_spki(in, inlen,
112-
LTC_OID_RSA,
113-
LTC_ASN1_NULL, NULL, NULL,
114-
(public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
115-
/* not SSL public key, try to match against PKCS #1 standards */
116-
if ((err = rsa_import_pkcs1(in, inlen, key)) != CRYPT_OK) {
117-
rsa_free(key);
118-
}
111+
/* Try to match against PKCS #1 standards */
112+
if ((err = rsa_import_pkcs1(in, inlen, key)) != CRYPT_OK) {
113+
rsa_free(key);
119114
}
120115

121116
return err;

0 commit comments

Comments
 (0)