Exemplo n.º 1
0
/**
 * scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
 *     maxmem, maxmemfrac, maxtime):
 * Decrypt inbuflen bytes from inbuf, writing the result into outbuf and the
 * decrypted data length to outlen.  The allocated length of outbuf must
 * be at least inbuflen.
 */
int
scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
    size_t * outlen, const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	uint8_t hbuf[32];
	uint8_t dk[64];
	uint8_t * key_enc = dk;
	uint8_t * key_hmac = &dk[32];
	int rc;
	HMAC_SHA256_CTX hctx;
	struct crypto_aes_key * key_enc_exp;
	struct crypto_aesctr * AES;

	/*
	 * All versions of the scrypt format will start with "scrypt" and
	 * have at least 7 bytes of header.
	 */
	if ((inbuflen < 7) || (memcmp(inbuf, "scrypt", 6) != 0))
		return (7);

	/* Check the format. */
	if (inbuf[6] != 0)
		return (8);

	/* We must have at least 128 bytes. */
	if (inbuflen < 128)
		return (7);

	/* Parse the header and generate derived keys. */
	if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen,
	    maxmem, maxmemfrac, maxtime)) != 0)
		return (rc);

	/* Decrypt data. */
	if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
		return (5);
	if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
		return (6);
	crypto_aesctr_stream(AES, &inbuf[96], outbuf, inbuflen - 128);
	crypto_aesctr_free(AES);
	crypto_aes_key_free(key_enc_exp);
	*outlen = inbuflen - 128;

	/* Verify signature. */
	HMAC_SHA256_Init(&hctx, key_hmac, 32);
	HMAC_SHA256_Update(&hctx, inbuf, inbuflen - 32);
	HMAC_SHA256_Final(hbuf, &hctx);
	if (memcmp(hbuf, &inbuf[inbuflen - 32], 32))
		return (7);

	/* Zero sensitive data. */
	insecure_memzero(dk, 64);

	/* Success! */
	return (0);
}
Exemplo n.º 2
0
/**
 * crypto_aesctr_free(stream):
 * Free the provided stream object.
 */
void
crypto_aesctr_free(struct crypto_aesctr * stream)
{

	/* Behave consistently with free(NULL). */
	if (stream == NULL)
		return;

	/* Zero potentially sensitive information. */
	insecure_memzero(stream, sizeof(struct crypto_aesctr));

	/* Free the stream. */
	free(stream);
}
Exemplo n.º 3
0
/**
 * crypto_aes_key_free_aesni(key):
 * Free the expanded AES key ${key}.
 */
void
crypto_aes_key_free_aesni(void * key)
{

	/* Behave consistently with free(NULL). */
	if (key == NULL)
		return;

	/* Attempt to zero the expanded key. */
	insecure_memzero(key, sizeof(struct crypto_aes_key_aesni));

	/* Free the key. */
	free(key);
}
Exemplo n.º 4
0
/**
 * crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen):
 * Equivalent to init(key, nonce); stream(inbuf, outbuf, buflen); free.
 */
void
crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce,
    const uint8_t * inbuf, uint8_t * outbuf, size_t buflen)
{
	struct crypto_aesctr stream_rec;
	struct crypto_aesctr * stream = &stream_rec;

	/* Initialize values. */
	stream->key = key;
	stream->nonce = nonce;
	stream->bytectr = 0;

	/* Perform the encryption. */
	crypto_aesctr_stream(stream, inbuf, outbuf, buflen);

	/* Zero potentially sensitive information. */
	insecure_memzero(stream, sizeof(struct crypto_aesctr));
}
Exemplo n.º 5
0
/**
 * scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
 *     maxmem, maxmemfrac, maxtime):
 * Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
 * bytes to outbuf.
 */
