1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 
4 #include "tomcrypt_private.h"
5 
6 /**
7   @file ecc_encrypt_key.c
8   ECC Crypto, Tom St Denis
9 */
10 
11 #ifdef LTC_MECC
12 
13 /**
14   Encrypt a symmetric key with ECC
15   @param in         The symmetric key you want to encrypt
16   @param inlen      The length of the key to encrypt (octets)
17   @param out        [out] The destination for the ciphertext
18   @param outlen     [in/out] The max size and resulting size of the ciphertext
19   @param prng       An active PRNG state
20   @param wprng      The index of the PRNG you wish to use
21   @param hash       The index of the hash you want to use
22   @param key        The ECC key you want to encrypt to
23   @return CRYPT_OK if successful
24 */
ecc_encrypt_key(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,prng_state * prng,int wprng,int hash,const ecc_key * key)25 int ecc_encrypt_key(const unsigned char *in,   unsigned long inlen,
26                           unsigned char *out,  unsigned long *outlen,
27                           prng_state *prng, int wprng, int hash,
28                           const ecc_key *key)
29 {
30     unsigned char *pub_expt, *ecc_shared, *skey;
31     ecc_key        pubkey;
32     unsigned long  x, y, pubkeysize;
33     int            err;
34 
35     LTC_ARGCHK(in      != NULL);
36     LTC_ARGCHK(out     != NULL);
37     LTC_ARGCHK(outlen  != NULL);
38     LTC_ARGCHK(key     != NULL);
39 
40     if ((err = hash_is_valid(hash)) != CRYPT_OK) {
41        return err;
42     }
43 
44     if (inlen > hash_descriptor[hash].hashsize) {
45        return CRYPT_INVALID_HASH;
46     }
47 
48     /* make a random key and export the public copy */
49     if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { return err; }
50     if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; }
51 
52     pub_expt   = XMALLOC(ECC_BUF_SIZE);
53     ecc_shared = XMALLOC(ECC_BUF_SIZE);
54     skey       = XMALLOC(MAXBLOCKSIZE);
55     if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
56        if (pub_expt != NULL) {
57           XFREE(pub_expt);
58        }
59        if (ecc_shared != NULL) {
60           XFREE(ecc_shared);
61        }
62        if (skey != NULL) {
63           XFREE(skey);
64        }
65        ecc_free(&pubkey);
66        return CRYPT_MEM;
67     }
68 
69     pubkeysize = ECC_BUF_SIZE;
70     if (ltc_mp.sqrtmod_prime != NULL) {
71        /* PK_COMPRESSED requires sqrtmod_prime */
72        err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey);
73     }
74     else {
75        err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey);
76     }
77     if (err != CRYPT_OK) {
78        ecc_free(&pubkey);
79        goto LBL_ERR;
80     }
81 
82     /* make random key */
83     x        = ECC_BUF_SIZE;
84     if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
85        ecc_free(&pubkey);
86        goto LBL_ERR;
87     }
88     ecc_free(&pubkey);
89     y = MAXBLOCKSIZE;
90     if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) {
91        goto LBL_ERR;
92     }
93 
94     /* Encrypt key */
95     for (x = 0; x < inlen; x++) {
96       skey[x] ^= in[x];
97     }
98 
99     err = der_encode_sequence_multi(out, outlen,
100                                     LTC_ASN1_OBJECT_IDENTIFIER,  hash_descriptor[hash].OIDlen,   hash_descriptor[hash].OID,
101                                     LTC_ASN1_OCTET_STRING,       pubkeysize,                     pub_expt,
102                                     LTC_ASN1_OCTET_STRING,       inlen,                          skey,
103                                     LTC_ASN1_EOL,                0UL,                            NULL);
104 
105 LBL_ERR:
106 #ifdef LTC_CLEAN_STACK
107     /* clean up */
108     zeromem(pub_expt,   ECC_BUF_SIZE);
109     zeromem(ecc_shared, ECC_BUF_SIZE);
110     zeromem(skey,       MAXBLOCKSIZE);
111 #endif
112 
113     XFREE(skey);
114     XFREE(ecc_shared);
115     XFREE(pub_expt);
116 
117     return err;
118 }
119 
120 #endif
121