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