Пример #1
0
	virtual std::string serialize() const
	{
		/*
		Vector elements are "packed" together. Their keys are stripped. Only one
		key is left at the start of the list. Format of a "packed" list is:
		<key><field_size><val_size><val> + <val_size><val> + ...
		*/
		if(val.empty()){
			return "";
		}
		std::string packed;
		for(typename std::list<field_type>::const_iterator it_cur = val.begin(),
			it_end = val.end(); it_cur != it_end; ++it_cur)
		{
			std::string tmp = it_cur->serialize();
			std::string key_vint = vint_split(tmp);
			if(key_vint.empty()){
				continue;
			}
			packed += tmp;
		}
		if(packed.empty()){
			return "";
		}
		std::string ser;
		ser += key_create(field_type::field_ID, true);
		ser += uint_to_vint(packed.size());
		ser += packed;
		return ser;
	}
Пример #2
0
	virtual std::string serialize() const
	{
		if(!val){
			return "";
		}
		std::string ser;
		ser += key_create(field_ID, false);
		ser += uint_to_vint(encode_sint(*val));
		return ser;
	}
Пример #3
0
	virtual std::string serialize() const
	{
		if(val.empty()){
			return "";
		}
		std::string ser;
		ser += key_create(field_ID, true);
		ser += uint_to_vint(val.size());
		ser += val;
		return ser;
	}
Пример #4
0
	virtual std::string serialize() const
	{
		if(Field.empty()){
			return "";
		}
		std::string tmp;
		for(std::map<boost::uint64_t, field *>::const_iterator it_cur = Field.begin(),
			it_end = Field.end(); it_cur != it_end; ++it_cur)
		{
			tmp += it_cur->second->serialize();
		}
		for(std::map<boost::uint64_t, unknown>::const_iterator it_cur = Unknown_Field.begin(),
			it_end = Unknown_Field.end(); it_cur != it_end; ++it_cur)
		{
			tmp += it_cur->second.serialize();
		}
		std::string ser;
		ser += key_create(field_ID, true);
		ser += uint_to_vint(tmp.size());
		ser += tmp;
		return ser;
	}
