version 1.2, 1999/09/26 21:02:15 |
version 1.3, 1999/09/28 04:45:35 |
|
|
#include "includes.h" |
#include "includes.h" |
RCSID("$Id$"); |
RCSID("$Id$"); |
|
|
#include <gmp.h> |
#include <ssl/bn.h> |
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "buffer.h" |
#include "buffer.h" |
#include "bufaux.h" |
#include "bufaux.h" |
|
|
will precede the key to provide identification of the key without |
will precede the key to provide identification of the key without |
needing a passphrase. */ |
needing a passphrase. */ |
|
|
int save_private_key(const char *filename, const char *passphrase, |
int |
RSAPrivateKey *key, const char *comment, |
save_private_key(const char *filename, const char *passphrase, |
RandomState *state) |
RSA *key, const char *comment) |
{ |
{ |
Buffer buffer, encrypted; |
Buffer buffer, encrypted; |
char buf[100], *cp; |
char buf[100], *cp; |
int f, i; |
int f, i; |
CipherContext cipher; |
CipherContext cipher; |
int cipher_type; |
int cipher_type; |
|
u_int32_t rand; |
|
|
/* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting to |
/* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting to |
another cipher; otherwise use SSH_AUTHFILE_CIPHER. */ |
another cipher; otherwise use SSH_AUTHFILE_CIPHER. */ |
|
|
buffer_init(&buffer); |
buffer_init(&buffer); |
|
|
/* Put checkbytes for checking passphrase validity. */ |
/* Put checkbytes for checking passphrase validity. */ |
buf[0] = random_get_byte(state); |
rand = arc4random(); |
buf[1] = random_get_byte(state); |
buf[0] = rand & 0xff; |
|
buf[1] = (rand >> 8) & 0xff; |
buf[2] = buf[0]; |
buf[2] = buf[0]; |
buf[3] = buf[1]; |
buf[3] = buf[1]; |
buffer_append(&buffer, buf, 4); |
buffer_append(&buffer, buf, 4); |
|
|
/* Store the private key (n and e will not be stored because they will |
/* Store the private key (n and e will not be stored because they will |
be stored in plain text, and storing them also in encrypted format |
be stored in plain text, and storing them also in encrypted format |
would just give known plaintext). */ |
would just give known plaintext). */ |
buffer_put_mp_int(&buffer, &key->d); |
buffer_put_bignum(&buffer, key->d); |
buffer_put_mp_int(&buffer, &key->u); |
buffer_put_bignum(&buffer, key->iqmp); |
buffer_put_mp_int(&buffer, &key->p); |
buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */ |
buffer_put_mp_int(&buffer, &key->q); |
buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */ |
|
|
/* Pad the part to be encrypted until its size is a multiple of 8. */ |
/* Pad the part to be encrypted until its size is a multiple of 8. */ |
while (buffer_len(&buffer) % 8 != 0) |
while (buffer_len(&buffer) % 8 != 0) |
|
|
buffer_put_int(&encrypted, 0); /* For future extension */ |
buffer_put_int(&encrypted, 0); /* For future extension */ |
|
|
/* Store public key. This will be in plain text. */ |
/* Store public key. This will be in plain text. */ |
buffer_put_int(&encrypted, key->bits); |
buffer_put_int(&encrypted, BN_num_bits(key->n)); |
buffer_put_mp_int(&encrypted, &key->n); |
buffer_put_bignum(&encrypted, key->n); |
buffer_put_mp_int(&encrypted, &key->e); |
buffer_put_bignum(&encrypted, key->e); |
buffer_put_string(&encrypted, comment, strlen(comment)); |
buffer_put_string(&encrypted, comment, strlen(comment)); |
|
|
/* Allocate space for the private part of the key in the buffer. */ |
/* Allocate space for the private part of the key in the buffer. */ |
|
|
was encountered (the file does not exist or is not readable), and |
was encountered (the file does not exist or is not readable), and |
non-zero otherwise. */ |
non-zero otherwise. */ |
|
|
int load_public_key(const char *filename, RSAPublicKey *pub, |
int |
char **comment_return) |
load_public_key(const char *filename, RSA *pub, |
|
char **comment_return) |
{ |
{ |
int f, i; |
int f, i; |
unsigned long len; |
unsigned long len; |
|
|
(void)buffer_get_int(&buffer); /* reserved */ |
(void)buffer_get_int(&buffer); /* reserved */ |
|
|
/* Read the public key from the buffer. */ |
/* Read the public key from the buffer. */ |
pub->bits = buffer_get_int(&buffer); |
buffer_get_int(&buffer); |
mpz_init(&pub->n); |
pub->n = BN_new(); |
buffer_get_mp_int(&buffer, &pub->n); |
buffer_get_bignum(&buffer, pub->n); |
mpz_init(&pub->e); |
pub->e = BN_new(); |
buffer_get_mp_int(&buffer, &pub->e); |
buffer_get_bignum(&buffer, pub->e); |
if (comment_return) |
if (comment_return) |
*comment_return = buffer_get_string(&buffer, NULL); |
*comment_return = buffer_get_string(&buffer, NULL); |
/* The encrypted private part is not parsed by this function. */ |
/* The encrypted private part is not parsed by this function. */ |
|
|
(file does not exist or is not readable, or passphrase is bad). |
(file does not exist or is not readable, or passphrase is bad). |
This initializes the private key. */ |
This initializes the private key. */ |
|
|
int load_private_key(const char *filename, const char *passphrase, |
int |
RSAPrivateKey *prv, char **comment_return) |
load_private_key(const char *filename, const char *passphrase, |
|
RSA *prv, char **comment_return) |
{ |
{ |
int f, i, check1, check2, cipher_type; |
int f, i, check1, check2, cipher_type; |
unsigned long len; |
unsigned long len; |
Buffer buffer, decrypted; |
Buffer buffer, decrypted; |
char *cp; |
char *cp; |
CipherContext cipher; |
CipherContext cipher; |
|
BN_CTX *ctx; |
|
BIGNUM *aux; |
|
|
/* Read the file into the buffer. */ |
/* Read the file into the buffer. */ |
f = open(filename, O_RDONLY); |
f = open(filename, O_RDONLY); |
|
|
(void)buffer_get_int(&buffer); /* Reserved data. */ |
(void)buffer_get_int(&buffer); /* Reserved data. */ |
|
|
/* Read the public key from the buffer. */ |
/* Read the public key from the buffer. */ |
prv->bits = buffer_get_int(&buffer); |
buffer_get_int(&buffer); |
mpz_init(&prv->n); |
prv->n = BN_new(); |
buffer_get_mp_int(&buffer, &prv->n); |
buffer_get_bignum(&buffer, prv->n); |
mpz_init(&prv->e); |
prv->e = BN_new(); |
buffer_get_mp_int(&buffer, &prv->e); |
buffer_get_bignum(&buffer, prv->e); |
if (comment_return) |
if (comment_return) |
*comment_return = buffer_get_string(&buffer, NULL); |
*comment_return = buffer_get_string(&buffer, NULL); |
else |
else |
|
|
/* Bad passphrase. */ |
/* Bad passphrase. */ |
buffer_free(&decrypted); |
buffer_free(&decrypted); |
fail: |
fail: |
mpz_clear(&prv->n); |
BN_clear_free(prv->n); |
mpz_clear(&prv->e); |
BN_clear_free(prv->e); |
if (comment_return) |
if (comment_return) |
xfree(*comment_return); |
xfree(*comment_return); |
return 0; |
return 0; |
} |
} |
|
|
/* Read the rest of the private key. */ |
/* Read the rest of the private key. */ |
mpz_init(&prv->d); |
prv->d = BN_new(); |
buffer_get_mp_int(&decrypted, &prv->d); |
buffer_get_bignum(&decrypted, prv->d); |
mpz_init(&prv->u); |
prv->iqmp = BN_new(); |
buffer_get_mp_int(&decrypted, &prv->u); |
buffer_get_bignum(&decrypted, prv->iqmp); /* u */ |
mpz_init(&prv->p); |
/* in SSL and SSH p and q are exchanged */ |
buffer_get_mp_int(&decrypted, &prv->p); |
prv->q = BN_new(); |
mpz_init(&prv->q); |
buffer_get_bignum(&decrypted, prv->q); /* p */ |
buffer_get_mp_int(&decrypted, &prv->q); |
prv->p = BN_new(); |
|
buffer_get_bignum(&decrypted, prv->p); /* q */ |
|
|
|
ctx = BN_CTX_new(); |
|
aux = BN_new(); |
|
|
|
BN_sub(aux, prv->q, BN_value_one()); |
|
prv->dmq1 = BN_new(); |
|
BN_mod(prv->dmq1, prv->d, aux, ctx); |
|
|
|
BN_sub(aux, prv->p, BN_value_one()); |
|
prv->dmp1 = BN_new(); |
|
BN_mod(prv->dmp1, prv->d, aux, ctx); |
|
|
|
BN_clear_free(aux); |
|
BN_CTX_free(ctx); |
|
|
buffer_free(&decrypted); |
buffer_free(&decrypted); |
|
|