Skip to content

Commit 107b82c

Browse files
committed
re-factor PKCS#8 API a bit
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent 9f1db6a commit 107b82c

File tree

13 files changed

+382
-326
lines changed

13 files changed

+382
-326
lines changed

src/headers/tomcrypt_misc.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,6 @@ int padding_depad(const unsigned char *data, unsigned long *length, unsigned lon
160160
#endif /* LTC_PADDING */
161161

162162
#ifdef LTC_PEM
163-
typedef struct {
164-
int (*callback)(void **, unsigned long *, void *);
165-
void *userdata;
166-
} password_ctx;
167163

168164
#ifdef LTC_SSH
169165
int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, password_ctx *pw_ctx);

src/headers/tomcrypt_pk.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
22
/* SPDX-License-Identifier: Unlicense */
33

4+
typedef struct {
5+
int (*callback)(void **, unsigned long *, void *);
6+
void *userdata;
7+
} password_ctx;
8+
49
/* ---- NUMBER THEORY ---- */
510

611
enum public_key_type {
@@ -106,7 +111,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
106111

107112
int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key);
108113
int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
109-
const void *passwd, unsigned long passwdlen, rsa_key *key);
114+
const password_ctx *pw_ctx, rsa_key *key);
110115

111116
int rsa_set_key(const unsigned char *N, unsigned long Nlen,
112117
const unsigned char *e, unsigned long elen,
@@ -278,7 +283,7 @@ int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_ke
278283

279284
int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key);
280285
int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key);
281-
int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ecc_key *key);
286+
int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, ecc_key *key);
282287
int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key);
283288

284289
int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key,
@@ -351,9 +356,9 @@ int ed25519_export( unsigned char *out, unsigned long *outlen,
351356
int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key);
352357
int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key);
353358
int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key);
354-
int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
355-
const void *pwd, unsigned long pwdlen,
356-
curve25519_key *key);
359+
int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
360+
const password_ctx *pw_ctx,
361+
curve25519_key *key);
357362

358363
int ed25519_sign(const unsigned char *msg, unsigned long msglen,
359364
unsigned char *sig, unsigned long *siglen,
@@ -373,9 +378,9 @@ int x25519_export( unsigned char *out, unsigned long *outlen,
373378
int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key);
374379
int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key);
375380
int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key);
376-
int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
377-
const void *pwd, unsigned long pwdlen,
378-
curve25519_key *key);
381+
int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
382+
const password_ctx *pw_ctx,
383+
curve25519_key *key);
379384

380385
int x25519_shared_secret(const curve25519_key *private_key,
381386
const curve25519_key *public_key,

src/headers/tomcrypt_private.h

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ typedef struct {
5555
typedef struct
5656
{
5757
pbes_properties type;
58-
const void *pwd;
58+
void *pwd;
5959
unsigned long pwdlen;
6060
ltc_asn1_list *enc_data;
6161
ltc_asn1_list *salt;
@@ -309,6 +309,7 @@ int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx
309309
int ecc_copy_curve(const ecc_key *srckey, ecc_key *key);
310310
int ecc_set_curve_by_size(int size, ecc_key *key);
311311
int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key);
312+
int ecc_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, ecc_key *key);
312313

313314
#ifdef LTC_SSH
314315
int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key);
@@ -398,11 +399,18 @@ int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk);
398399
int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
399400
int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n);
400401

401-
typedef int (*sk_to_pk)(unsigned char *pk ,const unsigned char *sk);
402+
int ed25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
403+
curve25519_key *key);
404+
int x25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
405+
curve25519_key *key);
406+
407+
int ec25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
408+
enum ltc_oid_id id,
409+
curve25519_key *key);
402410
int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
403-
const void *pwd, unsigned long pwdlen,
404-
enum ltc_oid_id id, sk_to_pk fp,
405-
curve25519_key *key);
411+
const password_ctx *pw_ctx,
412+
enum ltc_oid_id id,
413+
curve25519_key *key);
406414
int ec25519_export( unsigned char *out, unsigned long *outlen,
407415
int which,
408416
const curve25519_key *key);
@@ -481,12 +489,35 @@ int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2);
481489

482490
#ifdef LTC_PKCS_8
483491