Пример #5
0
int main(int argc, char *argv[])
{
	STACK_OF(X509_EXTENSION) * sk = NULL;
	X509_EXTENSION *hash_ext = NULL;
	X509_EXTENSION *nvctr_ext = NULL;
	X509_EXTENSION *trusted_key_ext = NULL;
	X509_EXTENSION *non_trusted_key_ext = NULL;
	FILE *file = NULL;
	int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid;
	int c, opt_idx = 0;
	unsigned int err_code;
	unsigned char md[SHA256_DIGEST_LENGTH];
	const EVP_MD *md_info;

	NOTICE("CoT Generation Tool: %s\n", build_msg);
	NOTICE("Target platform: %s\n", platform_msg);

	/* Set default options */
	key_alg = KEY_ALG_RSA;

	while (1) {
		/* getopt_long stores the option index here. */
		c = getopt_long(argc, argv, "ahknp", long_opt, &opt_idx);

		/* Detect the end of the options. */
		if (c == -1) {
			break;
		}

		switch (c) {
		case 'a':
			key_alg = get_key_alg(optarg);
			if (key_alg < 0) {
				ERROR("Invalid key algorithm '%s'\n", optarg);
				exit(1);
			}
			break;
		case 'h':
			print_help(argv[0]);
			break;
		case 'k':
			save_keys = 1;
			break;
		case 'n':
			new_keys = 1;
			break;
		case 'p':
			print_cert = 1;
			break;
		case BL2_ID:
			certs[BL2_CERT].bin = strdup(optarg);
			break;
		case BL30_ID:
			certs[BL30_CERT].bin = strdup(optarg);
			break;
		case BL31_ID:
			certs[BL31_CERT].bin = strdup(optarg);
			break;
		case BL32_ID:
			certs[BL32_CERT].bin = strdup(optarg);
			break;
		case BL33_ID:
			certs[BL33_CERT].bin = strdup(optarg);
			break;
		case BL2_CERT_ID:
			certs[BL2_CERT].fn = strdup(optarg);
			break;
		case TRUSTED_KEY_CERT_ID:
			certs[TRUSTED_KEY_CERT].fn = strdup(optarg);
			break;
		case BL30_KEY_CERT_ID:
			certs[BL30_KEY_CERT].fn = strdup(optarg);
			break;
		case BL30_CERT_ID:
			certs[BL30_CERT].fn = strdup(optarg);
			break;
		case BL31_KEY_CERT_ID:
			certs[BL31_KEY_CERT].fn = strdup(optarg);
			break;
		case BL31_CERT_ID:
			certs[BL31_CERT].fn = strdup(optarg);
			break;
		case BL32_KEY_CERT_ID:
			certs[BL32_KEY_CERT].fn = strdup(optarg);
			break;
		case BL32_CERT_ID:
			certs[BL32_CERT].fn = strdup(optarg);
			break;
		case BL33_KEY_CERT_ID:
			certs[BL33_KEY_CERT].fn = strdup(optarg);
			break;
		case BL33_CERT_ID:
			certs[BL33_CERT].fn = strdup(optarg);
			break;
		case ROT_KEY_ID:
			keys[ROT_KEY].fn = strdup(optarg);
			break;
		case TRUSTED_WORLD_KEY_ID:
			keys[TRUSTED_WORLD_KEY].fn = strdup(optarg);
			break;
		case NON_TRUSTED_WORLD_KEY_ID:
			keys[NON_TRUSTED_WORLD_KEY].fn = strdup(optarg);
			break;
		case BL30_KEY_ID:
			keys[BL30_KEY].fn = strdup(optarg);
			break;
		case BL31_KEY_ID:
			keys[BL31_KEY].fn = strdup(optarg);
			break;
		case BL32_KEY_ID:
			keys[BL32_KEY].fn = strdup(optarg);
			break;
		case BL33_KEY_ID:
			keys[BL33_KEY].fn = strdup(optarg);
			break;
		case '?':
		default:
			printf("%s\n", optarg);
			exit(1);
		}
	}

	/* Set the value of the NVCounters */
	tf_nvcounter = NVCOUNTER_VALUE;
	non_tf_nvcounter = NVCOUNTER_VALUE;

	/* Check command line arguments */
	check_cmd_params();

	/* Register the new types and OIDs for the extensions */
	if (ext_init(tbb_ext) != 0) {
		ERROR("Cannot initialize TBB extensions\n");
		exit(1);
	}

	/* Indicate SHA256 as image hash algorithm in the certificate
	 * extension */
	md_info = EVP_sha256();

	/* Get non-volatile counters NIDs */
	CHECK_OID(tz_nvctr_nid, TZ_FW_NVCOUNTER_OID);
	CHECK_OID(ntz_nvctr_nid, NTZ_FW_NVCOUNTER_OID);

	/* Load private keys from files (or generate new ones) */
	for (i = 0 ; i < NUM_KEYS ; i++) {
		/* First try to load the key from disk */
		if (key_load(&keys[i], &err_code)) {
			/* Key loaded successfully */
			continue;
		}

		/* Key not loaded. Check the error code */
		if (err_code == KEY_ERR_MALLOC) {
			/* Cannot allocate memory. Abort. */
			ERROR("Malloc error while loading '%s'\n", keys[i].fn);
			exit(1);
		} else if (err_code == KEY_ERR_LOAD) {
			/* File exists, but it does not contain a valid private
			 * key. Abort. */
			ERROR("Error loading '%s'\n", keys[i].fn);
			exit(1);
		}

		/* File does not exist, could not be opened or no filename was
		 * given */
		if (new_keys) {
			/* Try to create a new key */
			NOTICE("Creating new key for '%s'\n", keys[i].desc);
			if (!key_create(&keys[i], key_alg)) {
				ERROR("Error creating key '%s'\n", keys[i].desc);
				exit(1);
			}
		} else {
			if (err_code == KEY_ERR_OPEN) {
				ERROR("Error opening '%s'\n", keys[i].fn);
			} else {
				ERROR("Key '%s' not specified\n", keys[i].desc);
			}
			exit(1);
		}
	}

	/* *********************************************************************
	 * BL2 certificate (Trusted Boot Firmware certificate):
	 *     - Self-signed with OEM ROT private key
	 *     - Extensions:
	 *         - TrustedFirmwareNVCounter (TODO)
	 *         - BL2 hash
	 **********************************************************************/
	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());

	/* Add the NVCounter as a critical extension */
	CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
			tf_nvcounter));
	sk_X509_EXTENSION_push(sk, nvctr_ext);

	/* Add hash of BL2 as an extension */
	if (!sha_file(certs[BL2_CERT].bin, md)) {
		ERROR("Cannot calculate the hash of %s\n", certs[BL2_CERT].bin);
		exit(1);
	}
	CHECK_OID(hash_nid, BL2_HASH_OID);
	CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md,
			SHA256_DIGEST_LENGTH));
	sk_X509_EXTENSION_push(sk, hash_ext);

	/* Create certificate. Signed with ROT key */
	if (!cert_new(&certs[BL2_CERT], VAL_DAYS, 0, sk)) {
		ERROR("Cannot create %s\n", certs[BL2_CERT].cn);
		exit(1);
	}
	sk_X509_EXTENSION_free(sk);

	/* *********************************************************************
	 * Trusted Key certificate:
	 *     - Self-signed with OEM ROT private key
	 *     - Extensions:
	 *         - TrustedFirmwareNVCounter (TODO)
	 *         - TrustedWorldPK
	 *         - NonTrustedWorldPK
	 **********************************************************************/
	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
	CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
			tf_nvcounter));
	sk_X509_EXTENSION_push(sk, nvctr_ext);
	CHECK_OID(pk_nid, TZ_WORLD_PK_OID);
	CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
			keys[TRUSTED_WORLD_KEY].key));
	sk_X509_EXTENSION_push(sk, trusted_key_ext);
	CHECK_OID(pk_nid, NTZ_WORLD_PK_OID);
	CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
			keys[NON_TRUSTED_WORLD_KEY].key));
	sk_X509_EXTENSION_push(sk, non_trusted_key_ext);
	if (!cert_new(&certs[TRUSTED_KEY_CERT], VAL_DAYS, 0, sk)) {
		ERROR("Cannot create %s\n", certs[TRUSTED_KEY_CERT].cn);
		exit(1);
	}
	sk_X509_EXTENSION_free(sk);

	/* *********************************************************************
	 * BL30 Key certificate (Trusted SCP Firmware Key certificate):
	 *     - Self-signed with Trusted World key
	 *     - Extensions:
	 *         - TrustedFirmwareNVCounter (TODO)
	 *         - SCPFirmwareContentCertPK
	 **********************************************************************/
	if (bl30_present) {
		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
		CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
				tf_nvcounter));
		sk_X509_EXTENSION_push(sk, nvctr_ext);
		CHECK_OID(pk_nid, BL30_CONTENT_CERT_PK_OID);
		CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
				keys[BL30_KEY].key));
		sk_X509_EXTENSION_push(sk, trusted_key_ext);
		if (!cert_new(&certs[BL30_KEY_CERT], VAL_DAYS, 0, sk)) {
			ERROR("Cannot create %s\n", certs[BL30_KEY_CERT].cn);
			exit(1);
		}
		sk_X509_EXTENSION_free(sk);
	}

	/* *********************************************************************
	 * BL30 certificate (SCP Firmware Content certificate):
	 *     - Signed with Trusted World Key
	 *     - Extensions:
	 *         - TrustedFirmwareNVCounter (TODO)
	 *         - SCPFirmwareHash
	 **********************************************************************/
	if (bl30_present) {
		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
		CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
				tf_nvcounter));
		sk_X509_EXTENSION_push(sk, nvctr_ext);

		if (!sha_file(certs[BL30_CERT].bin, md)) {
			ERROR("Cannot calculate the hash of %s\n",
					certs[BL30_CERT].bin);
			exit(1);
		}
		CHECK_OID(hash_nid, BL30_HASH_OID);
		CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info,
				md, SHA256_DIGEST_LENGTH));
		sk_X509_EXTENSION_push(sk, hash_ext);

		if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) {
			ERROR("Cannot create %s\n", certs[BL30_CERT].cn);
			exit(1);
		}

		sk_X509_EXTENSION_free(sk);
	}

	/* *********************************************************************
	 * BL31 Key certificate (Trusted SoC Firmware Key certificate):
	 *     - Self-signed with Trusted World key
	 *     - Extensions:
	 *         - TrustedFirmwareNVCounter (TODO)
	 *         - SoCFirmwareContentCertPK
	 **********************************************************************/
	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
	CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
			tf_nvcounter));
	sk_X509_EXTENSION_push(sk, nvctr_ext);
	CHECK_OID(pk_nid, BL31_CONTENT_CERT_PK_OID);
	CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
			keys[BL31_KEY].key));
	sk_X509_EXTENSION_push(sk, trusted_key_ext);
	if (!cert_new(&certs[BL31_KEY_CERT], VAL_DAYS, 0, sk)) {
		ERROR("Cannot create %s\n", certs[BL31_KEY_CERT].cn);
		exit(1);
	}
	sk_X509_EXTENSION_free(sk);

	/* *********************************************************************
	 * BL31 certificate (SOC Firmware Content certificate):
	 *     - Signed with Trusted World Key
	 *     - Extensions:
	 *         - TrustedFirmwareNVCounter (TODO)
	 *         - BL31 hash
	 **********************************************************************/
	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
	CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
			tf_nvcounter));
	sk_X509_EXTENSION_push(sk, nvctr_ext);

	if (!sha_file(certs[BL31_CERT].bin, md)) {
		ERROR("Cannot calculate the hash of %s\n", certs[BL31_CERT].bin);
		exit(1);
	}
	CHECK_OID(hash_nid, BL31_HASH_OID);
	CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md,
			SHA256_DIGEST_LENGTH));
	sk_X509_EXTENSION_push(sk, hash_ext);

	if (!cert_new(&certs[BL31_CERT], VAL_DAYS, 0, sk)) {
		ERROR("Cannot create %s\n", certs[BL31_CERT].cn);
		exit(1);
	}

	sk_X509_EXTENSION_free(sk);

	/* *********************************************************************
	 * BL32 Key certificate (Trusted OS Firmware Key certificate):
	 *     - Self-signed with Trusted World key
	 *     - Extensions:
	 *         - TrustedFirmwareNVCounter (TODO)
	 *         - TrustedOSFirmwareContentCertPK
	 **********************************************************************/
	if (bl32_present) {
		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
		CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
				tf_nvcounter));
		sk_X509_EXTENSION_push(sk, nvctr_ext);
		CHECK_OID(pk_nid, BL32_CONTENT_CERT_PK_OID);
		CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
				keys[BL32_KEY].key));
		sk_X509_EXTENSION_push(sk, trusted_key_ext);
		if (!cert_new(&certs[BL32_KEY_CERT], VAL_DAYS, 0, sk)) {
			ERROR("Cannot create %s\n", certs[BL32_KEY_CERT].cn);
			exit(1);
		}
		sk_X509_EXTENSION_free(sk);
	}

	/* *********************************************************************
	 * BL32 certificate (TrustedOS Firmware Content certificate):
	 *     - Signed with Trusted World Key
	 *     - Extensions:
	 *         - TrustedFirmwareNVCounter (TODO)
	 *         - BL32 hash
	 **********************************************************************/
	if (bl32_present) {
		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
		CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
				tf_nvcounter));
		sk_X509_EXTENSION_push(sk, nvctr_ext);

		if (!sha_file(certs[BL32_CERT].bin, md)) {
			ERROR("Cannot calculate the hash of %s\n",
					certs[BL32_CERT].bin);
			exit(1);
		}
		CHECK_OID(hash_nid, BL32_HASH_OID);
		CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info,
				md, SHA256_DIGEST_LENGTH));
		sk_X509_EXTENSION_push(sk, hash_ext);

		if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) {
			ERROR("Cannot create %s\n", certs[BL32_CERT].cn);
			exit(1);
		}

		sk_X509_EXTENSION_free(sk);
	}

	/* *********************************************************************
	 * BL33 Key certificate (Non Trusted Firmware Key certificate):
	 *     - Self-signed with Non Trusted World key
	 *     - Extensions:
	 *         - NonTrustedFirmwareNVCounter (TODO)
	 *         - NonTrustedFirmwareContentCertPK
	 **********************************************************************/
	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
	CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT,
			non_tf_nvcounter));
	sk_X509_EXTENSION_push(sk, nvctr_ext);
	CHECK_OID(pk_nid, BL33_CONTENT_CERT_PK_OID);
	CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
			keys[BL33_KEY].key));
	sk_X509_EXTENSION_push(sk, non_trusted_key_ext);
	if (!cert_new(&certs[BL33_KEY_CERT], VAL_DAYS, 0, sk)) {
		ERROR("Cannot create %s\n", certs[BL33_KEY_CERT].cn);
		exit(1);
	}
	sk_X509_EXTENSION_free(sk);

	/* *********************************************************************
	 * BL33 certificate (Non-Trusted World Content certificate):
	 *     - Signed with Non-Trusted World Key
	 *     - Extensions:
	 *         - NonTrustedFirmwareNVCounter (TODO)
	 *         - BL33 hash
	 **********************************************************************/
	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
	CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT,
			non_tf_nvcounter));
	sk_X509_EXTENSION_push(sk, nvctr_ext);

	if (!sha_file(certs[BL33_CERT].bin, md)) {
		ERROR("Cannot calculate the hash of %s\n", certs[BL33_CERT].bin);
		exit(1);
	}
	CHECK_OID(hash_nid, BL33_HASH_OID);
	CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md,
			SHA256_DIGEST_LENGTH));
	sk_X509_EXTENSION_push(sk, hash_ext);

	if (!cert_new(&certs[BL33_CERT], VAL_DAYS, 0, sk)) {
		ERROR("Cannot create %s\n", certs[BL33_CERT].cn);
		exit(1);
	}
	sk_X509_EXTENSION_free(sk);

	/* Print the certificates */
	if (print_cert) {
		for (i = 0 ; i < NUM_CERTIFICATES ; i++) {
			if (!certs[i].x) {
				continue;
			}
			printf("\n\n=====================================\n\n");
			X509_print_fp(stdout, certs[i].x);
		}
	}

	/* Save created certificates to files */
	for (i = 0 ; i < NUM_CERTIFICATES ; i++) {
		if (certs[i].x && certs[i].fn) {
			file = fopen(certs[i].fn, "w");
			if (file != NULL) {
				i2d_X509_fp(file, certs[i].x);
				fclose(file);
			} else {
				ERROR("Cannot create file %s\n", certs[i].fn);
			}
		}
	}

	/* Save keys */
	if (save_keys) {
		for (i = 0 ; i < NUM_KEYS ; i++) {
			if (!key_store(&keys[i])) {
				ERROR("Cannot save %s\n", keys[i].desc);
			}
		}
	}

	X509_EXTENSION_free(hash_ext);
	X509_EXTENSION_free(nvctr_ext);
	X509_EXTENSION_free(trusted_key_ext);
	X509_EXTENSION_free(non_trusted_key_ext);

