예제 #1
0
static int
do_random(int argc, char **argv)
{
	unsigned char buffer[128];
	int r, count;

	if (argc != 1)
		goto usage;

	count = atoi(argv[0]);
	if (count < 0 || count > 128) {
		printf("Number must be in range 0..128\n");
		return -1;
	}

	r = sc_get_challenge(card, buffer, count);
	if (r < 0) {
		printf("Failed to get random bytes: %s\n", sc_strerror(r));
		return -1;
	}

	util_hex_dump_asc(stdout, buffer, count, 0);
	return 0;

usage:
	printf("Usage: random count\n");
	return -1;
}
예제 #2
0
static void do_random()
{
	unsigned char buffer[128];
	int r, count = 128;
	int n = 128;
	int n_bits = 1024;

        struct rand_pool_info *output;
	int fd = open(DEV_RANDOM, O_WRONLY);
	if (fd == -1) {
		syslog(LOG_ERR,"Failed to open %s", DEV_RANDOM);
	}
	while (1) {

		r = sc_get_challenge(card, buffer, count);
		if (r < 0) {
			syslog(LOG_ERR,"Failed to get random bytes: %s\n", sc_strerror(r));
		}
        	output = (struct rand_pool_info *)malloc(sizeof(struct rand_pool_info) + n);
		output -> entropy_count = n_bits;
		output -> buf_size      = n;
		memcpy(&(output -> buf[0]), buffer, n);
		if (ioctl(fd, RNDADDENTROPY, output) == -1) {
			syslog(LOG_ERR,"ioctl(RNDADDENTROPY) failed!");
		}
		free(output);
		sleep(1);
	}
	close(fd);
}
예제 #3
0
int main(int argc, char *argv[])
{
	struct timeval tv1, tv2;
	int i, c, cnt = 3, freq[256];
	u8 buf[8];

	i = sc_test_init(&argc, argv);
	if (i < 0)
		return 1;
	for (i = 0; i < 256; i++)
		freq[i] = 0;
	c = 0;
	while (cnt) {
		if ((c % 10) == 1) {
			printf(".");
			fflush(stdout);
		}
		if (c == 0)
			gettimeofday(&tv1, NULL);
		i = sc_get_challenge(card, buf, 8);
		if (i != 0) {
			fprintf(stderr, "sc_get_challenge() failed: %s\n", sc_strerror(i));
			sc_test_cleanup();
			return 1;
		}
		for (i = 0; i < 8; i++)
			freq[buf[i]]++;
		c++;
		if (c == 100) {
			unsigned long long foo, foo2;
			gettimeofday(&tv2, NULL);
			foo = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
			foo2 = tv1.tv_sec * 1000 + tv1.tv_usec / 1000;
			printf("\nTime to generate 64 bits of randomness: %lld ms\n",
			       (foo - foo2) / 100);
			printf("Frequencies:\n");
			for (i = 0; i < 256; i++) {
				if (i && (i & 0x07) == 0)
					printf("\n");
				printf("%02X: %3d ", i, freq[i]);
			}
			printf("\n");
			c = 0;
			cnt--;
		}
	}
	sc_test_cleanup();
	return 0;
}
예제 #4
0
static int gostchiper(sc_card_t *card, u8 keyid,
		const char *path_infile, const char *path_outfile,
		const char IV[IV_SIZE], int is_iv, int op_oper)
{
	int r;
	u8 iv[IV_SIZE];

	if (op_oper == OP_ENCRYPT) {
		if (!is_iv) {
			/*  generated random on token  */
			r = sc_get_challenge(card, iv, IV_SIZE);
	if (r) {
				fprintf(stderr, "Error: Generate IV"
						" (get challenge) failed: %s\n",
		        sc_strerror(r));
				return -1;
			}
		}
		else
			memcpy(iv, IV, IV_SIZE);
	}
	return do_crypt(card, keyid, path_infile, path_outfile, iv, op_oper);
}
예제 #5
0
static void create_dkek_share(sc_card_t *card, const char *outf, int iter, char *password, int password_shares_threshold, int password_shares_total)
{
	EVP_CIPHER_CTX ctx;
	FILE *out = NULL;
	u8 filebuff[64], key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH],outbuff[64];
	u8 dkek_share[32];
	char *pwd = NULL;
	int r = 0, outlen, pwdlen = 0;

	if (password == NULL) {

		if (password_shares_threshold == -1) {
			ask_for_password(&pwd, &pwdlen);
		} else { // create password using threshold scheme
			r = generate_pwd_shares(card, &pwd, &pwdlen, password_shares_threshold, password_shares_total);
		}

	} else {
		pwd = password;
		pwdlen = strlen(password);
	}

	if (r < 0) {
		printf("Creating DKEK share failed");
		return;
	}

	memcpy(filebuff, magic, sizeof(magic) - 1);

	r = sc_get_challenge(card, filebuff + 8, 8);
	if (r < 0) {
		printf("Error generating random number failed with ", sc_strerror(r));
		return;
	}

	printf("Enciphering DKEK share, please wait...\n");
	EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, pwdlen, iter, key, iv);

	if (password == NULL) {
		OPENSSL_cleanse(pwd, pwdlen);
		free(pwd);
	}

	r = sc_get_challenge(card, dkek_share, sizeof(dkek_share));
	if (r < 0) {
		printf("Error generating random number failed with ", sc_strerror(r));
		return;
	}

	EVP_CIPHER_CTX_init(&ctx);
	EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv);
	if (!EVP_EncryptUpdate(&ctx, filebuff + 16, &outlen, dkek_share, sizeof(dkek_share))) {
		printf("Error encrypting DKEK share\n");
		return;
	}

	if (!EVP_EncryptFinal_ex(&ctx, filebuff + 16 + outlen, &r)) {
		printf("Error encrypting DKEK share\n");
		return;
	}

	out = fopen(outf, "wb");

	if (out == NULL) {
		perror(outf);
		return;
	}

	if (fwrite(filebuff, 1, sizeof(filebuff), out) != sizeof(filebuff)) {
		perror(outf);
		return;
	}

	fclose(out);

	OPENSSL_cleanse(filebuff, sizeof(filebuff));
	EVP_CIPHER_CTX_cleanup(&ctx);

	printf("DKEK share created and saved to %s\n", outf);
}
예제 #6
0
static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total)
{
	int r, i;
	BIGNUM prime;
	BIGNUM secret;
	char buf[64];
	char hex[64];
	int l;

	secret_share_t *shares = NULL;
	secret_share_t *sp;

	u8 rngseed[16];

	printf(	"\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n");
	printf(	"This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total);

	printf(	"Please keep the generated and encrypted DKEK file in a safe location. We also recommend \n");
	printf(	"to keep a paper printout, in case the electronic version becomes unavailable. A printable version\n");
	printf(	"of the file can be generated using \"openssl base64 -in <filename>\".\n");

	printf("\n\nPress <enter> to continue");

	waitForEnterKeyPressed();

	*pwd = calloc(1, 8);
	*pwdlen = 8;

	r = sc_get_challenge(card, *pwd, 8);
	if (r < 0) {
		printf("Error generating random key failed with ", sc_strerror(r));
		OPENSSL_cleanse(pwd, *pwdlen);
		free(pwd);
		return r;
	}
	**pwd |= 0x80;

	/*
	 * Initialize prime and secret
	 */
	BN_init(&prime);
	BN_init(&secret);

	/*
	 * Encode the secret value
	 */
	BN_bin2bn(*pwd, *pwdlen, &secret);

	/*
	 * Generate seed and calculate a prime depending on the size of the secret
	 */
	r = sc_get_challenge(card, rngseed, 16);
	if (r < 0) {
		printf("Error generating random seed failed with ", sc_strerror(r));
		OPENSSL_cleanse(pwd, *pwdlen);
		free(pwd);
		return r;
	}

	generatePrime(&prime, &secret, password_shares_total, rngseed);

	// Allocate data buffer for the generated shares
	shares = malloc(password_shares_total * sizeof(secret_share_t));

	createShares(&secret, password_shares_threshold, password_shares_total, prime, shares);

	sp = shares;
	for (i = 0; i < password_shares_total; i++) {
		clearScreen();

		printf("Press <enter> to display key share %i of %i\n\n", i + 1, password_shares_total);
		waitForEnterKeyPressed();

		clearScreen();

		printf("Share %i of %i\n\n", i + 1, password_shares_total);

		l = BN_bn2bin(&prime, buf);
		sc_bin_to_hex(buf, l, hex, 64, ':');
		printf("\nPrime       : %s\n", hex);

		printf("Share ID    : %s\n", BN_bn2dec(&(sp->x)));
		l = BN_bn2bin(&(sp->y), buf);
		sc_bin_to_hex(buf, l, hex, 64, ':');
		printf("Share value : %s\n", hex);

		printf("\n\nPlease note ALL values above and press <enter> when finished");
		waitForEnterKeyPressed();

		sp++;
	}

	clearScreen();

	cleanUpShares(shares, password_shares_total);

	BN_clear_free(&prime);
	BN_clear_free(&secret);

	return 0;
}
예제 #7
0
int
iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *tries_left)
{
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
	struct sc_remote_data rdata;
	struct sc_apdu apdu;
	unsigned char sbuf[0x100];
	int rv, offs;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "iasecc_sm_external_authentication(): SKey ref %i", skey_ref);

	if (card->sm_ctx.sm_mode == SM_MODE_NONE)
		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Cannot do 'External Authentication' without SM activated ");

	strncpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section));
	sm_info->cmd = SM_CMD_EXTERNAL_AUTH;
	sm_info->serialnr = card->serialnr;
	sm_info->card_type = card->type;
	sm_info->sm_type = SM_TYPE_CWA14890;
	cwa_session->params.crt_at.usage = IASECC_UQB_AT_EXTERNAL_AUTHENTICATION;
	cwa_session->params.crt_at.algo = IASECC_ALGORITHM_ROLE_AUTH;
	cwa_session->params.crt_at.refs[0] = skey_ref;

	offs = 0;
	sbuf[offs++] = IASECC_CRT_TAG_ALGO;
	sbuf[offs++] = 0x01;
	sbuf[offs++] = IASECC_ALGORITHM_ROLE_AUTH;
	sbuf[offs++] = IASECC_CRT_TAG_REFERENCE;
	sbuf[offs++] = 0x01;
	sbuf[offs++] = skey_ref;

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81, 0xA4);
	apdu.data = sbuf;
	apdu.datalen = offs;
	apdu.lc = offs;

	rv = sc_transmit_apdu(card, &apdu);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): APDU transmit failed");
	rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error");

	rv = sc_get_challenge(card, cwa_session->card_challenge, sizeof(cwa_session->card_challenge));
	LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error");

	sc_remote_data_init(&rdata);

	if (!card->sm_ctx.module.ops.initialize)
		LOG_TEST_RET(ctx, SC_ERROR_SM_NOT_INITIALIZED, "No SM module");
	rv = card->sm_ctx.module.ops.initialize(ctx, sm_info, &rdata);
	LOG_TEST_RET(ctx, rv, "SM: INITIALIZE failed");

	sc_log(ctx, "sm_iasecc_external_authentication(): rdata length %i\n", rdata.length);

	rv = iasecc_sm_transmit_apdus (card, &rdata, NULL, 0);
	if (rv == SC_ERROR_PIN_CODE_INCORRECT && tries_left)
		*tries_left = (rdata.data + rdata.length - 1)->apdu.sw2 & 0x0F;
	LOG_TEST_RET(ctx, rv, "sm_iasecc_external_authentication(): execute failed");

	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of SM and External Authentication");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
