1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 #include "tomcrypt_private.h"
5
6 /**
7 @file ecc_decrypt_key.c
8 ECC Crypto, Tom St Denis
9 */
10
11 #ifdef LTC_MECC
12
13 /**
14 Decrypt an ECC encrypted key
15 @param in The ciphertext
16 @param inlen The length of the ciphertext (octets)
17 @param out [out] The plaintext
18 @param outlen [in/out] The max size and resulting size of the plaintext
19 @param key The corresponding private ECC key
20 @return CRYPT_OK if successful
21 */
ecc_decrypt_key(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,const ecc_key * key)22 int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
23 unsigned char *out, unsigned long *outlen,
24 const ecc_key *key)
25 {
26 unsigned char *ecc_shared, *skey, *pub_expt;
27 unsigned long x, y;
28 unsigned long hashOID[32] = { 0 };
29 int hash, err;
30 ecc_key pubkey;
31 ltc_asn1_list decode[3];
32
33 LTC_ARGCHK(in != NULL);
34 LTC_ARGCHK(out != NULL);
35 LTC_ARGCHK(outlen != NULL);
36 LTC_ARGCHK(key != NULL);
37
38 /* right key type? */
39 if (key->type != PK_PRIVATE) {
40 return CRYPT_PK_NOT_PRIVATE;
41 }
42
43 /* decode to find out hash */
44 LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
45 err = der_decode_sequence(in, inlen, decode, 1);
46 if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
47 return err;
48 }
49
50 hash = find_hash_oid(hashOID, decode[0].size);
51 if (hash_is_valid(hash) != CRYPT_OK) {
52 return CRYPT_INVALID_PACKET;
53 }
54
55 /* we now have the hash! */
56
57 /* allocate memory */
58 pub_expt = XMALLOC(ECC_BUF_SIZE);
59 ecc_shared = XMALLOC(ECC_BUF_SIZE);
60 skey = XMALLOC(MAXBLOCKSIZE);
61 if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
62 if (pub_expt != NULL) {
63 XFREE(pub_expt);
64 }
65 if (ecc_shared != NULL) {
66 XFREE(ecc_shared);
67 }
68 if (skey != NULL) {
69 XFREE(skey);
70 }
71 return CRYPT_MEM;
72 }
73 LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE);
74 LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);
75
76 /* read the structure in now */
77 if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
78 goto LBL_ERR;
79 }
80
81 /* import ECC key from packet */
82 if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
83 if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
84
85 /* make shared key */
86 x = ECC_BUF_SIZE;
87 if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) {
88 ecc_free(&pubkey);
89 goto LBL_ERR;
90 }
91 ecc_free(&pubkey);
92
93 y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE);
94 if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) {
95 goto LBL_ERR;
96 }
97
98 /* ensure the hash of the shared secret is at least as big as the encrypt itself */
99 if (decode[2].size > y) {
100 err = CRYPT_INVALID_PACKET;
101 goto LBL_ERR;
102 }
103
104 /* avoid buffer overflow */
105 if (*outlen < decode[2].size) {
106 *outlen = decode[2].size;
107 err = CRYPT_BUFFER_OVERFLOW;
108 goto LBL_ERR;
109 }
110
111 /* Decrypt the key */
112 for (x = 0; x < decode[2].size; x++) {
113 out[x] = skey[x] ^ ecc_shared[x];
114 }
115 *outlen = x;
116
117 err = CRYPT_OK;
118 LBL_ERR:
119 #ifdef LTC_CLEAN_STACK
120 zeromem(pub_expt, ECC_BUF_SIZE);
121 zeromem(ecc_shared, ECC_BUF_SIZE);
122 zeromem(skey, MAXBLOCKSIZE);
123 #endif
124
125 XFREE(pub_expt);
126 XFREE(ecc_shared);
127 XFREE(skey);
128
129 return err;
130 }
131
132 #endif
133
134