1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file ec25519_import_pkcs8.c
7 Generic import of a Curve/Ed25519 private key in PKCS#8 format, Steffen Jaeckel
8 */
9
10 #ifdef LTC_CURVE25519
11
12 /**
13 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
19 @return CRYPT_OK if successful, on error all allocated memory is freed automatically
20 */
ec25519_import_pkcs8(const unsigned char * in,unsigned long inlen,const void * pwd,unsigned long pwdlen,enum ltc_oid_id id,sk_to_pk fp,curve25519_key * key)21 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)
25 {
26 int err;
27 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) {
39
40 LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid) / sizeof(tmpoid[0]));
41
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 }
59
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 }
77 }
78 out:
79 if (l) der_free_sequence_flexi(l);
80 #ifdef LTC_CLEAN_STACK
81 zeromem(private_key, sizeof(private_key));
82 #endif
83
84 return err;
85 }
86
87 #endif
88