1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
10 /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
12 * All curves taken from NIST recommendation paper of July 1999
13 * Available at http://csrc.nist.gov/cryptval/dss.htm
18 @file ecc_decrypt_key.c
19 ECC Crypto, Tom St Denis
25 Decrypt an ECC encrypted key
26 @param in The ciphertext
27 @param inlen The length of the ciphertext (octets)
28 @param out [out] The plaintext
29 @param outlen [in/out] The max size and resulting size of the plaintext
30 @param key The corresponding private ECC key
31 @return CRYPT_OK if successful
33 int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
34 unsigned char *out, unsigned long *outlen,
37 unsigned char *ecc_shared, *skey, *pub_expt;
39 unsigned long hashOID[32] = { 0 };
42 ltc_asn1_list decode[3];
44 LTC_ARGCHK(in != NULL);
45 LTC_ARGCHK(out != NULL);
46 LTC_ARGCHK(outlen != NULL);
47 LTC_ARGCHK(key != NULL);
50 if (key->type != PK_PRIVATE) {
51 return CRYPT_PK_NOT_PRIVATE;
54 /* decode to find out hash */
55 LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
56 err = der_decode_sequence(in, inlen, decode, 1);
57 if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
61 hash = find_hash_oid(hashOID, decode[0].size);
62 if (hash_is_valid(hash) != CRYPT_OK) {
63 return CRYPT_INVALID_PACKET;
66 /* we now have the hash! */
69 pub_expt = XMALLOC(ECC_BUF_SIZE);
70 ecc_shared = XMALLOC(ECC_BUF_SIZE);
71 skey = XMALLOC(MAXBLOCKSIZE);
72 if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
73 if (pub_expt != NULL) {
76 if (ecc_shared != NULL) {
84 LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE);
85 LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);
87 /* read the structure in now */
88 if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
92 /* import ECC key from packet */
93 if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) {
99 if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) {
105 y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE);
106 if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) {
110 /* ensure the hash of the shared secret is at least as big as the encrypt itself */
111 if (decode[2].size > y) {
112 err = CRYPT_INVALID_PACKET;
116 /* avoid buffer overflow */
117 if (*outlen < decode[2].size) {
118 *outlen = decode[2].size;
119 err = CRYPT_BUFFER_OVERFLOW;
123 /* Decrypt the key */
124 for (x = 0; x < decode[2].size; x++) {
125 out[x] = skey[x] ^ ecc_shared[x];
131 #ifdef LTC_CLEAN_STACK
132 zeromem(pub_expt, ECC_BUF_SIZE);
133 zeromem(ecc_shared, ECC_BUF_SIZE);
134 zeromem(skey, MAXBLOCKSIZE);
146 /* ref: $Format:%D$ */
147 /* git commit: $Format:%H$ */
148 /* commit time: $Format:%ai$ */