#ifdef TEST_CMDGEN
/*
* This section overrides some definitions below for test purposes.
- * When compiled with -DTEST_CMDGEN:
+ * When compiled with -DTEST_CMDGEN (as cgtest.c will do):
*
* - Calls to get_random_data() are replaced with the diagnostic
* function below (I #define the name so that I can still link
* run tests.
*/
#define get_random_data get_random_data_diagnostic
-char *get_random_data(int len)
+char *get_random_data(int len, const char *device)
{
char *buf = snewn(len, char);
memset(buf, 'x', len);
int ret = 1;
for (i = 0; i < p->n_prompts; i++) {
if (promptsgot < nprompts) {
- assert(strlen(prompts[promptsgot]) < p->prompts[i]->result_len);
- strcpy(p->prompts[i]->result, prompts[promptsgot++]);
+ p->prompts[i]->result = dupstr(prompts[promptsgot++]);
} else {
promptsgot++; /* track number of requests anyway */
ret = 0;
void showversion(void)
{
- printf("puttygen: %s\n", ver);
+ char *buildinfo_text = buildinfo("\n");
+ printf("puttygen: %s\n%s\n", ver, buildinfo_text);
+ sfree(buildinfo_text);
}
void usage(int standalone)
{
- fprintf(stderr,
+ fprintf(standalone ? stderr : stdout,
"Usage: puttygen ( keyfile | -t type [ -b bits ] )\n"
" [ -C comment ] [ -P ] [ -q ]\n"
" [ -o output-keyfile ] [ -O type | -l | -L"
* Help message is an extended version of the usage message. So
* start with that, plus a version heading.
*/
- showversion();
+ printf("PuTTYgen: key generator and converter for the PuTTY tools\n"
+ "%s\n", ver);
usage(FALSE);
- fprintf(stderr,
- " -t specify key type when generating (ed25519, ecdsa, rsa, "
+ printf(" -t specify key type when generating (ed25519, ecdsa, rsa, "
"dsa, rsa1)\n"
- " -b specify number of bits when generating key\n"
- " -C change or specify key comment\n"
- " -P change key passphrase\n"
- " -q quiet: do not display progress bar\n"
- " -O specify output type:\n"
- " private output PuTTY private key format\n"
- " private-openssh export OpenSSH private key\n"
- " private-openssh-new export OpenSSH private key "
- "(force new file format)\n"
- " private-sshcom export ssh.com private key\n"
- " public RFC 4716 / ssh.com public key\n"
- " public-openssh OpenSSH public key\n"
- " fingerprint output the key fingerprint\n"
- " -o specify output file\n"
- " -l equivalent to `-O fingerprint'\n"
- " -L equivalent to `-O public-openssh'\n"
- " -p equivalent to `-O public'\n"
- " --old-passphrase file\n"
- " specify file containing old key passphrase\n"
- " --new-passphrase file\n"
- " specify file containing new key passphrase\n"
- );
+ " -b specify number of bits when generating key\n"
+ " -C change or specify key comment\n"
+ " -P change key passphrase\n"
+ " -q quiet: do not display progress bar\n"
+ " -O specify output type:\n"
+ " private output PuTTY private key format\n"
+ " private-openssh export OpenSSH private key\n"
+ " private-openssh-new export OpenSSH private key "
+ "(force new format)\n"
+ " private-sshcom export ssh.com private key\n"
+ " public RFC 4716 / ssh.com public key\n"
+ " public-openssh OpenSSH public key\n"
+ " fingerprint output the key fingerprint\n"
+ " -o specify output file\n"
+ " -l equivalent to `-O fingerprint'\n"
+ " -L equivalent to `-O public-openssh'\n"
+ " -p equivalent to `-O public'\n"
+ " --old-passphrase file\n"
+ " specify file containing old key passphrase\n"
+ " --new-passphrase file\n"
+ " specify file containing new key passphrase\n"
+ " --random-device device\n"
+ " specify device to read entropy from (e.g. /dev/urandom)\n"
+ );
}
static int move(char *from, char *to)
return line;
}
+#define DEFAULT_RSADSA_BITS 2048
+
int main(int argc, char **argv)
{
char *infile = NULL;
char *old_passphrase = NULL, *new_passphrase = NULL;
int load_encrypted;
progfn_t progressfn = is_interactive() ? progress_update : no_progress;
+ const char *random_device = NULL;
/* ------------------------------------------------------------------
* Parse the command line to figure out what we've been asked to do.
if (!new_passphrase)
errs = TRUE;
}
+ } else if (!strcmp(opt, "-random-device")) {
+ if (!val && argc > 1)
+ --argc, val = *++argv;
+ if (!val) {
+ errs = TRUE;
+ fprintf(stderr, "puttygen: option `-%s'"
+ " expects an argument\n", opt);
+ } else {
+ random_device = val;
+ }
} else {
errs = TRUE;
fprintf(stderr,
bits = 256;
break;
default:
- bits = 2048;
+ bits = DEFAULT_RSADSA_BITS;
break;
}
}
errs = TRUE;
}
+ if (keytype == RSA2 || keytype == RSA1 || keytype == DSA) {
+ if (bits < 256) {
+ fprintf(stderr, "puttygen: cannot generate %s keys shorter than"
+ " 256 bits\n", (keytype == DSA ? "DSA" : "RSA"));
+ errs = TRUE;
+ } else if (bits < DEFAULT_RSADSA_BITS) {
+ fprintf(stderr, "puttygen: warning: %s keys shorter than"
+ " %d bits are probably not secure\n",
+ (keytype == DSA ? "DSA" : "RSA"), DEFAULT_RSADSA_BITS);
+ /* but this is just a warning, so proceed anyway */
+ }
+ }
+
if (errs)
return 1;
strftime(default_comment, 30, "rsa-key-%Y%m%d", &tm);
random_ref();
- entropy = get_random_data(bits / 8);
+ entropy = get_random_data(bits / 8, random_device);
if (!entropy) {
fprintf(stderr, "puttygen: failed to collect entropy, "
"could not generate key\n");
} else {
passes++;
}
+
+ sfree(argv);
}
void filecmp(char *file1, char *file2, char *fmt, ...)
s += strspn(s, " \n\t");
s += strcspn(s, " \n\t");
- return dupprintf("%.*s", s - p, p);
+ return dupprintf("%.*s", (int)(s - p), p);
}
char *get_fp(char *filename)