492+
/* Public-Key Cryptography Standards (PKCS) #8:
493+
* Private-Key Information Syntax Specification Version 1.2
494+
* https://tools.ietf.org/html/rfc5208
495+
*
496+
* PrivateKeyInfo ::= SEQUENCE {
497+
* version Version,
498+
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
499+
* privateKey PrivateKey,
500+
* attributes [0] IMPLICIT Attributes OPTIONAL }
501+
* where:
502+
* - Version ::= INTEGER
503+
* - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
504+
* - PrivateKey ::= OCTET STRING
505+
* - Attributes ::= SET OF Attribute
506+
*
507+
* EncryptedPrivateKeyInfo ::= SEQUENCE {
508+
* encryptionAlgorithm EncryptionAlgorithmIdentifier,
509+
* encryptedData EncryptedData }
510+
* where:
511+
* - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
512+
* - EncryptedData ::= OCTET STRING
513+
*/
514+
484515
int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
485-
const void *pwd, unsigned long pwdlen,
486-
ltc_asn1_list **decoded_list);
516+
const password_ctx *pw_ctx,
517+
ltc_asn1_list **decoded_list);
487518

488519
int pkcs8_get_children(const ltc_asn1_list *decoded_list, enum ltc_oid_id *pka,
489-
ltc_asn1_list **seq, ltc_asn1_list **priv_key);
520+
ltc_asn1_list **alg_id, ltc_asn1_list **priv_key);
490521

491522
#endif /* LTC_PKCS_8 */
492523

src/pk/asn1/pkcs8/pkcs8_decode_flexi.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,21 @@
1515
@return CRYPT_OK on success
1616
*/
1717
int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
18-
const void *pwd, unsigned long pwdlen,
18+
const password_ctx *pw_ctx,
1919
ltc_asn1_list **decoded_list)
2020
{
2121
unsigned long len = inlen;
2222
unsigned long dec_size;
2323
unsigned char *dec_data = NULL;
2424
ltc_asn1_list *l = NULL;
2525
int err;
26+
pbes_arg pbes;
2627

2728
LTC_ARGCHK(in != NULL);
2829
LTC_ARGCHK(decoded_list != NULL);
2930

31+
XMEMSET(&pbes, 0, sizeof(pbes));
32+
3033
*decoded_list = NULL;
3134
if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) {
3235
/* the following "if" detects whether it is encrypted or not */
@@ -44,9 +47,9 @@ int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
4447
LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) &&
4548
LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) {
4649
ltc_asn1_list *lalgoid = l->child->child;
47-
pbes_arg pbes;
4850

49-
XMEMSET(&pbes, 0, sizeof(pbes));
51+
LTC_ARGCHK(pw_ctx != NULL);
52+
LTC_ARGCHK(pw_ctx->callback != NULL);
5053

5154
if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) {
5255
/* Successfully extracted PBES1 parameters */
@@ -58,9 +61,12 @@ int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
5861
goto LBL_DONE;
5962
}
6063

64+
if (pw_ctx->callback(&pbes.pwd, &pbes.pwdlen, pw_ctx->userdata)) {
65+
err = CRYPT_ERROR;
66+
goto LBL_DONE;
67+
}
68+
6169
pbes.enc_data = l->child->next;
62-
pbes.pwd = pwd;
63-
pbes.pwdlen = pwdlen;
6470

