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