int
scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
    const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	uint8_t dk[64];
	uint8_t hbuf[32];
	uint8_t header[96];
	uint8_t * key_enc = dk;
	uint8_t * key_hmac = &dk[32];
	int rc;
	HMAC_SHA256_CTX hctx;
	struct crypto_aes_key * key_enc_exp;
	struct crypto_aesctr * AES;

	/* Generate the header and derived key. */
	if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
	    maxmem, maxmemfrac, maxtime)) != 0)
		return (rc);

	/* Copy header into output buffer. */
	memcpy(outbuf, header, 96);

	/* Encrypt data. */
	if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
		return (5);
	if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
		return (6);
	crypto_aesctr_stream(AES, inbuf, &outbuf[96], inbuflen);
	crypto_aesctr_free(AES);
	crypto_aes_key_free(key_enc_exp);

	/* Add signature. */
	HMAC_SHA256_Init(&hctx, key_hmac, 32);
	HMAC_SHA256_Update(&hctx, outbuf, 96 + inbuflen);
	HMAC_SHA256_Final(hbuf, &hctx);
	memcpy(&outbuf[96 + inbuflen], hbuf, 32);

	/* Zero sensitive data. */
	insecure_memzero(dk, 64);

	/* Success! */
	return (0);
}
Exemplo n.º 6
0
/**
 * crypto_aes_key_free(key):
 * Free the expanded AES key ${key}.
 */
void
crypto_aes_key_free(struct crypto_aes_key * key)
{

#ifdef CPUSUPPORT_X86_AESNI
	if (useaesni()) {
		crypto_aes_key_free_aesni((void *)key);
		return;
	}
#endif

	/* Behave consistently with free(NULL). */
	if (key == NULL)
		return;

	/* Attempt to zero the expanded key. */
	insecure_memzero(key, sizeof(AES_KEY));

	/* Free the key. */
	free(key);
}
Exemplo n.º 7
0
/**
 * scryptdec_file(infile, outfile, passwd, passwdlen,
 *     maxmem, maxmemfrac, maxtime):
 * Read a stream from infile and decrypt it, writing the resulting stream to
 * outfile.
 */
int
scryptdec_file(FILE * infile, FILE * outfile,
    const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	uint8_t buf[ENCBLOCK + 32];
	uint8_t header[96];
	uint8_t hbuf[32];
	uint8_t dk[64];
	uint8_t * key_enc = dk;
	uint8_t * key_hmac = &dk[32];
	size_t buflen = 0;
	size_t readlen;
	HMAC_SHA256_CTX hctx;
	struct crypto_aes_key * key_enc_exp;
	struct crypto_aesctr * AES;
	int rc;

	/*
	 * Read the first 7 bytes of the file; all future versions of scrypt
	 * are guaranteed to have at least 7 bytes of header.
	 */
	if (fread(header, 7, 1, infile) < 1) {
		if (ferror(infile))
			return (13);
		else
			return (7);
	}

	/* Do we have the right magic? */
	if (memcmp(header, "scrypt", 6))
		return (7);
	if (header[6] != 0)
		return (8);

	/*
	 * Read another 89 bytes of the file; version 0 of the scrypt file
	 * format has a 96-byte header.
	 */
	if (fread(&header[7], 89, 1, infile) < 1) {
		if (ferror(infile))
			return (13);
		else
			return (7);
	}

	/* Parse the header and generate derived keys. */
	if ((rc = scryptdec_setup(header, dk, passwd, passwdlen,
	    maxmem, maxmemfrac, maxtime)) != 0)
		return (rc);

	/* Start hashing with the header. */
	HMAC_SHA256_Init(&hctx, key_hmac, 32);
	HMAC_SHA256_Update(&hctx, header, 96);

	/*
	 * We don't know how long the encrypted data block is (we can't know,
	 * since data can be streamed into 'scrypt enc') so we need to read
	 * data and decrypt all of it except the final 32 bytes, then check
	 * if that final 32 bytes is the correct signature.
	 */
	if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
		return (5);
	if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
		return (6);
	do {
		/* Read data until we have more than 32 bytes of it. */
		if ((readlen = fread(&buf[buflen], 1,
		    ENCBLOCK + 32 - buflen, infile)) == 0)
			break;
		buflen += readlen;
		if (buflen <= 32)
			continue;

		/*
		 * Decrypt, hash, and output everything except the last 32
		 * bytes out of what we have in our buffer.
		 */
		HMAC_SHA256_Update(&hctx, buf, buflen - 32);
		crypto_aesctr_stream(AES, buf, buf, buflen - 32);
		if (fwrite(buf, 1, buflen - 32, outfile) < buflen - 32) {
			crypto_aesctr_free(AES);
			return (12);
		}

		/* Move the last 32 bytes to the start of the buffer. */
		memmove(buf, &buf[buflen - 32], 32);
		buflen = 32;
	} while (1);
	crypto_aesctr_free(AES);
	crypto_aes_key_free(key_enc_exp);

	/* Did we exit the loop due to a read error? */
	if (ferror(infile))
		return (13);

	/* Did we read enough data that we *might* have a valid signature? */
	if (buflen < 32)
		return (7);

	/* Verify signature. */
	HMAC_SHA256_Final(hbuf, &hctx);
	if (memcmp(hbuf, buf, 32))
		return (7);

	/* Zero sensitive data. */
	insecure_memzero(dk, 64);

	return (0);
}
Exemplo n.º 8
0
/**
 * scryptenc_file(infile, outfile, passwd, passwdlen,
 *     maxmem, maxmemfrac, maxtime):
 * Read a stream from infile and encrypt it, writing the resulting stream to
 * outfile.
 */
