mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-05-10 03:58:36 +00:00
- markus@cvs.openbsd.org 2013/12/06 13:34:54
[authfile.c authfile.h cipher.c cipher.h key.c packet.c ssh-agent.c] [ssh-keygen.c PROTOCOL.key] new private key format, bcrypt as KDF by default; details in PROTOCOL.key; feedback and lots help from djm; ok djm@
This commit is contained in:
parent
f0e9060d23
commit
bcd00abd84
@ -12,6 +12,11 @@
|
|||||||
- markus@cvs.openbsd.org 2013/12/06 13:30:08
|
- markus@cvs.openbsd.org 2013/12/06 13:30:08
|
||||||
[authfd.c key.c key.h ssh-agent.c]
|
[authfd.c key.c key.h ssh-agent.c]
|
||||||
move private key (de)serialization to key.c; ok djm
|
move private key (de)serialization to key.c; ok djm
|
||||||
|
- markus@cvs.openbsd.org 2013/12/06 13:34:54
|
||||||
|
[authfile.c authfile.h cipher.c cipher.h key.c packet.c ssh-agent.c]
|
||||||
|
[ssh-keygen.c PROTOCOL.key] new private key format, bcrypt as KDF by
|
||||||
|
default; details in PROTOCOL.key; feedback and lots help from djm;
|
||||||
|
ok djm@
|
||||||
|
|
||||||
20131205
|
20131205
|
||||||
- (djm) OpenBSD CVS Sync
|
- (djm) OpenBSD CVS Sync
|
||||||
|
68
PROTOCOL.key
Normal file
68
PROTOCOL.key
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
This document describes the private key format for OpenSSH.
|
||||||
|
|
||||||
|
1. Overall format
|
||||||
|
|
||||||
|
The key consists of a header, a list of public keys, and
|
||||||
|
an encrypted list of matching private keys.
|
||||||
|
|
||||||
|
#define AUTH_MAGIC "openssh-key-v1"
|
||||||
|
|
||||||
|
byte[] AUTH_MAGIC
|
||||||
|
string ciphername
|
||||||
|
string kdfname
|
||||||
|
string kdfoptions
|
||||||
|
int number of keys N
|
||||||
|
string publickey1
|
||||||
|
string publickey2
|
||||||
|
...
|
||||||
|
string publickeyN
|
||||||
|
string encrypted, padded list of private keys
|
||||||
|
|
||||||
|
2. KDF options for kdfname "bcrypt"
|
||||||
|
|
||||||
|
The options:
|
||||||
|
|
||||||
|
string salt
|
||||||
|
uint32 rounds
|
||||||
|
|
||||||
|
are concatenated and represented as a string.
|
||||||
|
|
||||||
|
3. Unencrypted list of N private keys
|
||||||
|
|
||||||
|
The list of privatekey/comment pairs is padded with the
|
||||||
|
bytes 1, 2, 3, ... until the total length is a multiple
|
||||||
|
of the cipher block size.
|
||||||
|
|
||||||
|
uint32 checkint
|
||||||
|
uint32 checkint
|
||||||
|
string privatekey1
|
||||||
|
string comment1
|
||||||
|
string privatekey2
|
||||||
|
string comment2
|
||||||
|
...
|
||||||
|
string privatekeyN
|
||||||
|
string commentN
|
||||||
|
char 1
|
||||||
|
char 2
|
||||||
|
char 3
|
||||||
|
...
|
||||||
|
char padlen % 255
|
||||||
|
|
||||||
|
Before the key is encrypted, a random integer is assigned
|
||||||
|
to both checkint fields so successful decryption can be
|
||||||
|
quickly checked by verifying that both checkint fields
|
||||||
|
hold the same value.
|
||||||
|
|
||||||
|
4. Encryption
|
||||||
|
|
||||||
|
The KDF is used to derive a key, IV (and other values required by
|
||||||
|
the cipher) from the passphrase. These values are then used to
|
||||||
|
encrypt the unencrypted list of private keys.
|
||||||
|
|
||||||
|
5. No encryption
|
||||||
|
|
||||||
|
For unencrypted keys the cipher "none" and the KDF "none"
|
||||||
|
are used with empty passphrases. The options if the KDF "none"
|
||||||
|
are the empty string.
|
||||||
|
|
||||||
|
$OpenBSD: PROTOCOL.key,v 1.1 2013/12/06 13:34:54 markus Exp $
|
371
authfile.c
371
authfile.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: authfile.c,v 1.98 2013/11/21 00:45:43 djm Exp $ */
|
/* $OpenBSD: authfile.c,v 1.99 2013/12/06 13:34:54 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -58,6 +58,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
@ -68,6 +70,16 @@
|
|||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "atomicio.h"
|
#include "atomicio.h"
|
||||||
|
#include "uuencode.h"
|
||||||
|
|
||||||
|
/* openssh private key file format */
|
||||||
|
#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||||
|
#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
|
||||||
|
#define KDFNAME "bcrypt"
|
||||||
|
#define AUTH_MAGIC "openssh-key-v1"
|
||||||
|
#define SALT_LEN 16
|
||||||
|
#define DEFAULT_CIPHERNAME "aes256-cbc"
|
||||||
|
#define DEFAULT_ROUNDS 16
|
||||||
|
|
||||||
#define MAX_KEY_FILE_SIZE (1024 * 1024)
|
#define MAX_KEY_FILE_SIZE (1024 * 1024)
|
||||||
|
|
||||||
@ -75,6 +87,333 @@
|
|||||||
static const char authfile_id_string[] =
|
static const char authfile_id_string[] =
|
||||||
"SSH PRIVATE KEY FILE FORMAT 1.1\n";
|
"SSH PRIVATE KEY FILE FORMAT 1.1\n";
|
||||||
|
|
||||||
|
static int
|
||||||
|
key_private_to_blob2(Key *prv, Buffer *blob, const char *passphrase,
|
||||||
|
const char *comment, const char *ciphername, int rounds)
|
||||||
|
{
|
||||||
|
u_char *key, *cp, salt[SALT_LEN];
|
||||||
|
size_t keylen, ivlen, blocksize, authlen;
|
||||||
|
u_int len, check;
|
||||||
|
int i, n;
|
||||||
|
const Cipher *c;
|
||||||
|
Buffer encoded, b, kdf;
|
||||||
|
CipherContext ctx;
|
||||||
|
const char *kdfname = KDFNAME;
|
||||||
|
|
||||||
|
if (rounds <= 0)
|
||||||
|
rounds = DEFAULT_ROUNDS;
|
||||||
|
if (passphrase == NULL || !strlen(passphrase)) {
|
||||||
|
ciphername = "none";
|
||||||
|
kdfname = "none";
|
||||||
|
} else if (ciphername == NULL)
|
||||||
|
ciphername = DEFAULT_CIPHERNAME;
|
||||||
|
else if (cipher_number(ciphername) != SSH_CIPHER_SSH2)
|
||||||
|
fatal("invalid cipher");
|
||||||
|
|
||||||
|
if ((c = cipher_by_name(ciphername)) == NULL)
|
||||||
|
fatal("unknown cipher name");
|
||||||
|
buffer_init(&kdf);
|
||||||
|
blocksize = cipher_blocksize(c);
|
||||||
|
keylen = cipher_keylen(c);
|
||||||
|
ivlen = cipher_ivlen(c);
|
||||||
|
authlen = cipher_authlen(c);
|
||||||
|
key = xcalloc(1, keylen + ivlen);
|
||||||
|
if (strcmp(kdfname, "none") != 0) {
|
||||||
|
arc4random_buf(salt, SALT_LEN);
|
||||||
|
if (bcrypt_pbkdf(passphrase, strlen(passphrase),
|
||||||
|
salt, SALT_LEN, key, keylen + ivlen, rounds) < 0)
|
||||||
|
fatal("bcrypt_pbkdf failed");
|
||||||
|
buffer_put_string(&kdf, salt, SALT_LEN);
|
||||||
|
buffer_put_int(&kdf, rounds);
|
||||||
|
}
|
||||||
|
cipher_init(&ctx, c, key, keylen, key + keylen , ivlen, 1);
|
||||||
|
memset(key, 0, keylen + ivlen);
|
||||||
|
free(key);
|
||||||
|
|
||||||
|
buffer_init(&encoded);
|
||||||
|
buffer_append(&encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC));
|
||||||
|
buffer_put_cstring(&encoded, ciphername);
|
||||||
|
buffer_put_cstring(&encoded, kdfname);
|
||||||
|
buffer_put_string(&encoded, buffer_ptr(&kdf), buffer_len(&kdf));
|
||||||
|
buffer_put_int(&encoded, 1); /* number of keys */
|
||||||
|
key_to_blob(prv, &cp, &len); /* public key */
|
||||||
|
buffer_put_string(&encoded, cp, len);
|
||||||
|
|
||||||
|
memset(cp, 0, len);
|
||||||
|
free(cp);
|
||||||
|
|
||||||
|
buffer_free(&kdf);
|
||||||
|
|
||||||
|
/* set up the buffer that will be encrypted */
|
||||||
|
buffer_init(&b);
|
||||||
|
|
||||||
|
/* Random check bytes */
|
||||||
|
check = arc4random();
|
||||||
|
buffer_put_int(&b, check);
|
||||||
|
buffer_put_int(&b, check);
|
||||||
|
|
||||||
|
/* append private key and comment*/
|
||||||
|
key_private_serialize(prv, &b);
|
||||||
|
buffer_put_cstring(&b, comment);
|
||||||
|
|
||||||
|
/* padding */
|
||||||
|
i = 0;
|
||||||
|
while (buffer_len(&b) % blocksize)
|
||||||
|
buffer_put_char(&b, ++i & 0xff);
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
buffer_put_int(&encoded, buffer_len(&b));
|
||||||
|
|
||||||
|
/* encrypt */
|
||||||
|
cp = buffer_append_space(&encoded, buffer_len(&b) + authlen);
|
||||||
|
if (cipher_crypt(&ctx, 0, cp, buffer_ptr(&b), buffer_len(&b), 0,
|
||||||
|
authlen) != 0)
|
||||||
|
fatal("%s: cipher_crypt failed", __func__);
|
||||||
|
buffer_free(&b);
|
||||||
|
cipher_cleanup(&ctx);
|
||||||
|
|
||||||
|
/* uuencode */
|
||||||
|
len = 2 * buffer_len(&encoded);
|
||||||
|
cp = xmalloc(len);
|
||||||
|
n = uuencode(buffer_ptr(&encoded), buffer_len(&encoded),
|
||||||
|
(char *)cp, len);
|
||||||
|
if (n < 0)
|
||||||
|
fatal("%s: uuencode", __func__);
|
||||||
|
|
||||||
|
buffer_clear(blob);
|
||||||
|
buffer_append(blob, MARK_BEGIN, sizeof(MARK_BEGIN) - 1);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
buffer_put_char(blob, cp[i]);
|
||||||
|
if (i % 70 == 69)
|
||||||
|
buffer_put_char(blob, '\n');
|
||||||
|
}
|
||||||
|
if (i % 70 != 69)
|
||||||
|
buffer_put_char(blob, '\n');
|
||||||
|
buffer_append(blob, MARK_END, sizeof(MARK_END) - 1);
|
||||||
|
free(cp);
|
||||||
|
|
||||||
|
return buffer_len(blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Key *
|
||||||
|
key_parse_private2(Buffer *blob, int type, const char *passphrase,
|
||||||
|
char **commentp)
|
||||||
|
{
|
||||||
|
u_char *key = NULL, *cp, *salt = NULL, pad, last;
|
||||||
|
char *comment = NULL, *ciphername = NULL, *kdfname = NULL, *kdfp;
|
||||||
|
u_int keylen = 0, ivlen, blocksize, slen, klen, len, rounds, nkeys;
|
||||||
|
u_int check1, check2, m1len, m2len;
|
||||||
|
size_t authlen;
|
||||||
|
const Cipher *c;
|
||||||
|
Buffer b, encoded, copy, kdf;
|
||||||
|
CipherContext ctx;
|
||||||
|
Key *k = NULL;
|
||||||
|
int dlen, ret, i;
|
||||||
|
|
||||||
|
buffer_init(&b);
|
||||||
|
buffer_init(&kdf);
|
||||||
|
buffer_init(&encoded);
|
||||||
|
buffer_init(©);
|
||||||
|
|
||||||
|
/* uudecode */
|
||||||
|
m1len = sizeof(MARK_BEGIN) - 1;
|
||||||
|
m2len = sizeof(MARK_END) - 1;
|
||||||
|
cp = buffer_ptr(blob);
|
||||||
|
len = buffer_len(blob);
|
||||||
|
if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) {
|
||||||
|
debug("%s: missing begin marker", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
cp += m1len;
|
||||||
|
len -= m1len;
|
||||||
|
while (len) {
|
||||||
|
if (*cp != '\n' && *cp != '\r')
|
||||||
|
buffer_put_char(&encoded, *cp);
|
||||||
|
last = *cp;
|
||||||
|
len--;
|
||||||
|
cp++;
|
||||||
|
if (last == '\n') {
|
||||||
|
if (len >= m2len && !memcmp(cp, MARK_END, m2len)) {
|
||||||
|
buffer_put_char(&encoded, '\0');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!len) {
|
||||||
|
debug("%s: no end marker", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
len = buffer_len(&encoded);
|
||||||
|
if ((cp = buffer_append_space(©, len)) == NULL) {
|
||||||
|
error("%s: buffer_append_space", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((dlen = uudecode(buffer_ptr(&encoded), cp, len)) < 0) {
|
||||||
|
error("%s: uudecode failed", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((u_int)dlen > len) {
|
||||||
|
error("%s: crazy uudecode length %d > %u", __func__, dlen, len);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
buffer_consume_end(©, len - dlen);
|
||||||
|
if (buffer_len(©) < sizeof(AUTH_MAGIC) ||
|
||||||
|
memcmp(buffer_ptr(©), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
|
||||||
|
error("%s: bad magic", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
buffer_consume(©, sizeof(AUTH_MAGIC));
|
||||||
|
|
||||||
|
ciphername = buffer_get_cstring_ret(©, NULL);
|
||||||
|
if (ciphername == NULL ||
|
||||||
|
(c = cipher_by_name(ciphername)) == NULL) {
|
||||||
|
error("%s: unknown cipher name", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((passphrase == NULL || !strlen(passphrase)) &&
|
||||||
|
strcmp(ciphername, "none") != 0) {
|
||||||
|
/* passphrase required */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
kdfname = buffer_get_cstring_ret(©, NULL);
|
||||||
|
if (kdfname == NULL ||
|
||||||
|
(!strcmp(kdfname, "none") && !strcmp(kdfname, "bcrypt"))) {
|
||||||
|
error("%s: unknown kdf name", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
|
||||||
|
error("%s: cipher %s requires kdf", __func__, ciphername);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* kdf options */
|
||||||
|
kdfp = buffer_get_string_ptr_ret(©, &klen);
|
||||||
|
if (kdfp == NULL) {
|
||||||
|
error("%s: kdf options not set", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (klen > 0) {
|
||||||
|
if ((cp = buffer_append_space(&kdf, klen)) == NULL) {
|
||||||
|
error("%s: kdf alloc failed", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
memcpy(cp, kdfp, klen);
|
||||||
|
}
|
||||||
|
/* number of keys */
|
||||||
|
if (buffer_get_int_ret(&nkeys, ©) < 0) {
|
||||||
|
error("%s: key counter missing", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (nkeys != 1) {
|
||||||
|
error("%s: only one key supported", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* pubkey */
|
||||||
|
if ((cp = buffer_get_string_ret(©, &len)) == NULL) {
|
||||||
|
error("%s: pubkey not found", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
free(cp); /* XXX check pubkey against decrypted private key */
|
||||||
|
|
||||||
|
/* size of encrypted key blob */
|
||||||
|
len = buffer_get_int(©);
|
||||||
|
blocksize = cipher_blocksize(c);
|
||||||
|
authlen = cipher_authlen(c);
|
||||||
|
if (len < blocksize) {
|
||||||
|
error("%s: encrypted data too small", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (len % blocksize) {
|
||||||
|
error("%s: length not multiple of blocksize", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup key */
|
||||||
|
keylen = cipher_keylen(c);
|
||||||
|
ivlen = cipher_ivlen(c);
|
||||||
|
key = xcalloc(1, keylen + ivlen);
|
||||||
|
if (!strcmp(kdfname, "bcrypt")) {
|
||||||
|
if ((salt = buffer_get_string_ret(&kdf, &slen)) == NULL) {
|
||||||
|
error("%s: salt not set", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (buffer_get_int_ret(&rounds, &kdf) < 0) {
|
||||||
|
error("%s: rounds not set", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
|
||||||
|
key, keylen + ivlen, rounds) < 0) {
|
||||||
|
error("%s: bcrypt_pbkdf failed", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = buffer_append_space(&b, len);
|
||||||
|
cipher_init(&ctx, c, key, keylen, key + keylen, ivlen, 0);
|
||||||
|
ret = cipher_crypt(&ctx, 0, cp, buffer_ptr(©), len, 0, authlen);
|
||||||
|
cipher_cleanup(&ctx);
|
||||||
|
buffer_consume(©, len);
|
||||||
|
|
||||||
|
/* fail silently on decryption errors */
|
||||||
|
if (ret != 0) {
|
||||||
|
debug("%s: decrypt failed", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_len(©) != 0) {
|
||||||
|
error("%s: key blob has trailing data (len = %u)", __func__,
|
||||||
|
buffer_len(©));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check bytes */
|
||||||
|
if (buffer_get_int_ret(&check1, &b) < 0 ||
|
||||||
|
buffer_get_int_ret(&check2, &b) < 0) {
|
||||||
|
error("check bytes missing");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (check1 != check2) {
|
||||||
|
debug("%s: decrypt failed: 0x%08x != 0x%08x", __func__,
|
||||||
|
check1, check2);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = key_private_deserialize(&b);
|
||||||
|
|
||||||
|
/* comment */
|
||||||
|
comment = buffer_get_cstring_ret(&b, NULL);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (buffer_len(&b)) {
|
||||||
|
if (buffer_get_char_ret(&pad, &b) == -1 ||
|
||||||
|
pad != (++i & 0xff)) {
|
||||||
|
error("%s: bad padding", __func__);
|
||||||
|
key_free(k);
|
||||||
|
k = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k && commentp) {
|
||||||
|
*commentp = comment;
|
||||||
|
comment = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX decode pubkey and check against private */
|
||||||
|
out:
|
||||||
|
free(ciphername);
|
||||||
|
free(kdfname);
|
||||||
|
free(salt);
|
||||||
|
free(comment);
|
||||||
|
if (key)
|
||||||
|
memset(key, 0, keylen + ivlen);
|
||||||
|
free(key);
|
||||||
|
buffer_free(&encoded);
|
||||||
|
buffer_free(©);
|
||||||
|
buffer_free(&kdf);
|
||||||
|
buffer_free(&b);
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Serialises the authentication (private) key to a blob, encrypting it with
|
* Serialises the authentication (private) key to a blob, encrypting it with
|
||||||
* passphrase. The identification of the blob (lowest 64 bits of n) will
|
* passphrase. The identification of the blob (lowest 64 bits of n) will
|
||||||
@ -149,8 +488,9 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
|
|||||||
|
|
||||||
cipher_set_key_string(&ciphercontext, cipher, passphrase,
|
cipher_set_key_string(&ciphercontext, cipher, passphrase,
|
||||||
CIPHER_ENCRYPT);
|
CIPHER_ENCRYPT);
|
||||||
cipher_crypt(&ciphercontext, 0, cp,
|
if (cipher_crypt(&ciphercontext, 0, cp,
|
||||||
buffer_ptr(&buffer), buffer_len(&buffer), 0, 0);
|
buffer_ptr(&buffer), buffer_len(&buffer), 0, 0) != 0)
|
||||||
|
fatal("%s: cipher_crypt failed", __func__);
|
||||||
cipher_cleanup(&ciphercontext);
|
cipher_cleanup(&ciphercontext);
|
||||||
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
||||||
|
|
||||||
@ -239,7 +579,8 @@ key_save_private_blob(Buffer *keybuf, const char *filename)
|
|||||||
/* Serialise "key" to buffer "blob" */
|
/* Serialise "key" to buffer "blob" */
|
||||||
static int
|
static int
|
||||||
key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
|
key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
|
||||||
const char *comment)
|
const char *comment, int force_new_format, const char *new_format_cipher,
|
||||||
|
int new_format_rounds)
|
||||||
{
|
{
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case KEY_RSA1:
|
case KEY_RSA1:
|
||||||
@ -247,6 +588,10 @@ key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
|
|||||||
case KEY_DSA:
|
case KEY_DSA:
|
||||||
case KEY_ECDSA:
|
case KEY_ECDSA:
|
||||||
case KEY_RSA:
|
case KEY_RSA:
|
||||||
|
if (force_new_format) {
|
||||||
|
return key_private_to_blob2(key, blob, passphrase,
|
||||||
|
comment, new_format_cipher, new_format_rounds);
|
||||||
|
}
|
||||||
return key_private_pem_to_blob(key, blob, passphrase, comment);
|
return key_private_pem_to_blob(key, blob, passphrase, comment);
|
||||||
default:
|
default:
|
||||||
error("%s: cannot save key type %d", __func__, key->type);
|
error("%s: cannot save key type %d", __func__, key->type);
|
||||||
@ -256,13 +601,15 @@ key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
|
|||||||
|
|
||||||
int
|
int
|
||||||
key_save_private(Key *key, const char *filename, const char *passphrase,
|
key_save_private(Key *key, const char *filename, const char *passphrase,
|
||||||
const char *comment)
|
const char *comment, int force_new_format, const char *new_format_cipher,
|
||||||
|
int new_format_rounds)
|
||||||
{
|
{
|
||||||
Buffer keyblob;
|
Buffer keyblob;
|
||||||
int success = 0;
|
int success = 0;
|
||||||
|
|
||||||
buffer_init(&keyblob);
|
buffer_init(&keyblob);
|
||||||
if (!key_private_to_blob(key, &keyblob, passphrase, comment))
|
if (!key_private_to_blob(key, &keyblob, passphrase, comment,
|
||||||
|
force_new_format, new_format_cipher, new_format_rounds))
|
||||||
goto out;
|
goto out;
|
||||||
if (!key_save_private_blob(&keyblob, filename))
|
if (!key_save_private_blob(&keyblob, filename))
|
||||||
goto out;
|
goto out;
|
||||||
@ -473,8 +820,9 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
|
|||||||
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
|
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
|
||||||
cipher_set_key_string(&ciphercontext, cipher, passphrase,
|
cipher_set_key_string(&ciphercontext, cipher, passphrase,
|
||||||
CIPHER_DECRYPT);
|
CIPHER_DECRYPT);
|
||||||
cipher_crypt(&ciphercontext, 0, cp,
|
if (cipher_crypt(&ciphercontext, 0, cp,
|
||||||
buffer_ptr(©), buffer_len(©), 0, 0);
|
buffer_ptr(©), buffer_len(©), 0, 0) != 0)
|
||||||
|
fatal("%s: cipher_crypt failed", __func__);
|
||||||
cipher_cleanup(&ciphercontext);
|
cipher_cleanup(&ciphercontext);
|
||||||
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
||||||
buffer_free(©);
|
buffer_free(©);
|
||||||
@ -641,6 +989,8 @@ static Key *
|
|||||||
key_parse_private_type(Buffer *blob, int type, const char *passphrase,
|
key_parse_private_type(Buffer *blob, int type, const char *passphrase,
|
||||||
char **commentp)
|
char **commentp)
|
||||||
{
|
{
|
||||||
|
Key *k;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case KEY_RSA1:
|
case KEY_RSA1:
|
||||||
return key_parse_private_rsa1(blob, passphrase, commentp);
|
return key_parse_private_rsa1(blob, passphrase, commentp);
|
||||||
@ -648,6 +998,8 @@ key_parse_private_type(Buffer *blob, int type, const char *passphrase,
|
|||||||
case KEY_ECDSA:
|
case KEY_ECDSA:
|
||||||
case KEY_RSA:
|
case KEY_RSA:
|
||||||
case KEY_UNSPEC:
|
case KEY_UNSPEC:
|
||||||
|
if ((k = key_parse_private2(blob, type, passphrase, commentp)))
|
||||||
|
return k;
|
||||||
return key_parse_private_pem(blob, type, passphrase, commentp);
|
return key_parse_private_pem(blob, type, passphrase, commentp);
|
||||||
default:
|
default:
|
||||||
error("%s: cannot parse key type %d", __func__, type);
|
error("%s: cannot parse key type %d", __func__, type);
|
||||||
@ -943,4 +1295,3 @@ key_in_file(Key *key, const char *filename, int strict_type)
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: authfile.h,v 1.16 2011/05/04 21:15:29 djm Exp $ */
|
/* $OpenBSD: authfile.h,v 1.17 2013/12/06 13:34:54 markus Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -15,7 +15,8 @@
|
|||||||
#ifndef AUTHFILE_H
|
#ifndef AUTHFILE_H
|
||||||
#define AUTHFILE_H
|
#define AUTHFILE_H
|
||||||
|
|
||||||
int key_save_private(Key *, const char *, const char *, const char *);
|
int key_save_private(Key *, const char *, const char *, const char *,
|
||||||
|
int, const char *, int);
|
||||||
int key_load_file(int, const char *, Buffer *);
|
int key_load_file(int, const char *, Buffer *);
|
||||||
Key *key_load_cert(const char *);
|
Key *key_load_cert(const char *);
|
||||||
Key *key_load_public(const char *, char **);
|
Key *key_load_public(const char *, char **);
|
||||||
|
18
cipher.c
18
cipher.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cipher.c,v 1.92 2013/12/02 03:13:14 djm Exp $ */
|
/* $OpenBSD: cipher.c,v 1.93 2013/12/06 13:34:54 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -344,17 +344,16 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
|
|||||||
* Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
|
* Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
|
||||||
* This tag is written on encryption and verified on decryption.
|
* This tag is written on encryption and verified on decryption.
|
||||||
* Both 'aadlen' and 'authlen' can be set to 0.
|
* Both 'aadlen' and 'authlen' can be set to 0.
|
||||||
|
* cipher_crypt() returns 0 on success and -1 if the decryption integrity
|
||||||
|
* check fails.
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
|
cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
|
||||||
u_int len, u_int aadlen, u_int authlen)
|
u_int len, u_int aadlen, u_int authlen)
|
||||||
{
|
{
|
||||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
|
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
|
||||||
if (chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, aadlen,
|
return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len,
|
||||||
authlen, cc->encrypt) != 0)
|
aadlen, authlen, cc->encrypt);
|
||||||
fatal("Decryption integrity check failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (authlen) {
|
if (authlen) {
|
||||||
u_char lastiv[1];
|
u_char lastiv[1];
|
||||||
|
|
||||||
@ -387,13 +386,14 @@ cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
|
|||||||
if (cc->encrypt)
|
if (cc->encrypt)
|
||||||
fatal("%s: EVP_Cipher(final) failed", __func__);
|
fatal("%s: EVP_Cipher(final) failed", __func__);
|
||||||
else
|
else
|
||||||
fatal("Decryption integrity check failed");
|
return -1;
|
||||||
}
|
}
|
||||||
if (cc->encrypt &&
|
if (cc->encrypt &&
|
||||||
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
|
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
|
||||||
authlen, dest + aadlen + len))
|
authlen, dest + aadlen + len))
|
||||||
fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__);
|
fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract the packet length, including any decryption necessary beforehand */
|
/* Extract the packet length, including any decryption necessary beforehand */
|
||||||
|
4
cipher.h
4
cipher.h
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cipher.h,v 1.42 2013/11/21 00:45:44 djm Exp $ */
|
/* $OpenBSD: cipher.h,v 1.43 2013/12/06 13:34:54 markus Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -81,7 +81,7 @@ int ciphers_valid(const char *);
|
|||||||
char *cipher_alg_list(char, int);
|
char *cipher_alg_list(char, int);
|
||||||
void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int,
|
void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int,
|
||||||
const u_char *, u_int, int);
|
const u_char *, u_int, int);
|
||||||
void cipher_crypt(CipherContext *, u_int, u_char *, const u_char *,
|
int cipher_crypt(CipherContext *, u_int, u_char *, const u_char *,
|
||||||
u_int, u_int, u_int);
|
u_int, u_int, u_int);
|
||||||
int cipher_get_length(CipherContext *, u_int *, u_int,
|
int cipher_get_length(CipherContext *, u_int *, u_int,
|
||||||
const u_char *, u_int);
|
const u_char *, u_int);
|
||||||
|
3
key.c
3
key.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: key.c,v 1.107 2013/12/06 13:30:08 markus Exp $ */
|
/* $OpenBSD: key.c,v 1.108 2013/12/06 13:34:54 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* read_bignum():
|
* read_bignum():
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -1892,6 +1892,7 @@ key_certify(Key *k, Key *ca)
|
|||||||
if (!key_cert_is_legacy(k))
|
if (!key_cert_is_legacy(k))
|
||||||
buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
|
buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
|
||||||
|
|
||||||
|
/* XXX this substantially duplicates to_blob(); refactor */
|
||||||
switch (k->type) {
|
switch (k->type) {
|
||||||
case KEY_DSA_CERT_V00:
|
case KEY_DSA_CERT_V00:
|
||||||
case KEY_DSA_CERT:
|
case KEY_DSA_CERT:
|
||||||
|
27
packet.c
27
packet.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: packet.c,v 1.190 2013/11/21 00:45:44 djm Exp $ */
|
/* $OpenBSD: packet.c,v 1.191 2013/12/06 13:34:54 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -713,9 +713,10 @@ packet_send1(void)
|
|||||||
buffer_append(&active_state->output, buf, 4);
|
buffer_append(&active_state->output, buf, 4);
|
||||||
cp = buffer_append_space(&active_state->output,
|
cp = buffer_append_space(&active_state->output,
|
||||||
buffer_len(&active_state->outgoing_packet));
|
buffer_len(&active_state->outgoing_packet));
|
||||||
cipher_crypt(&active_state->send_context, 0, cp,
|
if (cipher_crypt(&active_state->send_context, 0, cp,
|
||||||
buffer_ptr(&active_state->outgoing_packet),
|
buffer_ptr(&active_state->outgoing_packet),
|
||||||
buffer_len(&active_state->outgoing_packet), 0, 0);
|
buffer_len(&active_state->outgoing_packet), 0, 0) != 0)
|
||||||
|
fatal("%s: cipher_crypt failed", __func__);
|
||||||
|
|
||||||
#ifdef PACKET_DEBUG
|
#ifdef PACKET_DEBUG
|
||||||
fprintf(stderr, "encrypted: ");
|
fprintf(stderr, "encrypted: ");
|
||||||
@ -946,9 +947,10 @@ packet_send2_wrapped(void)
|
|||||||
}
|
}
|
||||||
/* encrypt packet and append to output buffer. */
|
/* encrypt packet and append to output buffer. */
|
||||||
cp = buffer_append_space(&active_state->output, len + authlen);
|
cp = buffer_append_space(&active_state->output, len + authlen);
|
||||||
cipher_crypt(&active_state->send_context, active_state->p_send.seqnr,
|
if (cipher_crypt(&active_state->send_context, active_state->p_send.seqnr,
|
||||||
cp, buffer_ptr(&active_state->outgoing_packet),
|
cp, buffer_ptr(&active_state->outgoing_packet),
|
||||||
len - aadlen, aadlen, authlen);
|
len - aadlen, aadlen, authlen) != 0)
|
||||||
|
fatal("%s: cipher_crypt failed", __func__);
|
||||||
/* append unencrypted MAC */
|
/* append unencrypted MAC */
|
||||||
if (mac && mac->enabled) {
|
if (mac && mac->enabled) {
|
||||||
if (mac->etm) {
|
if (mac->etm) {
|
||||||
@ -1208,8 +1210,9 @@ packet_read_poll1(void)
|
|||||||
/* Decrypt data to incoming_packet. */
|
/* Decrypt data to incoming_packet. */
|
||||||
buffer_clear(&active_state->incoming_packet);
|
buffer_clear(&active_state->incoming_packet);
|
||||||
cp = buffer_append_space(&active_state->incoming_packet, padded_len);
|
cp = buffer_append_space(&active_state->incoming_packet, padded_len);
|
||||||
cipher_crypt(&active_state->receive_context, 0, cp,
|
if (cipher_crypt(&active_state->receive_context, 0, cp,
|
||||||
buffer_ptr(&active_state->input), padded_len, 0, 0);
|
buffer_ptr(&active_state->input), padded_len, 0, 0) != 0)
|
||||||
|
fatal("%s: cipher_crypt failed", __func__);
|
||||||
|
|
||||||
buffer_consume(&active_state->input, padded_len);
|
buffer_consume(&active_state->input, padded_len);
|
||||||
|
|
||||||
@ -1304,9 +1307,10 @@ packet_read_poll2(u_int32_t *seqnr_p)
|
|||||||
buffer_clear(&active_state->incoming_packet);
|
buffer_clear(&active_state->incoming_packet);
|
||||||
cp = buffer_append_space(&active_state->incoming_packet,
|
cp = buffer_append_space(&active_state->incoming_packet,
|
||||||
block_size);
|
block_size);
|
||||||
cipher_crypt(&active_state->receive_context,
|
if (cipher_crypt(&active_state->receive_context,
|
||||||
active_state->p_read.seqnr, cp,
|
active_state->p_read.seqnr, cp,
|
||||||
buffer_ptr(&active_state->input), block_size, 0, 0);
|
buffer_ptr(&active_state->input), block_size, 0, 0) != 0)
|
||||||
|
fatal("Decryption integrity check failed");
|
||||||
cp = buffer_ptr(&active_state->incoming_packet);
|
cp = buffer_ptr(&active_state->incoming_packet);
|
||||||
active_state->packlen = get_u32(cp);
|
active_state->packlen = get_u32(cp);
|
||||||
if (active_state->packlen < 1 + 4 ||
|
if (active_state->packlen < 1 + 4 ||
|
||||||
@ -1360,9 +1364,10 @@ packet_read_poll2(u_int32_t *seqnr_p)
|
|||||||
macbuf = mac_compute(mac, active_state->p_read.seqnr,
|
macbuf = mac_compute(mac, active_state->p_read.seqnr,
|
||||||
buffer_ptr(&active_state->input), aadlen + need);
|
buffer_ptr(&active_state->input), aadlen + need);
|
||||||
cp = buffer_append_space(&active_state->incoming_packet, aadlen + need);
|
cp = buffer_append_space(&active_state->incoming_packet, aadlen + need);
|
||||||
cipher_crypt(&active_state->receive_context,
|
if (cipher_crypt(&active_state->receive_context,
|
||||||
active_state->p_read.seqnr, cp,
|
active_state->p_read.seqnr, cp,
|
||||||
buffer_ptr(&active_state->input), need, aadlen, authlen);
|
buffer_ptr(&active_state->input), need, aadlen, authlen) != 0)
|
||||||
|
fatal("Decryption integrity check failed");
|
||||||
buffer_consume(&active_state->input, aadlen + need + authlen);
|
buffer_consume(&active_state->input, aadlen + need + authlen);
|
||||||
/*
|
/*
|
||||||
* compute MAC over seqnr and packet,
|
* compute MAC over seqnr and packet,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-agent.c,v 1.178 2013/12/06 13:30:08 markus Exp $ */
|
/* $OpenBSD: ssh-agent.c,v 1.179 2013/12/06 13:34:54 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -484,7 +484,6 @@ process_add_identity(SocketEntry *e, int version)
|
|||||||
/* Generate additional parameters */
|
/* Generate additional parameters */
|
||||||
rsa_generate_additional_parameters(k->rsa);
|
rsa_generate_additional_parameters(k->rsa);
|
||||||
|
|
||||||
/* enable blinding */
|
|
||||||
if (RSA_blinding_on(k->rsa, NULL) != 1) {
|
if (RSA_blinding_on(k->rsa, NULL) != 1) {
|
||||||
error("process_add_identity: RSA_blinding_on failed");
|
error("process_add_identity: RSA_blinding_on failed");
|
||||||
key_free(k);
|
key_free(k);
|
||||||
|
51
ssh-keygen.c
51
ssh-keygen.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-keygen.c,v 1.236 2013/12/06 03:40:51 djm Exp $ */
|
/* $OpenBSD: ssh-keygen.c,v 1.237 2013/12/06 13:34:54 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -150,6 +150,18 @@ char *key_type_name = NULL;
|
|||||||
/* Load key from this PKCS#11 provider */
|
/* Load key from this PKCS#11 provider */
|
||||||
char *pkcs11provider = NULL;
|
char *pkcs11provider = NULL;
|
||||||
|
|
||||||
|
/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */
|
||||||
|
int use_new_format = 0;
|
||||||
|
|
||||||
|
/* Cipher for new-format private keys */
|
||||||
|
char *new_format_cipher = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of KDF rounds to derive new format keys /
|
||||||
|
* number of primality trials when screening moduli.
|
||||||
|
*/
|
||||||
|
int rounds = 0;
|
||||||
|
|
||||||
/* argv0 */
|
/* argv0 */
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
@ -923,7 +935,8 @@ do_gen_all_hostkeys(struct passwd *pw)
|
|||||||
public = key_from_private(private);
|
public = key_from_private(private);
|
||||||
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
|
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
|
||||||
hostname);
|
hostname);
|
||||||
if (!key_save_private(private, identity_file, "", comment)) {
|
if (!key_save_private(private, identity_file, "", comment,
|
||||||
|
use_new_format, new_format_cipher, rounds)) {
|
||||||
printf("Saving the key failed: %s.\n", identity_file);
|
printf("Saving the key failed: %s.\n", identity_file);
|
||||||
key_free(private);
|
key_free(private);
|
||||||
key_free(public);
|
key_free(public);
|
||||||
@ -1275,7 +1288,8 @@ do_change_passphrase(struct passwd *pw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Save the file using the new passphrase. */
|
/* Save the file using the new passphrase. */
|
||||||
if (!key_save_private(private, identity_file, passphrase1, comment)) {
|
if (!key_save_private(private, identity_file, passphrase1, comment,
|
||||||
|
use_new_format, new_format_cipher, rounds)) {
|
||||||
printf("Saving the key failed: %s.\n", identity_file);
|
printf("Saving the key failed: %s.\n", identity_file);
|
||||||
memset(passphrase1, 0, strlen(passphrase1));
|
memset(passphrase1, 0, strlen(passphrase1));
|
||||||
free(passphrase1);
|
free(passphrase1);
|
||||||
@ -1385,7 +1399,8 @@ do_change_comment(struct passwd *pw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Save the file using the new passphrase. */
|
/* Save the file using the new passphrase. */
|
||||||
if (!key_save_private(private, identity_file, passphrase, new_comment)) {
|
if (!key_save_private(private, identity_file, passphrase, new_comment,
|
||||||
|
use_new_format, new_format_cipher, rounds)) {
|
||||||
printf("Saving the key failed: %s.\n", identity_file);
|
printf("Saving the key failed: %s.\n", identity_file);
|
||||||
memset(passphrase, 0, strlen(passphrase));
|
memset(passphrase, 0, strlen(passphrase));
|
||||||
free(passphrase);
|
free(passphrase);
|
||||||
@ -2132,7 +2147,7 @@ usage(void)
|
|||||||
fprintf(stderr, "usage: %s [options]\n", __progname);
|
fprintf(stderr, "usage: %s [options]\n", __progname);
|
||||||
fprintf(stderr, "Options:\n");
|
fprintf(stderr, "Options:\n");
|
||||||
fprintf(stderr, " -A Generate non-existent host keys for all key types.\n");
|
fprintf(stderr, " -A Generate non-existent host keys for all key types.\n");
|
||||||
fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n");
|
fprintf(stderr, " -a number Number of KDF rounds for new key format or moduli primality tests.\n");
|
||||||
fprintf(stderr, " -B Show bubblebabble digest of key file.\n");
|
fprintf(stderr, " -B Show bubblebabble digest of key file.\n");
|
||||||
fprintf(stderr, " -b bits Number of bits in the key to create.\n");
|
fprintf(stderr, " -b bits Number of bits in the key to create.\n");
|
||||||
fprintf(stderr, " -C comment Provide new comment.\n");
|
fprintf(stderr, " -C comment Provide new comment.\n");
|
||||||
@ -2160,6 +2175,7 @@ usage(void)
|
|||||||
fprintf(stderr, " -N phrase Provide new passphrase.\n");
|
fprintf(stderr, " -N phrase Provide new passphrase.\n");
|
||||||
fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
|
fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
|
||||||
fprintf(stderr, " -O option Specify a certificate option.\n");
|
fprintf(stderr, " -O option Specify a certificate option.\n");
|
||||||
|
fprintf(stderr, " -o Enforce new private key format.\n");
|
||||||
fprintf(stderr, " -P phrase Provide old passphrase.\n");
|
fprintf(stderr, " -P phrase Provide old passphrase.\n");
|
||||||
fprintf(stderr, " -p Change passphrase of private key file.\n");
|
fprintf(stderr, " -p Change passphrase of private key file.\n");
|
||||||
fprintf(stderr, " -Q Test whether key(s) are revoked in KRL.\n");
|
fprintf(stderr, " -Q Test whether key(s) are revoked in KRL.\n");
|
||||||
@ -2176,6 +2192,7 @@ usage(void)
|
|||||||
fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
|
fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
|
||||||
fprintf(stderr, " -y Read private key file and print public key.\n");
|
fprintf(stderr, " -y Read private key file and print public key.\n");
|
||||||
fprintf(stderr, " -z serial Specify a serial number.\n");
|
fprintf(stderr, " -z serial Specify a serial number.\n");
|
||||||
|
fprintf(stderr, " -Z cipher Specify a cipher for new private key format.\n");
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -2193,7 +2210,7 @@ main(int argc, char **argv)
|
|||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int opt, type, fd;
|
int opt, type, fd;
|
||||||
u_int32_t memory = 0, generator_wanted = 0, trials = 100;
|
u_int32_t memory = 0, generator_wanted = 0;
|
||||||
int do_gen_candidates = 0, do_screen_candidates = 0;
|
int do_gen_candidates = 0, do_screen_candidates = 0;
|
||||||
int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
|
int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
|
||||||
unsigned long start_lineno = 0, lines_to_process = 0;
|
unsigned long start_lineno = 0, lines_to_process = 0;
|
||||||
@ -2225,9 +2242,9 @@ main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remaining characters: EUYZdow */
|
/* Remaining characters: EUYdw */
|
||||||
while ((opt = getopt(argc, argv, "ABHLQXceghiklpquvxy"
|
while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
|
||||||
"C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:a:b:f:j:m:n:r:s:t:z:")) != -1) {
|
"C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'A':
|
case 'A':
|
||||||
gen_all_hostkeys = 1;
|
gen_all_hostkeys = 1;
|
||||||
@ -2285,6 +2302,9 @@ main(int argc, char **argv)
|
|||||||
case 'n':
|
case 'n':
|
||||||
cert_principals = optarg;
|
cert_principals = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'o':
|
||||||
|
use_new_format = 1;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
change_passphrase = 1;
|
change_passphrase = 1;
|
||||||
break;
|
break;
|
||||||
@ -2312,6 +2332,9 @@ main(int argc, char **argv)
|
|||||||
case 'O':
|
case 'O':
|
||||||
add_cert_option(optarg);
|
add_cert_option(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'Z':
|
||||||
|
new_format_cipher = optarg;
|
||||||
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
identity_comment = optarg;
|
identity_comment = optarg;
|
||||||
break;
|
break;
|
||||||
@ -2370,9 +2393,9 @@ main(int argc, char **argv)
|
|||||||
optarg, errstr);
|
optarg, errstr);
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
trials = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
|
rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr);
|
||||||
if (errstr)
|
if (errstr)
|
||||||
fatal("Invalid number of trials: %s (%s)",
|
fatal("Invalid number: %s (%s)",
|
||||||
optarg, errstr);
|
optarg, errstr);
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
@ -2531,7 +2554,8 @@ main(int argc, char **argv)
|
|||||||
fatal("Couldn't open moduli file \"%s\": %s",
|
fatal("Couldn't open moduli file \"%s\": %s",
|
||||||
out_file, strerror(errno));
|
out_file, strerror(errno));
|
||||||
}
|
}
|
||||||
if (prime_test(in, out, trials, generator_wanted, checkpoint,
|
if (prime_test(in, out, rounds == 0 ? 100 : rounds,
|
||||||
|
generator_wanted, checkpoint,
|
||||||
start_lineno, lines_to_process) != 0)
|
start_lineno, lines_to_process) != 0)
|
||||||
fatal("modulus screening failed");
|
fatal("modulus screening failed");
|
||||||
return (0);
|
return (0);
|
||||||
@ -2623,7 +2647,8 @@ passphrase_again:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Save the key with the given passphrase and comment. */
|
/* Save the key with the given passphrase and comment. */
|
||||||
if (!key_save_private(private, identity_file, passphrase1, comment)) {
|
if (!key_save_private(private, identity_file, passphrase1, comment,
|
||||||
|
use_new_format, new_format_cipher, rounds)) {
|
||||||
printf("Saving the key failed: %s.\n", identity_file);
|
printf("Saving the key failed: %s.\n", identity_file);
|
||||||
memset(passphrase1, 0, strlen(passphrase1));
|
memset(passphrase1, 0, strlen(passphrase1));
|
||||||
free(passphrase1);
|
free(passphrase1);
|
||||||
|
Loading…
Reference in New Issue
Block a user