#ifndef OPENSSL_NO_ENGINE
	ENGINE_cleanup();
#endif
	CRYPTO_cleanup_all_ex_data();

	return 0;
}
Пример #6
0
	virtual bool parse(std::string buf)
	{
		/*
		To parse we take the key and prepend it to every list element before we
		pass the list elements to be parsed by the field_type. This makes it so
		fields don't have to understand the "packed" format.
		*/
		clear();
		std::string key_vint = vint_split(buf);
		if(key_vint.empty() || buf.empty()){
			return false;
		}
		boost::optional<std::pair<boost::uint64_t, bool> > key = key_parse(key_vint);
		if(!key || key->first != field_type::field_ID || key->second != true){
			return false;
		}
		if(field_type::length_delim == false && key->second == true){
			/*
			The vector is length delimited but the elements are not. Change the
			length delimited bit on the key before passing it to the field
			object to be parsed.
			*/
			key_vint = key_create(key->first, false);
		}
		std::string len_vint = vint_split(buf);
		if(len_vint.empty() || buf.empty()){
			return false;
		}
		boost::uint64_t len = vint_to_uint(len_vint);
		if(buf.size() != len){
			return false;
		}
		while(!buf.empty()){
			std::string packed_field;
			if(field_type::length_delim){
				std::string f_size_vint = vint_split(buf);
				if(f_size_vint.empty() || buf.empty()){
					return false;
				}
				boost::uint64_t f_size = vint_to_uint(f_size_vint);
				if(buf.size() < f_size){
					return false;
				}
				std::string reassembled = key_vint + f_size_vint + buf.substr(0, f_size);
				buf.erase(0, f_size);
				field_type Field;
				if(!Field.parse(reassembled)){
					return false;
				}
				val.push_back(Field);
			}else{
				std::string val_vint = vint_split(buf);
				if(val_vint.empty()){
					return false;
				}
				std::string reassembled = key_vint + val_vint;
				field_type Field;
				if(!Field.parse(reassembled)){
					return false;
				}
				val.push_back(Field);
			}
		}
		return true;
	}