int
scryptenc_file(FILE * infile, FILE * outfile,
    const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	uint8_t buf[ENCBLOCK];
	uint8_t dk[64];
	uint8_t hbuf[32];
	uint8_t header[96];
	uint8_t * key_enc = dk;
	uint8_t * key_hmac = &dk[32];
	size_t readlen;
	HMAC_SHA256_CTX hctx;
	struct crypto_aes_key * key_enc_exp;
	struct crypto_aesctr * AES;
	int rc;

	/* Generate the header and derived key. */
	if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
	    maxmem, maxmemfrac, maxtime)) != 0)
		return (rc);

	/* Hash and write the header. */
	HMAC_SHA256_Init(&hctx, key_hmac, 32);
	HMAC_SHA256_Update(&hctx, header, 96);
	if (fwrite(header, 96, 1, outfile) != 1)
		return (12);

	/*
	 * Read blocks of data, encrypt them, and write them out; hash the
	 * data as it is produced.
	 */
	if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
		return (5);
	if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
		return (6);
	do {
		if ((readlen = fread(buf, 1, ENCBLOCK, infile)) == 0)
			break;
		crypto_aesctr_stream(AES, buf, buf, readlen);
		HMAC_SHA256_Update(&hctx, buf, readlen);
		if (fwrite(buf, 1, readlen, outfile) < readlen) {
			crypto_aesctr_free(AES);
			return (12);
		}
	} while (1);
	crypto_aesctr_free(AES);
	crypto_aes_key_free(key_enc_exp);

	/* Did we exit the loop due to a read error? */
	if (ferror(infile))
		return (13);

	/* Compute the final HMAC and output it. */
	HMAC_SHA256_Final(hbuf, &hctx);
	if (fwrite(hbuf, 32, 1, outfile) != 1)
		return (12);

	/* Zero sensitive data. */
	insecure_memzero(dk, 64);

	/* Success! */
	return (0);
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
0
int
main(int argc, char * argv[])
{
	/* State variables. */
	struct serverpool * SP;
	struct dynamodb_request_queue * QW;
	struct dynamodb_request_queue * QR;
	struct dispatch_state * D;
	int s;

	/* Command-line parameters. */
	char * opt_k = NULL;
	char * opt_l = NULL;
	char * opt_p = NULL;
	char * opt_r = NULL;
	char * opt_s = NULL;
	char * opt_t = NULL;
	int opt_1 = 0;

	/* Working variable. */
	char * dynamodb_host;
	char * key_id;
	char * key_secret;
	struct sock_addr ** sas;
	struct logging_file * logfile;
	struct capacity_reader * M;
	const char * ch;

	WARNP_INIT;

	/* Parse the command line. */
	while ((ch = GETOPT(argc, argv)) != NULL) {
		GETOPT_SWITCH(ch) {
		GETOPT_OPTARG("-k"):
			if (opt_k != NULL)
				usage();
			if ((opt_k = strdup(optarg)) == NULL)
				OPT_EPARSE(ch, optarg);
			break;
		GETOPT_OPTARG("-l"):
			if (opt_l != NULL)
				usage();
			if ((opt_l = strdup(optarg)) == NULL)
				OPT_EPARSE(ch, optarg);
			break;
		GETOPT_OPTARG("-p"):
			if (opt_p != NULL)
				usage();
			if ((opt_p = strdup(optarg)) == NULL)
				OPT_EPARSE(ch, optarg);
			break;
		GETOPT_OPTARG("-r"):
			if (opt_r != NULL)
				usage();
			if ((opt_r = strdup(optarg)) == NULL)
				OPT_EPARSE(ch, optarg);
			break;
		GETOPT_OPTARG("-s"):
			if (opt_s != NULL)
				usage();
			if ((opt_s = strdup(optarg)) == NULL)
				OPT_EPARSE(ch, optarg);
			break;
		GETOPT_OPTARG("-t"):
			if (opt_t != NULL)
				usage();
			if ((opt_t = strdup(optarg)) == NULL)
				OPT_EPARSE(ch, optarg);
			break;
		GETOPT_OPT("--version"):
			fprintf(stderr, "dynamodb-kv @VERSION@\n");
			exit(0);
		GETOPT_OPT("-1"):
			if (opt_1 != 0)
				usage();
			opt_1 = 1;
			break;
		GETOPT_MISSING_ARG:
			warn0("Missing argument to %s\n", ch);
			usage();
		GETOPT_DEFAULT:
			warn0("illegal option -- %s\n", ch);
			usage();
		}
	}
	argc -= optind;
	argv += optind;

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

	/* Verify that we have mandatory options. */
	if (opt_k == NULL)
		usage();
	if (opt_r == NULL)
		usage();
	if (opt_s == NULL)
		usage();
	if (opt_t == NULL)
		usage();

	/* Construct the DynamoDB endpoint host name. */
	if (asprintf(&dynamodb_host, "dynamodb.%s.amazonaws.com:80",
	    opt_r) == -1) {
		warnp("asprintf");
		exit(1);
	}

	/* Start looking up addresses for DynamoDB endpoints. */
	if ((SP = serverpool_create(dynamodb_host, 15, 120)) == NULL) {
		warnp("Error starting DNS lookups for %s", dynamodb_host);
		exit(1);
	}

	/* Read the key file. */
	if (aws_readkeys(opt_k, &key_id, &key_secret)) {
		warnp("Error reading AWS keys from %s", opt_k);
		exit(1);
	}

	/* Create DynamoDB request queues for writes and reads. */
	if ((QW = dynamodb_request_queue_init(key_id, key_secret,
	    opt_r, SP)) == NULL) {
		warnp("Error creating DynamoDB request queue");
		exit(1);
	}
	if ((QR = dynamodb_request_queue_init(key_id, key_secret,
	    opt_r, SP)) == NULL) {
		warnp("Error creating DynamoDB request queue");
		exit(1);
	}

	/* Start reading table throughput parameters. */
	if ((M = capacity_init(key_id, key_secret, opt_t, opt_r,
	    SP, QW, QR)) == NULL) {
		warnp("Error reading DynamoDB table metadata");
		exit(1);
	}

	/* Resolve the listening address. */
	if ((sas = sock_resolve(opt_s)) == NULL) {
		warnp("Error resolving socket address: %s", opt_s);
		exit(1);
	}
	if (sas[0] == NULL) {
		warn0("No addresses found for %s", opt_s);
		exit(1);
	}

	/* Create and bind a socket, and mark it as listening. */
	if (sas[1] != NULL)
		warn0("Listening on first of multiple addresses found for %s",
		    opt_s);
	if ((s = sock_listener(sas[0])) == -1)
		exit(1);

	/* If requested, create a log file. */
	if (opt_l != NULL) {
		if ((logfile = logging_open(opt_l)) == NULL) {
			warnp("Cannot open log file");
			exit(1);
		}
		dynamodb_request_queue_log(QW, logfile);
		dynamodb_request_queue_log(QR, logfile);
	} else {
		logfile = NULL;
	}

	/* Daemonize and write pid. */
	if (opt_p == NULL) {
		if (asprintf(&opt_p, "%s.pid", opt_s) == -1) {
			warnp("asprintf");
			exit(1);
		}
	}
	if (daemonize(opt_p)) {
		warnp("Failed to daemonize");
		exit(1);
	}

	/* Handle connections, one at once. */
	do {
		/* accept a connection. */
		if ((D = dispatch_accept(QW, QR, opt_t, s)) == NULL) {
			warnp("Error accepting new connection");
			exit(1);
		}

		/* Loop until the connection dies. */
		do {
			if (events_run()) {
				warnp("Error running event loop");
				exit(1);
			}
		} while (dispatch_alive(D));

		/* Clean up the connection. */
		if (dispatch_done(D))
			exit(1);
	} while (opt_1 == 0);

	/* Close the log file, if we have one. */
	if (logfile != NULL)
		logging_close(logfile);

	/* Close the listening socket. */
	close(s);

	/* Free the address structures. */
	sock_addr_freelist(sas);

	/* Stop performing DescribeTable requests. */
	capacity_free(M);

	/* Free DynamoDB request queues. */
	dynamodb_request_queue_free(QR);
	dynamodb_request_queue_free(QW);

	/* Stop DNS lookups. */
	serverpool_free(SP);

	/* Shut down the event subsystem. */
	events_shutdown();

	/* Free string allocated by asprintf. */
	free(dynamodb_host);

	/* Free key strings. */
	free(key_id);
	insecure_memzero(key_secret, strlen(key_secret));
	free(key_secret);

	/* Free option strings. */
	free(opt_k);
	free(opt_l);
	free(opt_p);
	free(opt_r);
	free(opt_s);
	free(opt_t);

	/* Success! */
	exit(0);
}
Exemplo n.º 11
0
/**
 * readpass(passwd, prompt, confirmprompt, devtty)
 * If ${devtty} is non-zero, read a password from /dev/tty if possible; if
 * not, read from stdin.  If reading from a tty (either /dev/tty or stdin),
 * disable echo and prompt the user by printing ${prompt} to stderr.  If
 * ${confirmprompt} is non-NULL, read a second password (prompting if a
 * terminal is being used) and repeat until the user enters the same password
 * twice.  Return the password as a malloced NUL-terminated string via
 * ${passwd}.
 */