예제 #8
0
int main(int argc, char *argv[])
{
	int i, c, r, cnt = 3, freq[39];
	struct timeval tv1, tv2;
	u8 buf[14];

	i = sc_test_init(&argc, argv);
	for (i = 0; i < 39; i++)
		freq[i] = 0;
	c = 0;
	while (cnt) {
		u8 nbuf[39];

		for (i = 0; i < 39; i++) {
			nbuf[i] = i + 1;
		}
		if (c == 0)
			gettimeofday(&tv1, NULL);
		sc_lock(card);
		r = sc_get_challenge(card, buf, 14);
		sc_unlock(card);
		if (r == 0) {
			int left = 39;

			printf("Lottery: ");
			for (i = 0; i < 7; i++) {
				unsigned short s = buf[2 * i] + (buf[2 * i + 1] << 8);
				int lot = s % (left + 1);
				int num = nbuf[lot];

				nbuf[lot] = nbuf[left - 1];
				left--;
				freq[num - 1]++;
				printf("%3d ", num);
			}
			printf("\n");
		} else {
			fprintf(stderr, "sc_get_challenge() failed: %s\n", sc_strerror(r));
			sc_test_cleanup();
			return 1;
		}
		c++;
		if (c == 50) {
			unsigned long long foo, foo2;

			gettimeofday(&tv2, NULL);
			foo = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
			foo2 = tv1.tv_sec * 1000 + tv1.tv_usec / 1000;
			printf("Time per one: %lld ms\n", (foo - foo2) / 50);
			printf("Frequencies:\n");
			for (i = 0; i < 39; i++) {
				printf("%3d: %-5d", i + 1, freq[i]);
				if (((i + 1) % 10) == 0)
					printf("\n");
			}
			printf("\n");
			c = 0;
			cnt--;
		}
	}
	sc_test_cleanup();
	return 0;
}
예제 #9
0
static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total)
{
	int r, i;
	BIGNUM *prime;
	BIGNUM *secret;
	unsigned char buf[64];
	char hex[64];
	int l;

	secret_share_t *shares = NULL;
	secret_share_t *sp;

	u8 rngseed[16];

	if ((password_shares_threshold == -1) || (password_shares_total == -1)) {
		fprintf(stderr, "Must specify both, --pwd-shares-total and --pwd-shares-threshold\n");
		return -1;
	}

	if (password_shares_total < 3) {
		fprintf(stderr, "--pwd-shares-total must be 3 or larger\n");
		return -1;
	}

	if (password_shares_threshold < 2) {
		fprintf(stderr, "--pwd-shares-threshold must 2 or larger\n");
		return -1;
	}

	if (password_shares_threshold > password_shares_total) {
		fprintf(stderr, "--pwd-shares-threshold must be smaller or equal to --pwd-shares-total\n");
		return -1;
	}

	printf(	"\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n");
	printf(	"This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total);

	printf(	"Please keep the generated and encrypted DKEK file in a safe location. We also recommend \n");
	printf(	"to keep a paper printout, in case the electronic version becomes unavailable. A printable version\n");
	printf(	"of the file can be generated using \"openssl base64 -in <filename>\".\n");

	printf("\n\nPress <enter> to continue");

	waitForEnterKeyPressed();

	*pwd = calloc(1, 8);
	*pwdlen = 8;

	r = sc_get_challenge(card, (unsigned char *)*pwd, 8);
	if (r < 0) {
		printf("Error generating random key failed with %s", sc_strerror(r));
		OPENSSL_cleanse(*pwd, *pwdlen);
		free(*pwd);
		return r;
	}
	**pwd &= 0x7F; // Make sure the bit size of the secret is not bigger than 63 bits

	/*
	 * Initialize prime and secret
	 */
	prime = BN_new();
	secret = BN_new();

	/*
	 * Encode the secret value
	 */
	BN_bin2bn((unsigned char *)*pwd, *pwdlen, secret);

	/*
	 * Generate seed and calculate a prime depending on the size of the secret
	 */
	r = sc_get_challenge(card, rngseed, SEED_LENGTH);
	if (r < 0) {
		printf("Error generating random seed failed with %s", sc_strerror(r));
		OPENSSL_cleanse(*pwd, *pwdlen);
		free(*pwd);
		return r;
	}

	r = generatePrime(prime, secret, 64, rngseed, SEED_LENGTH);
	if (r < 0) {
		printf("Error generating valid prime number. Please try again.");
		OPENSSL_cleanse(*pwd, *pwdlen);
		free(*pwd);
		return r;
	}

	// Allocate data buffer for the generated shares
	shares = malloc(password_shares_total * sizeof(secret_share_t));

	createShares(secret, password_shares_threshold, password_shares_total, prime, shares);

	sp = shares;
	for (i = 0; i < password_shares_total; i++) {
		clearScreen();

		printf("Press <enter> to display key share %i of %i\n\n", i + 1, password_shares_total);
		waitForEnterKeyPressed();

		clearScreen();

		printf("Share %i of %i\n\n", i + 1, password_shares_total);

		l = BN_bn2bin(prime, buf);
		sc_bin_to_hex(buf, l, hex, 64, ':');
		printf("\nPrime       : %s\n", hex);

		printf("Share ID    : %s\n", BN_bn2dec((sp->x)));
		l = BN_bn2bin((sp->y), buf);
		sc_bin_to_hex(buf, l, hex, 64, ':');
		printf("Share value : %s\n", hex);

		printf("\n\nPlease note ALL values above and press <enter> when finished");
		waitForEnterKeyPressed();

		sp++;
	}

	clearScreen();

	cleanUpShares(shares, password_shares_total);

	BN_clear_free(prime);
	BN_clear_free(secret);

	return 0;
}