Skip to content

Commit bab00ec

Browse files
committed
Refactor SubjectPublicKeyInfo import
Slightly minimize both space and time when importing a SubjectPublicKeyInfo. 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] ``` ==1980544== HEAP SUMMARY: ==1980544== in use at exit: 0 bytes in 0 blocks ==1980544== total heap usage: 292,202 allocs, 292,202 frees, 41,089,931 bytes allocated ``` [1] ``` x509 cert-rsa-pss.pem : 50436 cycles x509 LTC_CA.pem : 10669 cycles x509 LTC_S0.pem : 49137 cycles x509 LTC_SS0.pem : 38253 cycles x509 secp384r1.pem : 2152532 cycles x509 secp521r1.pem : 3401689 cycles x509 LTC_SSS0.pem : 24910 cycles x509 secp224r1.pem : 830851 cycles ``` After this patch: [0] ``` ==1973920== HEAP SUMMARY: ==1973920== in use at exit: 0 bytes in 0 blocks ==1973920== total heap usage: 229,984 allocs, 229,984 frees, 35,093,923 bytes allocated ``` [1] ``` x509 cert-rsa-pss.pem : 33132 cycles x509 LTC_CA.pem : 5348 cycles x509 LTC_S0.pem : 36368 cycles x509 LTC_SS0.pem : 24032 cycles x509 secp384r1.pem : 2059992 cycles x509 secp521r1.pem : 3291269 cycles x509 LTC_SSS0.pem : 14192 cycles x509 secp224r1.pem : 844587 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 <[email protected]>
1 parent 07d7c64 commit bab00ec

File tree

6 files changed

+164
-67
lines changed

6 files changed

+164
-67
lines changed

src/headers/tomcrypt_pk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_ke
163163
int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
164164

165165
int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key);
166+
int rsa_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key);
166167
int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
167168
const password_ctx *pw_ctx, rsa_key *key);
168169

src/headers/tomcrypt_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,8 @@ int dsa_int_validate(const dsa_key *key, int *stat);
561561
int dsa_int_validate_xy(const dsa_key *key, int *stat);
562562
int dsa_int_validate_pqg(const dsa_key *key, int *stat);
563563
int dsa_int_validate_primes(const dsa_key *key, int *stat);
564-
int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key);
565564
int dsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dsa_key *key);
565+
int dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_key *key);
566566
#endif /* LTC_MDSA */
567567

568568

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: 45 additions & 13 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;
@@ -41,6 +41,24 @@ LTC_INLINE static int s_dsa_set_params(dsa_key *key, ltc_asn1_list *params)
4141
return 3;
4242
}
4343

44+
LTC_INLINE static 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;

src/pk/rsa/rsa_import_x509.c

Lines changed: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -126,51 +126,58 @@ int rsa_decode_parameters(const ltc_asn1_list *parameters, ltc_rsa_parameters *r
126126
}
127127
}
128128

129-
130129
rsa_params->pss_oaep = 1;
131130

132131
return CRYPT_OK;
133132
}
134133

135-
static int s_rsa_import_pss(const unsigned char *in, unsigned long inlen, rsa_key *key)
134+
LTC_INLINE static int s_rsa_1_5_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key)
135+
{
136+
return x509_process_public_key_from_spki(in, inlen,
137+
LTC_OID_RSA,
138+
LTC_ASN1_NULL, NULL, NULL,
139+
(public_key_decode_cb)s_rsa_decode, key);
140+
}
141+
142+
LTC_INLINE static int s_rsa_pss_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key)
136143
{
137144
rsa_pss_parameters_data d;
138-
ltc_asn1_list *decoded_list;
139-
const ltc_asn1_list *spki;
140-
int err;
141145
unsigned long n_params = LTC_ARRAY_SIZE(d.params);
142146

143-
if ((err = x509_process_public_key_from_spki(in, inlen,
144-
LTC_OID_RSA_PSS,
145-
LTC_ASN1_NULL, NULL, NULL,
146-
(public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
147-
if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) {
148-
return err;
149-
}
150-
if ((err = x509_process_public_key_from_spki(spki->data, spki->size,
151-
LTC_OID_RSA_PSS,
152-
LTC_ASN1_NULL, NULL, NULL,
153-
(public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
154-
s_rsa_pss_parameters_data_setup(&d);
155-
err = x509_process_public_key_from_spki(spki->data, spki->size,
156-
LTC_OID_RSA_PSS,
157-
LTC_ASN1_SEQUENCE, d.params, &n_params,
158-
(public_key_decode_cb)s_rsa_decode, key);
159-
}
147+
if (x509_process_public_key_from_spki(in, inlen,
148+
LTC_OID_RSA_PSS,
149+
LTC_ASN1_NULL, NULL, NULL,
150+
(public_key_decode_cb)s_rsa_decode, key) == CRYPT_OK) {
151+
return CRYPT_OK;
160152
}
153+
s_rsa_pss_parameters_data_setup(&d);
154+
return x509_process_public_key_from_spki(in, inlen,
155+
LTC_OID_RSA_PSS,
156+
LTC_ASN1_SEQUENCE, d.params, &n_params,
157+
(public_key_decode_cb)s_rsa_decode, key);
158+
}
161159

162-
der_free_sequence_flexi(decoded_list);
160+
LTC_INLINE static int s_rsa_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key)
161+
{
162+
int err;
163+
if (s_rsa_1_5_import_spki(in, inlen, key) == CRYPT_OK) {
164+
return CRYPT_OK;
165+
}
166+
167+
if ((err = s_rsa_pss_import_spki(in, inlen, key)) == CRYPT_OK) {
168+
return CRYPT_OK;
169+
}
163170
return err;
164171
}
165172

166173
/**
167-
Import an RSA key from a X.509 certificate
174+
Import an RSA key from SubjectPublicKeyInfo
168175
@param in The packet to import from
169176
@param inlen It's length (octets)
170177
@param key [out] Destination for newly imported key
171178
@return CRYPT_OK if successful, upon error allocated memory is freed
172179
*/
173-
int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
180+
int rsa_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key)
174181
{
175182
int err;
176183

@@ -183,22 +190,58 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
183190
return err;
184191
}
185192

186-
if ((err = x509_decode_public_key_from_certificate(in, inlen,
187-
LTC_OID_RSA,
188-
LTC_ASN1_NULL, NULL, NULL,
189-
(public_key_decode_cb)s_rsa_decode, key)) == CRYPT_OK) {
193+
if ((err = s_rsa_import_spki(in, inlen, key)) == CRYPT_OK) {
190194
key->type = PK_PUBLIC;
191195
return CRYPT_OK;
192196
}
193197

194-
if ((err = s_rsa_import_pss(in, inlen, key)) == CRYPT_OK) {
198+
rsa_free(key);
199+
200+
return err;
201+
}
202+
203+
/**
204+
Import an RSA key from a X.509 certificate
205+
@param in The packet to import from
206+
@param inlen It's length (octets)
207+
@param key [out] Destination for newly imported key
208+
@return CRYPT_OK if successful, upon error allocated memory is freed
209+
*/
210+
int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
211+
{
212+
ltc_asn1_list *decoded_list;
213+
const ltc_asn1_list *spki;
214+
int err;
215+
216+
LTC_ARGCHK(in != NULL);
217+
LTC_ARGCHK(key != NULL);
218+
LTC_ARGCHK(ltc_mp.name != NULL);
219+
220+
/* init key */
221+
if ((err = rsa_init(key)) != CRYPT_OK) {
222+
return err;
223+
}
224+
225+
/* First try to decode as SubjectPublicKeyInfo */
226+
if (s_rsa_import_spki(in, inlen, key) == CRYPT_OK) {
195227
key->type = PK_PUBLIC;
196228
return CRYPT_OK;
197229
}
198230

199-
rsa_free(key);
231+
/* Now try to extract the SubjectPublicKeyInfo from the Certificate */
232+
if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) {
233+
rsa_free(key);
234+
return err;
235+
}
236+
err = s_rsa_import_spki(spki->data, spki->size, key);
200237

201-
return err;
238+
der_free_sequence_flexi(decoded_list);
239+
if (err != CRYPT_OK) {
240+
rsa_free(key);
241+
return err;
242+
}
243+
key->type = PK_PUBLIC;
244+
return CRYPT_OK;
202245
}
203246

204247
#endif /* LTC_MRSA */

0 commit comments

Comments
 (0)