C4Err ECC_Import(ECC_ContextRef ctx, void *in, size_t inlen ) { C4Err err = kC4Err_NoErr; validateECCContext(ctx); bool isPrivate = false; size_t importKeySize = 0; bool isANSIx963 = false; err = ECC_Import_Info( in, inlen, &isPrivate, &isANSIx963, &importKeySize );CKERR; ValidateParam(!isANSIx963 ) if(importKeySize > 384) { err = ecc_bl_import(in, inlen, &ctx->key); CKERR; ctx->isBLCurve = true; } else { err = ecc_import(in, inlen, &ctx->key); CKERR; ctx->isBLCurve = false; } ctx->isInited = true; done: return (err); }
/** M.getsecret(my_privkey, peer_pubkey) * Keys are represented as Lua strings, the private one under a libtomcrypt * proprietary format, the public one under X9.63 format. * The public one normally comes from the distant computer with which we want * to establish a shared secret. */ static int lgetsecret( lua_State *L) { /* Retrieve private key */ ecc_key my_privkey; size_t my_privkey_len; const char *my_privkey_str = luaL_checklstring( L, 1, & my_privkey_len); if( CRYPT_OK != ecc_import( (unsigned char *) my_privkey_str, my_privkey_len, & my_privkey)) goto failure; /* Retrieve public key */ ecc_key peer_pubkey; size_t peer_pubkey_len; const char *peer_pubkey_str = luaL_checklstring( L, 2, & peer_pubkey_len); if( CRYPT_OK != ecc_ansi_x963_import( (unsigned char *) peer_pubkey_str, peer_pubkey_len,& peer_pubkey)) goto failure; /* Retrieve secret */ unsigned char buff [BUFF_SIZE]; unsigned long buff_len = -1; if( CRYPT_OK != ecc_shared_secret( & my_privkey, & peer_pubkey, buff, & buff_len)) goto failure; lua_pushlstring( L, (const char *) buff, buff_len); return 1; failure: lua_pushnil( L); lua_pushstring( L, "error"); return 2; }
/* { loadKey start } */ int loadKey(ecc_key* key, char* fileName){ FILE *file; file = fopen(fileName,"rb"); // r for read, b for binary unsigned char keyArray[2048]; unsigned long keyLength = 2048; fread((char*)&keyLength, 4,1,file); fread(keyArray, keyLength, 1, file); int err; if ((err = ecc_import(keyArray, keyLength, key)) != CRYPT_OK) { printf("Error import public key ,%i, %s\n",err, error_to_string(err)); exit(EXIT_FAILURE); } return 1; }
int ecc_tests (void) { unsigned char buf[4][4096]; unsigned long x, y, z, s; int stat, stat2; ecc_key usera, userb, pubKey, privKey; DO(ecc_test ()); DO(ecc_test ()); DO(ecc_test ()); DO(ecc_test ()); DO(ecc_test ()); for (s = 0; s < (sizeof(sizes)/sizeof(sizes[0])); s++) { /* make up two keys */ DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera)); DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &userb)); /* make the shared secret */ x = sizeof(buf[0]); DO(ecc_shared_secret (&usera, &userb, buf[0], &x)); y = sizeof(buf[1]); DO(ecc_shared_secret (&userb, &usera, buf[1], &y)); if (y != x) { fprintf(stderr, "ecc Shared keys are not same size."); return 1; } if (memcmp (buf[0], buf[1], x)) { fprintf(stderr, "ecc Shared keys not same contents."); return 1; } /* now export userb */ y = sizeof(buf[0]); DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb)); ecc_free (&userb); /* import and make the shared secret again */ DO(ecc_import (buf[1], y, &userb)); z = sizeof(buf[0]); DO(ecc_shared_secret (&usera, &userb, buf[2], &z)); if (z != x) { fprintf(stderr, "failed. Size don't match?"); return 1; } if (memcmp (buf[0], buf[2], x)) { fprintf(stderr, "Failed. Contents didn't match."); return 1; } /* export with ANSI X9.63 */ y = sizeof(buf[1]); DO(ecc_ansi_x963_export(&userb, buf[1], &y)); ecc_free (&userb); /* now import the ANSI key */ DO(ecc_ansi_x963_import(buf[1], y, &userb)); /* shared secret */ z = sizeof(buf[0]); DO(ecc_shared_secret (&usera, &userb, buf[2], &z)); if (z != x) { fprintf(stderr, "failed. Size don't match?"); return 1; } if (memcmp (buf[0], buf[2], x)) { fprintf(stderr, "Failed. Contents didn't match."); return 1; } ecc_free (&usera); ecc_free (&userb); /* test encrypt_key */ DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera)); /* export key */ x = sizeof(buf[0]); DO(ecc_export(buf[0], &x, PK_PUBLIC, &usera)); DO(ecc_import(buf[0], x, &pubKey)); x = sizeof(buf[0]); DO(ecc_export(buf[0], &x, PK_PRIVATE, &usera)); DO(ecc_import(buf[0], x, &privKey)); for (x = 0; x < 32; x++) { buf[0][x] = x; } y = sizeof (buf[1]); DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &yarrow_prng, find_prng ("yarrow"), find_hash ("sha256"), &pubKey)); zeromem (buf[0], sizeof (buf[0])); x = sizeof (buf[0]); DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &privKey)); if (x != 32) { fprintf(stderr, "Failed (length)"); return 1; } for (x = 0; x < 32; x++) { if (buf[0][x] != x) { fprintf(stderr, "Failed (contents)"); return 1; } } /* test sign_hash */ for (x = 0; x < 16; x++) { buf[0][x] = x; } x = sizeof (buf[1]); DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey)); DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &pubKey)); buf[0][0] ^= 1; DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &privKey)); if (!(stat == 1 && stat2 == 0)) { fprintf(stderr, "ecc_verify_hash failed %d, %d, ", stat, stat2); return 1; } ecc_free (&usera); ecc_free (&pubKey); ecc_free (&privKey); } #ifdef LTC_ECC_SHAMIR return ecc_test_shamir(); #else return 0; #endif }
/** Decrypt an ECC encrypted key @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @param outlen [in/out] The max size and resulting size of the plaintext @param key The corresponding private ECC key @return CRYPT_OK if successful */ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, ecc_key *key) { unsigned char *ecc_shared, *skey, *pub_expt; unsigned long x, y, hashOID[32]; int hash, err; ecc_key pubkey; ltc_asn1_list decode[3]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* right key type? */ if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* decode to find out hash */ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) { return err; } for (hash = 0; hash_descriptor[hash].name != NULL && (hash_descriptor[hash].OIDlen != decode[0].size || memcmp(hash_descriptor[hash].OID, hashOID, sizeof(unsigned long)*decode[0].size)); hash++); if (hash_descriptor[hash].name == NULL) { return CRYPT_INVALID_PACKET; } /* we now have the hash! */ /* allocate memory */ pub_expt = XMALLOC(ECC_BUF_SIZE); ecc_shared = XMALLOC(ECC_BUF_SIZE); skey = XMALLOC(MAXBLOCKSIZE); if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { if (pub_expt != NULL) { XFREE(pub_expt); } if (ecc_shared != NULL) { XFREE(ecc_shared); } if (skey != NULL) { XFREE(skey); } return CRYPT_MEM; } LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE); LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); /* read the structure in now */ if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { goto LBL_ERR; } /* import ECC key from packet */ if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } /* make shared key */ x = ECC_BUF_SIZE; if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } ecc_free(&pubkey); y = MAXBLOCKSIZE; if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) { goto LBL_ERR; } /* ensure the hash of the shared secret is at least as big as the encrypt itself */ if (decode[2].size > y) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* avoid buffer overflow */ if (*outlen < decode[2].size) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* Decrypt the key */ for (x = 0; x < decode[2].size; x++) { out[x] = skey[x] ^ ecc_shared[x]; } *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(pub_expt, ECC_BUF_SIZE); zeromem(ecc_shared, ECC_BUF_SIZE); zeromem(skey, MAXBLOCKSIZE); #endif XFREE(pub_expt); XFREE(ecc_shared); XFREE(skey); return err; }