int
readpass(char ** passwd, const char * prompt,
    const char * confirmprompt, int devtty)
{
	FILE * readfrom;
	char passbuf[MAXPASSLEN];
	char confpassbuf[MAXPASSLEN];
	struct sigaction sa, savedsa[NSIGS];
	struct termios term, term_old;
	size_t i;
	int usingtty;

	/*
	 * If devtty != 0, try to open /dev/tty; if that fails, or if devtty
	 * is zero, we'll read the password from stdin instead.
	 */
	if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL))
		readfrom = stdin;

	/* We have not received any signals yet. */
	for (i = 0; i <= MAXSIG; i++)
		gotsig[i] = 0;

	/*
	 * If we receive a signal while we're reading the password, we might
	 * end up with echo disabled; to prevent this, we catch the signals
	 * here, and we'll re-send them to ourselves later after we re-enable
	 * terminal echo.
	 */
	sa.sa_handler = handle;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	for (i = 0; i < NSIGS; i++)
		sigaction(badsigs[i], &sa, &savedsa[i]);

	/* If we're reading from a terminal, try to disable echo. */
	if ((usingtty = isatty(fileno(readfrom))) != 0) {
		if (tcgetattr(fileno(readfrom), &term_old)) {
			warnp("Cannot read terminal settings");
			goto err2;
		}
		memcpy(&term, &term_old, sizeof(struct termios));
		term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL;
		if (tcsetattr(fileno(readfrom), TCSANOW, &term)) {
			warnp("Cannot set terminal settings");
			goto err2;
		}
	}