Пример #7
0
Файл: main.c Проект: paswd/kp9
int main(void)
{
	Table *table = table_create();
	printf("-------------------------------------------\n");
	printf("Commands:\n");
	printf("a <key> <value> - push to table\n");
	printf("d <key> - delete from table\n");
	printf("s - sort table\n");
	printf("p - print table\n");
	printf("f <key> - find element by key\n");
	printf("c - clear table\n");
	printf("q - exit\n");
	printf("-------------------------------------------\n");
	size_t cnt = 0;
	char last_cmd = '\n';
	while (true) {
		if (!cnt || last_cmd == '\n')
			printf("> ");
		char cmd;
		bool is_finished = false;
		scanf("%c", &cmd);
		size_t pos;
		//LinearlistElement *this = NULL;
		Key *key = key_create();
		switch (cmd) {
			case 'q':
				is_finished = true;
				break;
			case 'a':
				table_push(table);
				break;
			case 'd':
				//scanf("%d", &pos);
				key_set_value_from_input(key);
				table_note_delete(table, key);
				break;
			case 's':
				table_sort(table);
				break;
			case 'p':
				table_print(table);
				break;
			case 'c':
				table_clear(table);
				break;
			case 'f':
				key_set_value_from_input(key);
				Note *found = table_search(table, key, &pos);
				if (found == NULL) {
					printf("There are no notes with this key in the table\n");
					break;
				}
				note_print(table, found);
				break;
			case '\n':
				break;
			default:
				printf("Invalid command `%c`\n", cmd);
				break;
		}
		last_cmd = cmd;
		key_destroy(&key);
		if (is_finished) break;

		cnt++;
		cnt %= 2;

		//printf("First: %lld\n", (long long) linearlist_get_value(linearlist_get_first(linearlist)));
		//printf("Last: %lld\n", (long long) linearlist_get_value(linearlist_get_last(linearlist)));
	}
	printf("Goodbye!\n");

	table_destroy(&table);

	return 0;
}