1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 * 3 * LibTomCrypt is a library that provides various cryptographic 4 * algorithms in a highly modular and flexible manner. 5 * 6 * The library is free for all purposes without any express 7 * guarantee it works. 8 * 9 * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com 10 */ 11 12 /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b 13 * 14 * All curves taken from NIST recommendation paper of July 1999 15 * Available at http://csrc.nist.gov/cryptval/dss.htm 16 */ 17 #include "tomcrypt.h" 18 19 /** 20 @file ecc_decrypt_key.c 21 ECC Crypto, Tom St Denis 22 */ 23 24 #ifdef MECC 25 26 /** 27 Decrypt an ECC encrypted key 28 @param in The ciphertext 29 @param inlen The length of the ciphertext (octets) 30 @param out [out] The plaintext 31 @param outlen [in/out] The max size and resulting size of the plaintext 32 @param key The corresponding private ECC key 33 @return CRYPT_OK if successful 34 */ 35 int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, 36 unsigned char *out, unsigned long *outlen, 37 ecc_key *key) 38 { 39 unsigned char *ecc_shared, *skey, *pub_expt; 40 unsigned long x, y, hashOID[32]; 41 int hash, err; 42 ecc_key pubkey; 43 ltc_asn1_list decode[3]; 44 45 LTC_ARGCHK(in != NULL); 46 LTC_ARGCHK(out != NULL); 47 LTC_ARGCHK(outlen != NULL); 48 LTC_ARGCHK(key != NULL); 49 50 /* right key type? */ 51 if (key->type != PK_PRIVATE) { 52 return CRYPT_PK_NOT_PRIVATE; 53 } 54 55 /* decode to find out hash */ 56 LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); 57 58 if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) { 59 return err; 60 } 61 62 hash = find_hash_oid(hashOID, decode[0].size); 63 if (hash_is_valid(hash) != CRYPT_OK) { 64 return CRYPT_INVALID_PACKET; 65 } 66 67 /* we now have the hash! */ 68 69 /* allocate memory */ 70 pub_expt = XMALLOC(ECC_BUF_SIZE); 71 ecc_shared = XMALLOC(ECC_BUF_SIZE); 72 skey = XMALLOC(MAXBLOCKSIZE); 73 if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { 74 if (pub_expt != NULL) { 75 XFREE(pub_expt); 76 } 77 if (ecc_shared != NULL) { 78 XFREE(ecc_shared); 79 } 80 if (skey != NULL) { 81 XFREE(skey); 82 } 83 return CRYPT_MEM; 84 } 85 LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE); 86 LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); 87 88 /* read the structure in now */ 89 if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { 90 goto LBL_ERR; 91 } 92 93 /* import ECC key from packet */ 94 if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) { 95 goto LBL_ERR; 96 } 97 98 /* make shared key */ 99 x = ECC_BUF_SIZE; 100 if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) { 101 ecc_free(&pubkey); 102 goto LBL_ERR; 103 } 104 ecc_free(&pubkey); 105 106 y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE); 107 if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) { 108 goto LBL_ERR; 109 } 110 111 /* ensure the hash of the shared secret is at least as big as the encrypt itself */ 112 if (decode[2].size > y) { 113 err = CRYPT_INVALID_PACKET; 114 goto LBL_ERR; 115 } 116 117 /* avoid buffer overflow */ 118 if (*outlen < decode[2].size) { 119 *outlen = decode[2].size; 120 err = CRYPT_BUFFER_OVERFLOW; 121 goto LBL_ERR; 122 } 123 124 /* Decrypt the key */ 125 for (x = 0; x < decode[2].size; x++) { 126 out[x] = skey[x] ^ ecc_shared[x]; 127 } 128 *outlen = x; 129 130 err = CRYPT_OK; 131 LBL_ERR: 132 #ifdef LTC_CLEAN_STACK 133 zeromem(pub_expt, ECC_BUF_SIZE); 134 zeromem(ecc_shared, ECC_BUF_SIZE); 135 zeromem(skey, MAXBLOCKSIZE); 136 #endif 137 138 XFREE(pub_expt); 139 XFREE(ecc_shared); 140 XFREE(skey); 141 142 return err; 143 } 144 145 #endif 146 147 /* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c,v $ */ 148 /* $Revision: 1.5 $ */ 149 /* $Date: 2006/06/16 21:53:41 $ */ 150 151