retry:
	/* If we have a terminal, prompt the user to enter the password. */
	if (usingtty)
		fprintf(stderr, "%s: ", prompt);

	/* Read the password. */
	if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) {
		warnp("Cannot read password");
		goto err3;
	}

	/* Confirm the password if necessary. */
	if (confirmprompt != NULL) {
		if (usingtty)
			fprintf(stderr, "%s: ", confirmprompt);
		if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) {
			warnp("Cannot read password");
			goto err3;
		}
		if (strcmp(passbuf, confpassbuf)) {
			fprintf(stderr,
			    "Passwords mismatch, please try again\n");
			goto retry;
		}
	}

	/* Terminate the string at the first "\r" or "\n" (if any). */
	passbuf[strcspn(passbuf, "\r\n")] = '\0';

	/* If we changed terminal settings, reset them. */
	if (usingtty)
		tcsetattr(fileno(readfrom), TCSANOW, &term_old);

	/* Restore old signals. */
	for (i = 0; i < NSIGS; i++)
		sigaction(badsigs[i], &savedsa[i], NULL);

	/* If we intercepted a signal, re-issue it. */
	for (i = 0; i < NSIGS; i++) {
		if (gotsig[badsigs[i]])
			raise(badsigs[i]);
	}

	/* Close /dev/tty if we opened it. */
	if (readfrom != stdin)
		fclose(readfrom);

	/* Copy the password out. */
	if ((*passwd = strdup(passbuf)) == NULL) {
		warnp("Cannot allocate memory");
		goto err1;
	}

	/*
	 * Zero any stored passwords.  This is not guaranteed to work, since a
	 * "sufficiently intelligent" compiler can optimize these out due to
	 * the values not being accessed again; and even if we outwitted the
	 * compiler, all we can do is ensure that *a* buffer is zeroed but
	 * not that it is the only buffer containing the data in question.
	 * Unfortunately the C standard does not provide any way to mark data
	 * as "sensitive" in order to prevent extra copies being sprinkled
	 * around the implementation address space.
	 */
	insecure_memzero(passbuf, MAXPASSLEN);
	insecure_memzero(confpassbuf, MAXPASSLEN);

	/* Success! */
	return (0);

