Ejemplo n.º 1
0
int main(void)
{
	int i;
	static char str[256];
	unsigned char *md5;
	unsigned int seed;

	readpass(str, 256);

	// the time used to type the pass is entropy
	srand(time(NULL));
	seed = rand();
	
	md5 = chash_double(str, seed);
        for (i = 0; i < 20; i++)
		printf("%02x", md5[i]);
	printf("\n");
	free(md5);
	return 0;
}
Ejemplo n.º 2
0
int
main(int argc, char *argv[])
{
    int     n, i, cnt = 1, pass = 0, hexmode = 0;
    char    passwd[SKEY_MAX_PW_LEN+1], key[SKEY_BINKEY_SIZE];
    char	buf[33], *seed, *slash;

    /* If we were called as otp-METHOD, set algorithm based on that */
    if ((slash = strrchr(argv[0], '/')))
        slash++;
    else
        slash = argv[0];
    if (strncmp(slash, "otp-", 4) == 0) {
        slash += 4;
        if (skey_set_algorithm(slash) == NULL)
            errx(1, "Unknown hash algorithm %s", slash);
    }

    for (i = 1; i < argc && argv[i][0] == '-' && strcmp(argv[i], "--");) {
        if (argv[i][2] == '\0') {
            /* Single character switch */
            switch (argv[i][1]) {
            case 'n':
                if (++i == argc)
                    usage(argv[0]);
                cnt = atoi(argv[i]);
                break;
            case 'p':
                if (++i == argc)
                    usage(argv[0]);
                if (strlcpy(passwd, argv[i], sizeof(passwd)) >=
                        sizeof(passwd))
                    errx(1, "Password too long");
                pass = 1;
                break;
            case 'x':
                hexmode = 1;
                break;
            default:
                usage(argv[0]);
            }
        } else {
            /* Multi character switches are hash types */
            if (skey_set_algorithm(&argv[i][1]) == NULL) {
                warnx("Unknown hash algorithm %s", &argv[i][1]);
                usage(argv[0]);
            }
        }
        i++;
    }

    if (argc > i + 2)
        usage(argv[0]);

    /* Could be in the form <number>/<seed> */
    if (argc <= i + 1) {
        /* look for / in it */
        if (argc <= i)
            usage(argv[0]);
        slash = strchr(argv[i], '/');
        if (slash == NULL)
            usage(argv[0]);
        *slash++ = '\0';
        seed = slash;

        if ((n = atoi(argv[i])) < 0) {
            warnx("%d not positive", n);
            usage(argv[0]);
        } else if (n > SKEY_MAX_SEQ) {
            warnx("%d is larger than max (%d)", n, SKEY_MAX_SEQ);
            usage(argv[0]);
        }
    } else {
        if ((n = atoi(argv[i])) < 0) {
            warnx("%d not positive", n);
            usage(argv[0]);
        } else if (n > SKEY_MAX_SEQ) {
            warnx("%d is larger than max (%d)", n, SKEY_MAX_SEQ);
            usage(argv[0]);
        }
        seed = argv[++i];
    }

    /* Get user's secret passphrase */
    if (!pass) {
        fputs("Reminder - Do not use this program while"
              " logged in via telnet.\n", stderr);
        (void)fputs("Enter secret passphrase: ", stderr);
        readpass(passwd, sizeof(passwd));
        if (passwd[0] == '\0')
            exit(1);
    }

    /* Crunch seed and passphrase into starting key */
    if (keycrunch(key, seed, passwd) != 0)
        errx(1, "key crunch failed");

    if (cnt == 1) {
        while (n-- != 0)
            f(key);
        (void)puts(hexmode ? put8(buf, key) : btoe(buf, key));
    } else {
        for (i = 0; i <= n - cnt; i++)
            f(key);
        for (; i <= n; i++) {
            if (hexmode)
                (void)printf("%d: %s\n", i, put8(buf, key));
            else
                (void)printf("%d: %-29s\n", i, btoe(buf, key));
            f(key);
        }
    }
    exit(0);
}
Ejemplo n.º 3
0
int
main(int argc, char *argv[])
{
	FILE * infile;
	FILE * outfile;
	int dec = 0;
	size_t maxmem = 0;
	double maxmemfrac = 0.5;
	double maxtime = 300.0;
	const char * ch;
	char * passwd;
	int rc;
	int verbose = 0;

	WARNP_INIT;

	/* We should have "enc" or "dec" first. */
	if (argc < 2)
		usage();
	if (strcmp(argv[1], "enc") == 0) {
		maxmem = 0;
		maxmemfrac = 0.125;
		maxtime = 5.0;
	} else if (strcmp(argv[1], "dec") == 0) {
		dec = 1;
	} else
		usage();
	argc--;
	argv++;

	/* Parse arguments. */
	while ((ch = GETOPT(argc, argv)) != NULL) {
		GETOPT_SWITCH(ch) {
		GETOPT_OPTARG("-M"):
			maxmem = strtoumax(optarg, NULL, 0);
			break;
		GETOPT_OPTARG("-m"):
			maxmemfrac = strtod(optarg, NULL);
			break;
		GETOPT_OPTARG("-t"):
			maxtime = strtod(optarg, NULL);
			break;
		GETOPT_OPT("-v"):
			verbose = 1;
			break;
		GETOPT_MISSING_ARG:
			warn0("Missing argument to %s\n", ch);
			/* FALLTHROUGH */
		GETOPT_DEFAULT:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	/* We must have one or two parameters left. */
	if ((argc < 1) || (argc > 2))
		usage();

	/* If the input isn't stdin, open the file. */
	if (strcmp(argv[0], "-")) {
		if ((infile = fopen(argv[0], "rb")) == NULL) {
			warnp("Cannot open input file: %s", argv[0]);
			exit(1);
		}
	} else {
		infile = stdin;
	}

	/* If we have an output file, open it. */
	if (argc > 1) {
		if ((outfile = fopen(argv[1], "wb")) == NULL) {
			warnp("Cannot open output file: %s", argv[1]);
			exit(1);
		}
	} else {
		outfile = stdout;
	}

	/* Prompt for a password. */
	if (readpass(&passwd, "Please enter passphrase",
	    dec ? NULL : "Please confirm passphrase", 1))
		exit(1);

	/* Encrypt or decrypt. */
	if (dec)
		rc = scryptdec_file(infile, outfile, (uint8_t *)passwd,
		    strlen(passwd), maxmem, maxmemfrac, maxtime, verbose);
	else
		rc = scryptenc_file(infile, outfile, (uint8_t *)passwd,
		    strlen(passwd), maxmem, maxmemfrac, maxtime, verbose);

	/* Zero and free the password. */
	insecure_memzero(passwd, strlen(passwd));
	free(passwd);

	/* Close any files we opened. */
	if (infile != stdin)
		fclose(infile);
	if (outfile != stdout)
		fclose(outfile);

	/* If we failed, print the right error message and exit. */
	if (rc != 0) {
		switch (rc) {
		case 1:
			warnp("Error determining amount of available memory");
			break;
		case 2:
			warnp("Error reading clocks");
			break;
		case 3:
			warnp("Error computing derived key");
			break;
		case 4:
			warnp("Error reading salt");
			break;
		case 5:
			warnp("OpenSSL error");
			break;
		case 6:
			warnp("Error allocating memory");
			break;
		case 7:
			warn0("Input is not valid scrypt-encrypted block");
			break;
		case 8:
			warn0("Unrecognized scrypt format version");
			break;
		case 9:
			warn0("Decrypting file would require too much memory");
			break;
		case 10:
			warn0("Decrypting file would take too much CPU time");
			break;
		case 11:
			warn0("Passphrase is incorrect");
			break;
		case 12:
			warnp("Error writing file: %s",
			    (argc > 1) ? argv[1] : "standard output");
			break;
		case 13:
			warnp("Error reading file: %s", argv[0]);
			break;
		}
		exit(1);
	}

	return (0);
}
Ejemplo n.º 4
0
int
main(int argc, char **argv)
{
	struct register_internal C;
	const char * keyfilename;
	FILE * keyfile;
	NETPACKET_CONNECTION * NPC;
	int passphrased;
	uint64_t maxmem;
	double maxtime;
	char * passphrase;

	WARNP_INIT;

	/* We have no username, machine name, or key filename yet. */
	C.user = C.name = NULL;
	keyfilename = NULL;

	/*
	 * So far we're not using a passphrase, have unlimited RAM, and allow
	 * up to 1 second of CPU time.
	 */
	passphrased = 0;
	maxmem = 0;
	maxtime = 1.0;

	/* Parse arguments. */
	while (--argc > 0) {
		argv++;

		if (strcmp(argv[0], "--user") == 0) {
			if ((C.user != NULL) || (argc < 2))
				usage();
			C.user = argv[1];
			argv++; argc--;
		} else if (strcmp(argv[0], "--machine") == 0) {
			if ((C.name != NULL) || (argc < 2))
				usage();
			C.name = argv[1];
			argv++; argc--;
		} else if (strcmp(argv[0], "--keyfile") == 0) {
			if ((keyfilename != NULL) || (argc < 2))
				usage();
			keyfilename = argv[1];
			argv++; argc--;
		} else if (strcmp(argv[0], "--passphrase-mem") == 0) {
			if ((maxmem != 0) || (argc < 2))
				usage();
			if (humansize_parse(argv[1], &maxmem)) {
				warnp("Cannot parse --passphrase-mem"
				    " argument: %s", argv[1]);
				exit(1);
			}
			argv++; argc--;
		} else if (strcmp(argv[0], "--passphrase-time") == 0) {
			if ((maxtime != 1.0) || (argc < 2))
				usage();
			maxtime = strtod(argv[1], NULL);
			if ((maxtime < 0.05) || (maxtime > 86400)) {
				warn0("Invalid --passphrase-time argument: %s",
				    argv[1]);
				exit(1);
			}
			argv++; argc--;
		} else if (strcmp(argv[0], "--passphrased") == 0) {
			passphrased = 1;
		} else {
			usage();
		}
	}

	/* We must have a user name, machine name, and key file specified. */
	if ((C.user == NULL) || (C.name == NULL) || (keyfilename == NULL))
		usage();

	/*
	 * It doesn't make sense to specify --passphrase-mem or
	 * --passphrase-time if we're not using a passphrase.
	 */
	if (((maxmem != 0) || (maxtime != 1.0)) && (passphrased == 0))
		usage();

	/* Sanity-check the user name. */
	if (strlen(C.user) > 255) {
		fprintf(stderr, "User name too long: %s\n", C.user);
		exit(1);
	}
	if (strlen(C.user) == 0) {
		fprintf(stderr, "User name must be non-empty\n");
		exit(1);
	}

	/* Sanity-check the machine name. */
	if (strlen(C.name) > 255) {
		fprintf(stderr, "Machine name too long: %s\n", C.name);
		exit(1);
	}
	if (strlen(C.name) == 0) {
		fprintf(stderr, "Machine name must be non-empty\n");
		exit(1);
	}

	/* Get a password. */
	if (readpass(&C.passwd, "Enter tarsnap account password", NULL, 0)) {
		warnp("Error reading password");
		exit(1);
	}

	/*
	 * Create key file -- we do this now rather than later so that we
	 * avoid registering with the server if we won't be able to create
	 * the key file later.
	 */
	if ((keyfile = keyfile_write_open(keyfilename)) == NULL) {
		warnp("Cannot create %s", keyfilename);
		exit(1);
	}

	/* Initialize key cache. */
	if (crypto_keys_init()) {
		warnp("Key cache initialization failed");
		goto err1;
	}

	/* Generate keys. */
	if (crypto_keys_generate(CRYPTO_KEYMASK_USER)) {
		warnp("Error generating keys");
		goto err1;
	}

	/*
	 * We're not done, haven't answered a challenge, and don't have a
	 * machine number.
	 */
	C.done = 0;
	C.donechallenge = 0;
	C.machinenum = (uint64_t)(-1);

	/* Open netpacket connection. */
	if ((NPC = netpacket_open(USERAGENT)) == NULL)
		goto err2;

	/* Ask the netpacket layer to send a request and get a response. */
	if (netpacket_op(NPC, callback_register_send, &C))
		goto err2;

	/* Run event loop until an error occurs or we're done. */
	if (network_spin(&C.done))
		goto err2;

	/* Close netpacket connection. */
	if (netpacket_close(NPC))
		goto err2;

	/*
	 * If we didn't respond to a challenge, the server's response must
	 * have been a "no such user" error.
	 */
	if ((C.donechallenge == 0) && (C.status != 1)) {
		netproto_printerr(NETPROTO_STATUS_PROTERR);
		goto err1;
	}

	/* The machine number should be -1 iff the status is nonzero. */
	if (((C.machinenum == (uint64_t)(-1)) && (C.status == 0)) ||
	    ((C.machinenum != (uint64_t)(-1)) && (C.status != 0))) {
		netproto_printerr(NETPROTO_STATUS_PROTERR);
		goto err1;
	}

	/* Parse status returned by server. */
	switch (C.status) {
	case 0:
		/* Success! */
		break;
	case 1:
		warn0("No such user: %s", C.user);
		break;
	case 2:
		warn0("Incorrect password");
		break;
	case 3:
		warn0("Cannot register with server: "
		    "Account balance for user %s is not positive", C.user);
		break;
	default:
		netproto_printerr(NETPROTO_STATUS_PROTERR);
		goto err2;
	}

	/* Shut down the network event loop. */
	network_fini();

	/* Exit with a code of 1 if we couldn't register. */
	if (C.machinenum == (uint64_t)(-1))
		goto err1;

	/* If the user wants to passphrase the keyfile, get the passphrase. */
	if (passphrased != 0) {
		if (readpass(&passphrase,
		    "Please enter passphrase for keyfile encryption",
		    "Please confirm passphrase for keyfile encryption", 1)) {
			warnp("Error reading password");
			goto err1;
		}
	} else {
		passphrase = NULL;
	}

	/* Write keys to file. */
	if (keyfile_write_file(keyfile, C.machinenum,
	    CRYPTO_KEYMASK_USER, passphrase, maxmem, maxtime))
		goto err1;

	/* Close the key file. */
	if (fclose(keyfile)) {
		warnp("Error closing key file");
		goto err1;
	}

	/* Success! */
	return (0);

err2:
	warnp("Error registering with server");
err1:
	unlink(keyfilename);
	exit(1);
}
Ejemplo n.º 5
0
static char *
prompt_password(const char *prompt, int with_echo)
{
	static char nostring[1] = "";
	static char *return_value;
	volatile int tty_opened;
	static FILE *ifp, *ofp;
	volatile int is_tty;
#ifdef HAVE_SIGACTION
	struct sigaction old_sigact;
#else
	RETSIGTYPE (*old_signal)();
#endif
	TERMIO old_modes;
	int max_asterisks = getdef_num("GETPASS_ASTERISKS", -1);

	/*
	 * set a flag so the SIGINT signal can be re-sent if it
	 * is caught
	 */

	sig_caught = 0;
	return_value = NULL;
	tty_opened = 0;

	/*
	 * if /dev/tty can't be opened, getpass() needs to read
	 * from stdin and write to stderr instead.
	 */

	if (!(ifp = fopen("/dev/tty", "r+"))) {
		ifp = stdin;
		ofp = stderr;
	} else {
		ofp = ifp;
		tty_opened = 1;
	}
	setbuf(ifp, (char *) 0);

	/*
	 * the current tty modes must be saved so they can be
	 * restored later on.  echo will be turned off, except
	 * for the newline character
	 */

	is_tty = 1;
	if (GTTY(fileno(ifp), &old_modes)) {
		is_tty = 0;
#if 0  /* to make getpass work with redirected stdin */
		return_value = NULL;
		goto out2;
#endif
	}

#ifdef USE_SETJMP
	/*
	 * If we get a SIGINT, sig_catch() will jump here -
	 * no need to press Enter after Ctrl-C.
	 */
	if (sigsetjmp(intr, 1))
		goto out;
#endif

#ifdef HAVE_SIGACTION
	sigact.sa_handler = sig_catch;
	sigemptyset(&sigact.sa_mask);
	sigact.sa_flags = 0;
	sigaction(SIGINT, &sigact, &old_sigact);
#else
	old_signal = signal(SIGINT, sig_catch);
#endif

	if (is_tty) {
		TERMIO new_modes = old_modes;

		if (max_asterisks < 0)
			new_modes.c_lflag |= ICANON;
		else
			new_modes.c_lflag &= ~(ICANON);

		if (with_echo)
			new_modes.c_lflag |= (ECHO | ECHOE | ECHOK);
		else
			new_modes.c_lflag &= ~(ECHO | ECHOE | ECHOK);

		new_modes.c_lflag |= ECHONL;

		if (STTY(fileno(ifp), &new_modes))
			goto out;
	}

	/*
	 * the prompt is output, and the response read without
	 * echoing.  the trailing newline must be removed.  if
	 * the fgets() returns an error, a NULL pointer is
	 * returned.
	 */

	if ((fputs(prompt, ofp) != EOF) && (fflush(ofp) != EOF))
		return_value = readpass(ifp, ofp, with_echo, max_asterisks);
out:
	/*
	 * the old SIGINT handler is restored after the tty
	 * modes.  then /dev/tty is closed if it was opened in
	 * the beginning.  finally, if a signal was caught it
	 * is sent to this process for normal processing.
	 */

	if (is_tty) {
		if (STTY(fileno(ifp), &old_modes))
			return_value = NULL;
	}

#ifdef HAVE_SIGACTION
	(void) sigaction (SIGINT, &old_sigact, NULL);
#else
	(void) signal (SIGINT, old_signal);
#endif
#if 0
out2:
#endif
	if (tty_opened)
		(void) fclose(ifp);

	if (sig_caught) {
		kill(getpid(), SIGINT);
		return_value = NULL;
	}
	if (!return_value) {
		nostring[0] = '\0';
		return_value = nostring;
	}
	return return_value;
}
Ejemplo n.º 6
0
int
main(int argc, char *argv[])
{
	FILE * infile;
	FILE * outfile;
	int dec = 0;
	size_t maxmem = 0;
	double maxmemfrac = 0.5;
	double maxtime = 300.0;
	int ch;
	char * passwd;
	int rc;

	WARNP_INIT;

	/* We should have "enc" or "dec" first. */
	if (argc < 2)
		usage();
	if (strcmp(argv[1], "enc") == 0) {
		maxmem = 0;
		maxmemfrac = 0.125;
		maxtime = 5.0;
	} else if (strcmp(argv[1], "dec") == 0) {
		dec = 1;
	} else
		usage();
	argc--;
	argv++;

	/* Parse arguments. */
	while ((ch = getopt(argc, argv, "hm:M:t:")) != -1) {
		switch (ch) {
		case 'M':
			maxmem = strtoumax(optarg, NULL, 0);
			break;
		case 'm':
			maxmemfrac = strtod(optarg, NULL);
			break;
		case 't':
			maxtime = strtod(optarg, NULL);
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	/* We must have one or two parameters left. */
	if ((argc < 1) || (argc > 2))
		usage();

	/* If the input isn't stdin, open the file. */
	if (strcmp(argv[0], "-")) {
		if ((infile = fopen(argv[0], "r")) == NULL) {
			warnp("Cannot open input file: %s", argv[0]);
			exit(1);
		}
	} else {
		infile = stdin;
	}

	/* If we have an output file, open it. */
	if (argc > 1) {
		if ((outfile = fopen(argv[1], "w")) == NULL) {
			warnp("Cannot open output file: %s", argv[1]);
			exit(1);
		}
	} else {
		outfile = stdout;
	}

	/* Prompt for a password. */
	if (readpass(&passwd, "Please enter passphrase",
	    dec ? NULL : "Please confirm passphrase", 1))
		exit(1);

	/* Encrypt or decrypt. */
	if (dec)
		rc = scryptdec_file(infile, outfile, (uint8_t *)passwd,
		    strlen(passwd), maxmem, maxmemfrac, maxtime);
	else
		rc = scryptenc_file(infile, outfile, (uint8_t *)passwd,
		    strlen(passwd), maxmem, maxmemfrac, maxtime);

	/* Zero and free the password. */
	memset(passwd, 0, strlen(passwd));
	free(passwd);

	/* If we failed, print the right error message and exit. */
	if (rc != 0) {
		switch (rc) {
		case 1:
			warnp("Error determining amount of available memory");
			break;
		case 2:
			warnp("Error reading clocks");
			break;
		case 3:
			warnp("Error computing derived key");
			break;
		case 4:
			warnp("Error reading salt");
			break;
		case 5:
			warnp("OpenSSL error");
			break;
		case 6:
			warnp("Error allocating memory");
			break;
		case 7:
			warn0("Input is not valid scrypt-encrypted block");
			break;
		case 8:
			warn0("Unrecognized scrypt format version");
			break;
		case 9:
			warn0("Decrypting file would require too much memory");
			break;
		case 10:
			warn0("Decrypting file would take too much CPU time");
			break;
		case 11:
			warn0("Passphrase is incorrect");
			break;
		case 12:
			warnp("Error writing file: %s",
			    (argc > 1) ? argv[1] : "standard output");
			break;
		case 13:
			warnp("Error reading file: %s", argv[0]);
			break;
		}
		exit(1);
	}

	return (0);
}
Ejemplo n.º 7
0
int
main(int argc, char **argv)
{
	const char * newkeyfile = NULL;
	int keyswanted = 0;
	char * tok, * brkb = NULL, * eptr;
	long keynum;
	uint64_t machinenum = (uint64_t)(-1);
	uint64_t kfmachinenum;
	const char * missingkey;
	int passphrased = 0;
	uint64_t maxmem = 0;
	double maxtime = 1.0;
	char * passphrase;
	const char * print_key_id_file = NULL;
	const char * print_key_permissions_file = NULL;
	const char * ch;
	char * optarg_copy;	/* for strtok_r. */

	WARNP_INIT;

	/* Initialize key cache. */
	if (crypto_keys_init()) {
		warnp("Key cache initialization failed");
		exit(1);
	}

	/* Parse arguments. */
	while ((ch = GETOPT(argc, argv)) != NULL) {
		GETOPT_SWITCH(ch) {
		GETOPT_OPTARG("--outkeyfile"):
			if (newkeyfile != NULL)
				usage();
			newkeyfile = optarg;
			break;
		GETOPT_OPT("-r"):
			keyswanted |= CRYPTO_KEYMASK_READ;
			break;
		GETOPT_OPT("-w"):
			keyswanted |= CRYPTO_KEYMASK_WRITE;
			break;
		GETOPT_OPT("-d"):
			/*
			 * Deleting data requires both delete authorization
			 * and being able to read archives -- we need to be
			 * able to figure out which bits are part of the
			 * archive.
			 */
			keyswanted |= CRYPTO_KEYMASK_READ;
			keyswanted |= CRYPTO_KEYMASK_AUTH_DELETE;
			break;
		GETOPT_OPT("--nuke"):
			keyswanted |= CRYPTO_KEYMASK_AUTH_DELETE;
			break;
		GETOPT_OPTARG("--keylist"):
			/*
			 * This is a deliberately undocumented option used
			 * mostly for testing purposes; it allows a list of
			 * keys to be specified according to their numbers in
			 * crypto/crypto.h instead of using the predefined
			 * sets of "read", "write" and "delete" keys.
			 */
			if ((optarg_copy = strdup(optarg)) == NULL) {
				warn0("Out of memory");
				exit(0);
			}
			for (tok = strtok_r(optarg_copy, ",", &brkb);
			     tok;
			     tok = strtok_r(NULL, ",", &brkb)) {
				keynum = strtol(tok, &eptr, 0);
				if ((eptr == tok) ||
				    (keynum < 0) || (keynum > 31)) {
					warn0("Not a valid key number: %s",
					    tok);
					free(optarg_copy);
					exit(1);
				}
				keyswanted |= (uint32_t)(1) << keynum;
			}
			free(optarg_copy);
			break;
		GETOPT_OPTARG("--passphrase-mem"):
			if (maxmem != 0)
				usage();
			if (humansize_parse(optarg, &maxmem)) {
				warnp("Cannot parse --passphrase-mem"
				    " argument: %s", optarg);
				exit(1);
			}
			break;
		GETOPT_OPTARG("--passphrase-time"):
			if (maxtime != 1.0)
				usage();
			maxtime = strtod(optarg, NULL);
			if ((maxtime < 0.05) || (maxtime > 86400)) {
				warn0("Invalid --passphrase-time argument: %s",
				    optarg);
				exit(1);
			}
			break;
		GETOPT_OPT("--passphrased"):
			if (passphrased != 0)
				usage();
			passphrased = 1;
			break;
		GETOPT_OPTARG("--print-key-id"):
			if (print_key_id_file != NULL)
				usage();
			print_key_id_file = optarg;
			break;
		GETOPT_OPTARG("--print-key-permissions"):
			if (print_key_permissions_file != NULL)
				usage();
			print_key_permissions_file = optarg;
			break;
		GETOPT_MISSING_ARG:
			warn0("Missing argument to %s\n", ch);
			/* FALLTHROUGH */
		GETOPT_DEFAULT:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	/* We can't print ID and permissions at the same time. */
	if ((print_key_id_file != NULL) && (print_key_permissions_file != NULL))
		usage();

	if ((print_key_id_file != NULL) ||
	    (print_key_permissions_file != NULL)) {
		/* We can't combine printing info with generating a new key. */
		if (newkeyfile != NULL)
			usage();

		/* We should have processed all arguments. */
		if (argc != 0)
			usage();

		/* Print info. */
		if (print_key_id_file != NULL)
			print_id(print_key_id_file);
		if (print_key_permissions_file != NULL)
			print_permissions(print_key_permissions_file);
	}

	/* We should have an output key file. */
	if (newkeyfile == NULL)
		usage();

	/*
	 * It doesn't make sense to specify --passphrase-mem or
	 * --passphrase-time if we're not using a passphrase.
	 */
	if (((maxmem != 0) || (maxtime != 1.0)) && (passphrased == 0))
		usage();

	/* Warn the user if they're being silly. */
	if (keyswanted == 0) {
		warn0("None of {-r, -w, -d, --nuke} options are specified."
		    "  This will create a key file with no keys, which is"
		    " probably not what you intended.");
	}

	/* Read the specified key files. */
	while (argc-- > 0) {
		/*
		 * Suck in the key file.  We could mask this to only load the
		 * keys we want to copy, but there's no point really since we
		 * export keys selectively.
		 */
		if (keyfile_read(argv[0], &kfmachinenum, ~0)) {
			warnp("Cannot read key file: %s", argv[0]);
			exit(1);
		}

		/*
		 * Check that we're not using key files which belong to
		 * different machines.
		 */
		if (machinenum == (uint64_t)(-1)) {
			machinenum = kfmachinenum;
		} else if (machinenum != kfmachinenum) {
			warn0("Keys from %s do not belong to the "
			    "same machine as earlier keys", argv[0]);
			exit(1);
		}

		/* Move on to the next file. */
		argv++;
	}

	/* Make sure that we have the necessary keys. */
	if ((missingkey = crypto_keys_missing(keyswanted)) != NULL) {
		warn0("The %s key is required but not in any input key files",
		    missingkey);
		exit(1);
	}

	/* If the user wants to passphrase the keyfile, get the passphrase. */
	if (passphrased != 0) {
		if (readpass(&passphrase,
		    "Please enter passphrase for keyfile encryption",
		    "Please confirm passphrase for keyfile encryption", 1)) {
			warnp("Error reading password");
			exit(1);
		}
	} else {
		passphrase = NULL;
	}

	/* Write out new key file. */
	if (keyfile_write(newkeyfile, machinenum, keyswanted,
	    passphrase, maxmem, maxtime))
		exit(1);

	/* Success! */
	return (0);
}
Ejemplo n.º 8
0
int
keygen_actual(struct register_internal * C, const char * keyfilename,
	const int passphrased, const uint64_t maxmem,
	const double maxtime,
	const char *oldkeyfilename)
{
	FILE * keyfile;
	char * passphrase = NULL;
	int keymask = CRYPTO_KEYMASK_USER;
	uint64_t dummy;

	/* Sanity-check the user name. */
	if (strlen(C->user) > 255) {
		fprintf(stderr, "User name too long: %s\n", C->user);
		goto err0;
	}
	if (strlen(C->user) == 0) {
		fprintf(stderr, "User name must be non-empty\n");
		goto err0;
	}

	/* Sanity-check the machine name. */
	if (strlen(C->name) > 255) {
		fprintf(stderr, "Machine name too long: %s\n", C->name);
		goto err0;
	}
	if (strlen(C->name) == 0) {
		fprintf(stderr, "Machine name must be non-empty\n");
		goto err0;
	}

	/* Get a password. */
	if (readpass(&C->passwd, "Enter tarsnap account password", NULL, 0)) {
		warnp("Error reading password");
		goto err0;
	}

	/*
	 * Create key file -- we do this now rather than later so that we
	 * avoid registering with the server if we won't be able to create
	 * the key file later.
	 */
	if ((keyfile = keyfile_write_open(keyfilename)) == NULL) {
		warnp("Cannot create %s", keyfilename);
		goto err1;
	}

	/* Initialize key cache. */
	if (crypto_keys_init()) {
		warnp("Key cache initialization failed");
		goto err3;
	}

	/* keyregen (with oldkeyfilename) only regenerates certain keys. */
	if (oldkeyfilename != NULL) {
		/*
		 * Load the keys CRYPTO_KEY_HMAC_{CHUNK, NAME, CPARAMS}
		 * from the old key file, since these are the keys which need
		 * to be consistent in order for two key sets to be
		 * compatible.  (CHUNK and NAME are used to compute the
		 * 32-byte keys for blocks; CPARAMS is used to compute
		 * parameters used to split a stream of bytes into chunks.)
		 */
		if (keyfile_read(oldkeyfilename, &dummy,
		    CRYPTO_KEYMASK_HMAC_CHUNK |
		    CRYPTO_KEYMASK_HMAC_NAME |
		    CRYPTO_KEYMASK_HMAC_CPARAMS)) {
			warnp("Error reading old key file");
			goto err3;
		}

		/*
		 * Adjust the keymask to avoid regenerating keys we read from
		 * the old keyfile.
		 */
		keymask &= ~CRYPTO_KEYMASK_HMAC_CHUNK &
		    ~CRYPTO_KEYMASK_HMAC_NAME &
		    ~CRYPTO_KEYMASK_HMAC_CPARAMS;
	}

	/* Generate keys. */
	if (crypto_keys_generate(keymask)) {
		warnp("Error generating keys");
		goto err3;
	}

	/* Register the keys with the server. */
	if (keygen_network_register(C) != 0)
		goto err3;

	/* Exit with a code of 1 if we couldn't register. */
	if (C->machinenum == (uint64_t)(-1))
		goto err3;

	/* If the user wants to passphrase the keyfile, get the passphrase. */
	if (passphrased != 0) {
		if (readpass(&passphrase,
		    "Please enter passphrase for keyfile encryption",
		    "Please confirm passphrase for keyfile encryption", 1)) {
			warnp("Error reading password");
			goto err3;
		}
	}

	/* Write keys to file. */
	if (keyfile_write_file(keyfile, C->machinenum,
	    CRYPTO_KEYMASK_USER, passphrase, maxmem, maxtime))
		goto err3;

	/* Close the key file. */
	if (fclose(keyfile)) {
		warnp("Error closing key file");
		goto err2;
	}

	/* Free allocated memory.  C->passwd is a NUL-terminated string. */
	insecure_memzero(C->passwd, strlen(C->passwd));
	free(C->passwd);

	/* Free passphrase, if used.  passphrase is a NUL-terminated string. */
	if (passphrase != NULL) {
		insecure_memzero(passphrase, strlen(passphrase));
		free(passphrase);
	}

	/* Success! */
	return (0);

err3:
	fclose(keyfile);
err2:
	unlink(keyfilename);
err1:
	insecure_memzero(C->passwd, strlen(C->passwd));
	free(C->passwd);
	if (passphrase != NULL) {
		insecure_memzero(passphrase, strlen(passphrase));
		free(passphrase);
	}
err0:
	/* Failure! */
	return (-1);
}