|
9 | 9 |
|
10 | 10 | #ifdef LTC_CURVE25519 |
11 | 11 |
|
| 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 | + |
12 | 47 | /** |
13 | 48 | 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 |
19 | 54 | @return CRYPT_OK if successful, on error all allocated memory is freed automatically |
20 | 55 | */ |
21 | 56 | 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) |
25 | 60 | { |
26 | | - int err; |
| 61 | + int err; |
27 | 62 | 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; |
39 | 65 |
|
40 | | - LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid) / sizeof(tmpoid[0])); |
| 66 | + LTC_ARGCHK(in != NULL); |
41 | 67 |
|
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; |
59 | 70 |
|
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; |
77 | 73 | } |
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); |
83 | 80 |
|
| 81 | +LBL_DER_FREE: |
| 82 | + der_free_sequence_flexi(l); |
84 | 83 | return err; |
85 | 84 | } |
86 | 85 |
|
|
0 commit comments