err3:
	/* Reset terminal settings if necessary. */
	if (usingtty)
		tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old);
err2:
	/* Close /dev/tty if we opened it. */
	if (readfrom != stdin)
		fclose(readfrom);
err1:
	/* Zero any stored passwords. */
	insecure_memzero(passbuf, MAXPASSLEN);
	insecure_memzero(confpassbuf, MAXPASSLEN);

	/* Failure! */
	return (-1);
}
Exemplo n.º 12
0
/**
 * aws_readkeys(fname, key_id, key_secret):
 * Read an AWS key id and secret from the file ${fname}, returning malloced
 * strings via ${key_id} and ${key_secret}.
 */
int
aws_readkeys(const char * fname, char ** key_id, char ** key_secret)
{
	FILE * f;
	char buf[1024];
	char * p;

	/* No keys yet. */
	*key_id = *key_secret = NULL;

	/* Open the key file. */
	if ((f = fopen(fname, "r")) == NULL) {
		warnp("fopen(%s)", fname);
		goto err0;
	}

	/* Read lines of up to 1024 characters. */
	while (fgets(buf, sizeof(buf), f) != NULL) {
		/* Find the first EOL character and truncate. */
		p = buf + strcspn(buf, "\r\n");
		if (*p == '\0') {
			warn0("Missing EOL in %s", fname);
			break;
		} else
			*p = '\0';

		/* Look for the first = character. */
		p = strchr(buf, '=');

		/* Missing separator? */
		if (p == NULL)
			goto err3;

		/* Replace separator with NUL and point p at the value. */
		*p++ = '\0';

		/* We should have ACCESS_KEY_ID or ACCESS_KEY_SECRET. */
		if (strcmp(buf, "ACCESS_KEY_ID") == 0) {
			/* Copy key ID string. */
			if (*key_id != NULL) {
				warn0("ACCESS_KEY_ID specified twice");
				goto err2;
			}
			if ((*key_id = strdup(p)) == NULL)
				goto err2;
		} else if (strcmp(buf, "ACCESS_KEY_SECRET") == 0) {
			/* Copy key secret string. */
			if (*key_secret != NULL) {
				warn0("ACCESS_KEY_SECRET specified twice");
				goto err2;
			}
			if ((*key_secret = strdup(p)) == NULL)
				goto err2;
		} else
			goto err3;
	}

	/* Check for error. */
	if (ferror(f)) {
		warnp("Error reading %s", fname);
		goto err2;
	}

	/* Close the file. */
	if (fclose(f)) {
		warnp("fclose");
		goto err1;
	}

	/* Check that we got the necessary keys. */
	if ((*key_id == NULL) || (*key_secret == NULL)) {
		warn0("Need ACCESS_KEY_ID and ACCESS_KEY_SECRET");
		goto err1;
	}

	/* Success! */
	return (0);

err3:
	warn0("Lines in %s must be ACCESS_KEY_(ID|SECRET)=...", fname);
err2:
	fclose(f);
err1:
	free(*key_id);
	if (*key_secret) {
		insecure_memzero(*key_secret, strlen(*key_secret));
		free(*key_secret);
	}
err0:
	/* Failure! */
	return (-1);
}
Exemplo n.º 13
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);
}