*/
#include "includes.h"
-RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $");
+RCSID("$OpenBSD: authfile.c,v 1.22 2000/12/19 22:43:44 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
+#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
-#include "cipher.h"
#include "ssh.h"
#include "key.h"
*/
int
-save_private_key_rsa(const char *filename, const char *passphrase,
+save_private_key_rsa1(const char *filename, const char *passphrase,
RSA *key, const char *comment)
{
Buffer buffer, encrypted;
char buf[100], *cp;
int fd, i;
- CipherContext cipher;
- int cipher_type;
+ CipherContext ciphercontext;
+ Cipher *cipher;
u_int32_t rand;
/*
* to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
*/
if (strcmp(passphrase, "") == 0)
- cipher_type = SSH_CIPHER_NONE;
+ cipher = cipher_by_number(SSH_CIPHER_NONE);
else
- cipher_type = SSH_AUTHFILE_CIPHER;
+ cipher = cipher_by_number(SSH_AUTHFILE_CIPHER);
+ if (cipher == NULL)
+ fatal("save_private_key_rsa: bad cipher");
/* This buffer is used to built the secret part of the private key. */
buffer_init(&buffer);
buffer_put_char(&encrypted, 0);
/* Store cipher type. */
- buffer_put_char(&encrypted, cipher_type);
+ buffer_put_char(&encrypted, cipher->number);
buffer_put_int(&encrypted, 0); /* For future extension */
/* Store public key. This will be in plain text. */
/* Allocate space for the private part of the key in the buffer. */
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
- cipher_set_key_string(&cipher, cipher_type, passphrase);
- cipher_encrypt(&cipher, (unsigned char *) cp,
- (unsigned char *) buffer_ptr(&buffer),
- buffer_len(&buffer));
- memset(&cipher, 0, sizeof(cipher));
+ cipher_set_key_string(&ciphercontext, cipher, passphrase);
+ cipher_encrypt(&ciphercontext, (unsigned char *) cp,
+ (unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
+ memset(&ciphercontext, 0, sizeof(ciphercontext));
/* Destroy temporary data. */
memset(buf, 0, sizeof(buf));
strerror(errno));
buffer_free(&encrypted);
close(fd);
- remove(filename);
+ unlink(filename);
return 0;
}
close(fd);
return 1;
}
-/* save DSA key in OpenSSL PEM format */
-
+/* save SSH2 key in OpenSSL PEM format */
int
-save_private_key_dsa(const char *filename, const char *passphrase,
- DSA *dsa, const char *comment)
+save_private_key_ssh2(const char *filename, const char *_passphrase,
+ Key *key, const char *comment)
{
FILE *fp;
int fd;
- int success = 1;
- int len = strlen(passphrase);
+ int success = 0;
+ int len = strlen(_passphrase);
+ char *passphrase = (len > 0) ? (char *)_passphrase : NULL;
+ EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
if (len > 0 && len <= 4) {
error("passphrase too short: %d bytes", len);
close(fd);
return 0;
}
- if (len > 0) {
- if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(),
- (char *)passphrase, strlen(passphrase), NULL, NULL))
- success = 0;
- } else {
- if (!PEM_write_DSAPrivateKey(fp, dsa, NULL,
- NULL, 0, NULL, NULL))
- success = 0;
+ switch (key->type) {
+ case KEY_DSA:
+ success = PEM_write_DSAPrivateKey(fp, key->dsa,
+ cipher, passphrase, len, NULL, NULL);
+ break;
+ case KEY_RSA:
+ success = PEM_write_RSAPrivateKey(fp, key->rsa,
+ cipher, passphrase, len, NULL, NULL);
+ break;
}
fclose(fp);
return success;
const char *comment)
{
switch (key->type) {
- case KEY_RSA:
- return save_private_key_rsa(filename, passphrase, key->rsa, comment);
+ case KEY_RSA1:
+ return save_private_key_rsa1(filename, passphrase, key->rsa, comment);
break;
case KEY_DSA:
- return save_private_key_dsa(filename, passphrase, key->dsa, comment);
+ case KEY_RSA:
+ return save_private_key_ssh2(filename, passphrase, key, comment);
break;
default:
break;
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
- debug("Bad key file %.200s.", filename);
+ debug3("Bad RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
- debug("Bad key file %.200s.", filename);
+ debug3("Bad RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
load_public_key(const char *filename, Key * key, char **comment_return)
{
switch (key->type) {
- case KEY_RSA:
+ case KEY_RSA1:
return load_public_key_rsa(filename, key->rsa, comment_return);
break;
case KEY_DSA:
+ case KEY_RSA:
default:
break;
}
*/
int
-load_private_key_rsa(int fd, const char *filename,
+load_private_key_rsa1(int fd, const char *filename,
const char *passphrase, RSA * prv, char **comment_return)
{
int i, check1, check2, cipher_type;
off_t len;
Buffer buffer, decrypted;
char *cp;
- CipherContext cipher;
+ CipherContext ciphercontext;
+ Cipher *cipher;
BN_CTX *ctx;
BIGNUM *aux;
if (read(fd, cp, (size_t) len) != (size_t) len) {
debug("Read from key file %.200s failed: %.100s", filename,
- strerror(errno));
+ strerror(errno));
buffer_free(&buffer);
close(fd);
return 0;
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
- debug("Bad key file %.200s.", filename);
+ debug3("Bad RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
* from the buffer.
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
- if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
- debug("Bad key file %.200s.", filename);
+ if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
+ debug3("Bad RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
xfree(buffer_get_string(&buffer, NULL));
/* Check that it is a supported cipher. */
- if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
- (1 << cipher_type)) == 0) {
- debug("Unsupported cipher %.100s used in key file %.200s.",
- cipher_name(cipher_type), filename);
+ cipher = cipher_by_number(cipher_type);
+ if (cipher == NULL) {
+ debug("Unsupported cipher %d used in key file %.200s.",
+ cipher_type, filename);
buffer_free(&buffer);
goto fail;
}
buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
- cipher_set_key_string(&cipher, cipher_type, passphrase);
- cipher_decrypt(&cipher, (unsigned char *) cp,
- (unsigned char *) buffer_ptr(&buffer),
- buffer_len(&buffer));
-
+ cipher_set_key_string(&ciphercontext, cipher, passphrase);
+ cipher_decrypt(&ciphercontext, (unsigned char *) cp,
+ (unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
+ memset(&ciphercontext, 0, sizeof(ciphercontext));
buffer_free(&buffer);
check1 = buffer_get_char(&decrypted);
}
int
-load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return)
+load_private_key_ssh2(int fd, const char *passphrase, Key *k, char **comment_return)
{
- DSA *dsa;
- BIO *in;
FILE *fp;
+ int success = 0;
+ EVP_PKEY *pk = NULL;
+ char *name = "<no key>";
- in = BIO_new(BIO_s_file());
- if (in == NULL) {
- error("BIO_new failed");
- return 0;
- }
fp = fdopen(fd, "r");
if (fp == NULL) {
error("fdopen failed");
return 0;
}
- BIO_set_fp(in, fp, BIO_NOCLOSE);
- dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase);
- if (dsa == NULL) {
- debug("PEM_read_bio_DSAPrivateKey failed");
- } else {
+ pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
+ if (pk == NULL) {
+ debug("PEM_read_PrivateKey failed");
+ (void)ERR_get_error();
+ } else if (pk->type == EVP_PKEY_RSA) {
+ /* replace k->rsa with loaded key */
+ if (k->type == KEY_RSA || k->type == KEY_UNSPEC) {
+ if (k->rsa != NULL)
+ RSA_free(k->rsa);
+ k->rsa = EVP_PKEY_get1_RSA(pk);
+ k->type = KEY_RSA;
+ name = "rsa w/o comment";
+ success = 1;
+#ifdef DEBUG_PK
+ RSA_print_fp(stderr, k->rsa, 8);
+#endif
+ }
+ } else if (pk->type == EVP_PKEY_DSA) {
/* replace k->dsa with loaded key */
- DSA_free(k->dsa);
- k->dsa = dsa;
+ if (k->type == KEY_DSA || k->type == KEY_UNSPEC) {
+ if (k->dsa != NULL)
+ DSA_free(k->dsa);
+ k->dsa = EVP_PKEY_get1_DSA(pk);
+ k->type = KEY_DSA;
+ name = "dsa w/o comment";
+#ifdef DEBUG_PK
+ DSA_print_fp(stderr, k->dsa, 8);
+#endif
+ success = 1;
+ }
+ } else {
+ error("PEM_read_PrivateKey: mismatch or "
+ "unknown EVP_PKEY save_type %d", pk->save_type);
}
- BIO_free(in);
fclose(fp);
- if (comment_return)
- *comment_return = xstrdup("dsa w/o comment");
- debug("read DSA private key done");
-#ifdef DEBUG_DSS
- DSA_print_fp(stderr, dsa, 8);
-#endif
- return dsa != NULL ? 1 : 0;
+ if (pk != NULL)
+ EVP_PKEY_free(pk);
+ if (success && comment_return)
+ *comment_return = xstrdup(name);
+ debug("read SSH2 private key done: name %s success %d", name, success);
+ return success;
}
int
return 0;
}
switch (key->type) {
- case KEY_RSA:
+ case KEY_RSA1:
if (key->rsa->e != NULL) {
BN_clear_free(key->rsa->e);
key->rsa->e = NULL;
BN_clear_free(key->rsa->n);
key->rsa->n = NULL;
}
- ret = load_private_key_rsa(fd, filename, passphrase,
+ ret = load_private_key_rsa1(fd, filename, passphrase,
key->rsa, comment_return);
break;
case KEY_DSA:
- ret = load_private_key_dsa(fd, passphrase, key, comment_return);
+ case KEY_RSA:
+ case KEY_UNSPEC:
+ ret = load_private_key_ssh2(fd, passphrase, key, comment_return);
default:
break;
}
do_load_public_key(const char *filename, Key *k, char **commentp)
{
FILE *f;
- unsigned int bits;
char line[1024];
char *cp;
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
;
if (*cp) {
- bits = key_read(k, &cp);
- if (bits != 0) {
+ if (key_read(k, &cp) == 1) {
if (commentp)
*commentp=xstrdup(filename);
fclose(f);