6571
dec_size = pbes.enc_data->size;
6672
if ((dec_data = XMALLOC(dec_size)) == NULL) {
@@ -87,6 +93,10 @@ int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
8793

8894
LBL_DONE:
8995
if (l) der_free_sequence_flexi(l);
96+
if (pbes.pwd) {
97+
zeromem(pbes.pwd, pbes.pwdlen);
98+
XFREE(pbes.pwd);
99+
}
90100
if (dec_data) {
91101
zeromem(dec_data, dec_size);
92102
XFREE(dec_data);

src/pk/ec25519/ec25519_import_pkcs8.c

Lines changed: 59 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -9,78 +9,77 @@
99

1010
#ifdef LTC_CURVE25519
1111

12+
typedef int (*sk_to_pk)(unsigned char *pk , const unsigned char *sk);
13+
14+
int ec25519_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key,
15+
enum ltc_oid_id id,
16+
curve25519_key *key)
17+
{
18+
int err;
19+
unsigned long key_len;
20+
sk_to_pk fp;
21+
22+
LTC_ARGCHK(key != NULL);
23+
LTC_ARGCHK(ltc_mp.name != NULL);
24+
25+
LTC_UNUSED_PARAM(alg_id);
26+
27+
switch (id) {
28+
case LTC_OID_ED25519:
29+
fp = tweetnacl_crypto_sk_to_pk;
30+
break;
31+
case LTC_OID_X25519:
32+
fp = tweetnacl_crypto_scalarmult_base;
33+
break;
34+
default:
35+
return CRYPT_PK_INVALID_TYPE;
36+
}
37+
38+
key_len = sizeof(key->priv);
39+
if ((err = der_decode_octet_string(priv_key->data, priv_key->size, key->priv, &key_len)) == CRYPT_OK) {
40+
fp(key->pub, key->priv);
41+
key->type = PK_PRIVATE;
42+
key->algo = id;
43+
}
44+
return err;
45+
}
46+
1247
/**
1348
Generic import of a Curve/Ed25519 private key in PKCS#8 format
14-
@param in The DER-encoded PKCS#8-formatted private key
15-
@param inlen The length of the input data
16-
@param passwd The password to decrypt the private key
17-
@param passwdlen Password's length (octets)
18-
@param key [out] Where to import the key to
49+
@param in The packet to import from
50+
@param inlen It's length (octets)
51+
@param pw_ctx The password context when decrypting the private key
52+
@param id The type of the private key
53+
@param key [out] Destination for newly imported key
1954
@return CRYPT_OK if successful, on error all allocated memory is freed automatically
2055
*/
2156
int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
22-
const void *pwd, unsigned long pwdlen,
23-
enum ltc_oid_id id, sk_to_pk fp,
24-
curve25519_key *key)
57+
const password_ctx *pw_ctx,
58+
enum ltc_oid_id id,
59+
curve25519_key *key)
2560
{
26-
int err;
61+
int err;
2762
ltc_asn1_list *l = NULL;
28-
const char *oid;
29-
ltc_asn1_list alg_id[1];
30-
unsigned char private_key[34];
31-
unsigned long version, key_len;
32-
unsigned long tmpoid[16];
33-
34-
LTC_ARGCHK(in != NULL);
35-
LTC_ARGCHK(key != NULL);
36-
LTC_ARGCHK(fp != NULL);
37-
38-
if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) {
63+
ltc_asn1_list *alg_id, *priv_key;
64+
enum ltc_oid_id pka;
3965

40-
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid) / sizeof(tmpoid[0]));
66+
LTC_ARGCHK(in != NULL);
4167

42-
key_len = sizeof(private_key);
43-
if ((err = der_decode_sequence_multi(l->data, l->size,
44-
LTC_ASN1_SHORT_INTEGER, 1uL, &version,
45-
LTC_ASN1_SEQUENCE, 1uL, alg_id,
46-
LTC_ASN1_OCTET_STRING, key_len, private_key,
47-
LTC_ASN1_EOL, 0uL, NULL))
48-
!= CRYPT_OK) {
49-
/* If there are attributes added after the private_key it is tagged with version 1 and
50-
* we get an 'input too long' error but the rest is already decoded and can be
51-
* handled the same as for version 0
52-
*/
53-
if ((err == CRYPT_INPUT_TOO_LONG) && (version == 1)) {
54-
version = 0;
55-
} else {
56-
goto out;
57-
}
58-
}
68+
err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l);
69+
if (err != CRYPT_OK) return err;
5970

60-
if ((err = pk_get_oid(id, &oid)) != CRYPT_OK) {
61-
goto out;
62-
}
63-
if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) {
64-
goto out;
65-
}
66-
67-
if (version == 0) {
68-
key_len = sizeof(key->priv);
69-
if ((err = der_decode_octet_string(private_key, sizeof(private_key), key->priv, &key_len)) == CRYPT_OK) {
70-
fp(key->pub, key->priv);
71-
key->type = PK_PRIVATE;
72-
key->algo = id;
73-
}
74-
} else {
75-
err = CRYPT_PK_INVALID_TYPE;
76-
}
71+
if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
72+
goto LBL_DER_FREE;
7773
}
78-
out:
79-
if (l) der_free_sequence_flexi(l);
80-
#ifdef LTC_CLEAN_STACK
81-
zeromem(private_key, sizeof(private_key));
82-
#endif
74+
if (pka != id) {
75+
err = CRYPT_INVALID_PACKET;
76+
goto LBL_DER_FREE;
77+
}
78+
79+
err = ec25519_import_pkcs8_asn1(alg_id, priv_key, id, key);
8380

81+
LBL_DER_FREE:
82+
der_free_sequence_flexi(l);
8483
return err;
8584
}
8685

0 commit comments

Comments
 (0)