keys.c   keys.c 
skipping to change at line 31 skipping to change at line 31
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef HAVE_LIBCRYPTO #ifdef HAVE_LIBCRYPTO
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#endif #endif
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/server.h"
#include "libssh/buffer.h"
#include "libssh/agent.h"
#include "libssh/session.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
/** \addtogroup ssh_auth /** \addtogroup ssh_auth
* @{ * @{
*/ */
/* Public key decoding functions */ /* Public key decoding functions */
const char *ssh_type_to_char(int type) { const char *ssh_type_to_char(int type) {
switch (type) { switch (type) {
case TYPE_DSS: case TYPE_DSS:
return "ssh-dss"; return "ssh-dss";
skipping to change at line 68 skipping to change at line 76
return TYPE_RSA1; return TYPE_RSA1;
} else if (strcmp(name, "ssh-rsa") == 0) { } else if (strcmp(name, "ssh-rsa") == 0) {
return TYPE_RSA; return TYPE_RSA;
} else if (strcmp(name, "ssh-dss") == 0) { } else if (strcmp(name, "ssh-dss") == 0) {
return TYPE_DSS; return TYPE_DSS;
} }
return -1; return -1;
} }
PUBLIC_KEY *publickey_make_dss(SSH_SESSION *session, BUFFER *buffer) { ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
STRING *p = NULL; ssh_string p = NULL;
STRING *q = NULL; ssh_string q = NULL;
STRING *g = NULL; ssh_string g = NULL;
STRING *pubkey = NULL; ssh_string pubkey = NULL;
PUBLIC_KEY *key = NULL; ssh_public_key key = NULL;
key = malloc(sizeof(PUBLIC_KEY)); key = malloc(sizeof(struct ssh_public_key_struct));
if (key == NULL) { if (key == NULL) {
buffer_free(buffer); buffer_free(buffer);
return NULL; return NULL;
} }
key->type = TYPE_DSS; key->type = TYPE_DSS;
key->type_c = ssh_type_to_char(key->type); key->type_c = ssh_type_to_char(key->type);
p = buffer_get_ssh_string(buffer); p = buffer_get_ssh_string(buffer);
q = buffer_get_ssh_string(buffer); q = buffer_get_ssh_string(buffer);
skipping to change at line 99 skipping to change at line 107
buffer_free(buffer); /* we don't need it anymore */ buffer_free(buffer); /* we don't need it anymore */
if (p == NULL || q == NULL || g == NULL || pubkey == NULL) { if (p == NULL || q == NULL || g == NULL || pubkey == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid DSA public key"); ssh_set_error(session, SSH_FATAL, "Invalid DSA public key");
goto error; goto error;
} }
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_build(&key->dsa_pub, NULL, gcry_sexp_build(&key->dsa_pub, NULL,
"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",
string_len(p), p->string, string_len(p), string_data(p),
string_len(q), q->string, string_len(q), string_data(q),
string_len(g), g->string, string_len(g), string_data(g),
string_len(pubkey), pubkey->string); string_len(pubkey), string_data(pubkey));
if (key->dsa_pub == NULL) { if (key->dsa_pub == NULL) {
goto error; goto error;
} }
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
key->dsa_pub = DSA_new(); key->dsa_pub = DSA_new();
if (key->dsa_pub == NULL) { if (key->dsa_pub == NULL) {
goto error; goto error;
} }
key->dsa_pub->p = make_string_bn(p); key->dsa_pub->p = make_string_bn(p);
skipping to change at line 154 skipping to change at line 162
string_free(q); string_free(q);
string_burn(g); string_burn(g);
string_free(g); string_free(g);
string_burn(pubkey); string_burn(pubkey);
string_free(pubkey); string_free(pubkey);
publickey_free(key); publickey_free(key);
return NULL; return NULL;
} }
PUBLIC_KEY *publickey_make_rsa(SSH_SESSION *session, BUFFER *buffer, ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
int type) { int type) {
STRING *e = NULL; ssh_string e = NULL;
STRING *n = NULL; ssh_string n = NULL;
PUBLIC_KEY *key = NULL; ssh_public_key key = NULL;
key = malloc(sizeof(PUBLIC_KEY)); key = malloc(sizeof(struct ssh_public_key_struct));
if (key == NULL) { if (key == NULL) {
buffer_free(buffer); buffer_free(buffer);
return NULL; return NULL;
} }
key->type = type; key->type = type;
key->type_c = ssh_type_to_char(key->type); key->type_c = ssh_type_to_char(key->type);
e = buffer_get_ssh_string(buffer); e = buffer_get_ssh_string(buffer);
n = buffer_get_ssh_string(buffer); n = buffer_get_ssh_string(buffer);
buffer_free(buffer); /* we don't need it anymore */ buffer_free(buffer); /* we don't need it anymore */
if(e == NULL || n == NULL) { if(e == NULL || n == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid RSA public key"); ssh_set_error(session, SSH_FATAL, "Invalid RSA public key");
goto error; goto error;
} }
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_build(&key->rsa_pub, NULL, gcry_sexp_build(&key->rsa_pub, NULL,
"(public-key(rsa(n %b)(e %b)))", "(public-key(rsa(n %b)(e %b)))",
string_len(n), n->string, string_len(n), string_data(n),
string_len(e),e->string); string_len(e),string_data(e));
if (key->rsa_pub == NULL) { if (key->rsa_pub == NULL) {
goto error; goto error;
} }
#elif HAVE_LIBCRYPTO #elif HAVE_LIBCRYPTO
key->rsa_pub = RSA_new(); key->rsa_pub = RSA_new();
if (key->rsa_pub == NULL) { if (key->rsa_pub == NULL) {
goto error; goto error;
} }
key->rsa_pub->e = make_string_bn(e); key->rsa_pub->e = make_string_bn(e);
skipping to change at line 221 skipping to change at line 229
error: error:
string_burn(e); string_burn(e);
string_free(e); string_free(e);
string_burn(n); string_burn(n);
string_free(n); string_free(n);
publickey_free(key); publickey_free(key);
return NULL; return NULL;
} }
void publickey_free(PUBLIC_KEY *key) { void publickey_free(ssh_public_key key) {
if (key == NULL) { if (key == NULL) {
return; return;
} }
switch(key->type) { switch(key->type) {
case TYPE_DSS: case TYPE_DSS:
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_release(key->dsa_pub); gcry_sexp_release(key->dsa_pub);
#elif HAVE_LIBCRYPTO #elif HAVE_LIBCRYPTO
DSA_free(key->dsa_pub); DSA_free(key->dsa_pub);
skipping to change at line 248 skipping to change at line 256
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
RSA_free(key->rsa_pub); RSA_free(key->rsa_pub);
#endif #endif
break; break;
default: default:
break; break;
} }
SAFE_FREE(key); SAFE_FREE(key);
} }
PUBLIC_KEY *publickey_from_string(SSH_SESSION *session, STRING *pubkey_s) { ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey
BUFFER *tmpbuf = NULL; _s) {
STRING *type_s = NULL; ssh_buffer tmpbuf = NULL;
ssh_string type_s = NULL;
char *type_c = NULL; char *type_c = NULL;
int type; int type;
tmpbuf = buffer_new(); tmpbuf = buffer_new();
if (tmpbuf == NULL) { if (tmpbuf == NULL) {
return NULL; return NULL;
} }
if (buffer_add_data(tmpbuf, pubkey_s->string, string_len(pubkey_s)) < 0) { if (buffer_add_data(tmpbuf, string_data(pubkey_s), string_len(pubkey_s)) < 0) {
goto error; goto error;
} }
type_s = buffer_get_ssh_string(tmpbuf); type_s = buffer_get_ssh_string(tmpbuf);
if (type_s == NULL) { if (type_s == NULL) {
ssh_set_error(session,SSH_FATAL,"Invalid public key format"); ssh_set_error(session,SSH_FATAL,"Invalid public key format");
goto error; goto error;
} }
type_c = string_to_char(type_s); type_c = string_to_char(type_s);
skipping to change at line 299 skipping to change at line 307
error: error:
buffer_free(tmpbuf); buffer_free(tmpbuf);
return NULL; return NULL;
} }
/** \brief Makes a PUBLIC_KEY object out of a PRIVATE_KEY object /** \brief Makes a PUBLIC_KEY object out of a PRIVATE_KEY object
* \param prv the Private key * \param prv the Private key
* \returns the public key * \returns the public key
* \see publickey_to_string() * \see publickey_to_string()
*/ */
PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv) { ssh_public_key publickey_from_privatekey(ssh_private_key prv) {
PUBLIC_KEY *key = NULL; ssh_public_key key = NULL;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_t sexp; gcry_sexp_t sexp;
const char *tmp = NULL; const char *tmp = NULL;
size_t size; size_t size;
STRING *p = NULL; ssh_string p = NULL;
STRING *q = NULL; ssh_string q = NULL;
STRING *g = NULL; ssh_string g = NULL;
STRING *y = NULL; ssh_string y = NULL;
STRING *e = NULL; ssh_string e = NULL;
STRING *n = NULL; ssh_string n = NULL;
#endif /* HAVE_LIBGCRYPT */ #endif /* HAVE_LIBGCRYPT */
key = malloc(sizeof(PUBLIC_KEY)); key = malloc(sizeof(struct ssh_public_key_struct));
if (key == NULL) { if (key == NULL) {
return NULL; return NULL;
} }
key->type = prv->type; key->type = prv->type;
switch(key->type) { switch(key->type) {
case TYPE_DSS: case TYPE_DSS:
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
sexp = gcry_sexp_find_token(prv->dsa_priv, "p", 0); sexp = gcry_sexp_find_token(prv->dsa_priv, "p", 0);
if (sexp == NULL) { if (sexp == NULL) {
skipping to change at line 372 skipping to change at line 380
tmp = gcry_sexp_nth_data(sexp,1,&size); tmp = gcry_sexp_nth_data(sexp,1,&size);
y = string_new(size); y = string_new(size);
if (y == NULL) { if (y == NULL) {
goto error; goto error;
} }
string_fill(y,(char *) tmp,size); string_fill(y,(char *) tmp,size);
gcry_sexp_release(sexp); gcry_sexp_release(sexp);
gcry_sexp_build(&key->dsa_pub, NULL, gcry_sexp_build(&key->dsa_pub, NULL,
"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",
string_len(p), p->string, string_len(p), string_data(p),
string_len(q), q->string, string_len(q), string_data(q),
string_len(g), g->string, string_len(g), string_data(g),
string_len(y), y->string); string_len(y), string_data(y));
string_burn(p); string_burn(p);
string_free(p); string_free(p);
string_burn(q); string_burn(q);
string_free(q); string_free(q);
string_burn(g); string_burn(g);
string_free(g); string_free(g);
string_burn(y); string_burn(y);
string_free(y); string_free(y);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
skipping to change at line 431 skipping to change at line 439
tmp = gcry_sexp_nth_data(sexp, 1, &size); tmp = gcry_sexp_nth_data(sexp, 1, &size);
e = string_new(size); e = string_new(size);
if (e == NULL) { if (e == NULL) {
goto error; goto error;
} }
string_fill(e, (char *) tmp, size); string_fill(e, (char *) tmp, size);
gcry_sexp_release(sexp); gcry_sexp_release(sexp);
gcry_sexp_build(&key->rsa_pub, NULL, gcry_sexp_build(&key->rsa_pub, NULL,
"(public-key(rsa(n %b)(e %b)))", "(public-key(rsa(n %b)(e %b)))",
string_len(n), n->string, string_len(n), string_data(n),
string_len(e), e->string); string_len(e), string_data(e));
if (key->rsa_pub == NULL) { if (key->rsa_pub == NULL) {
goto error; goto error;
} }
string_burn(e); string_burn(e);
string_free(e); string_free(e);
string_burn(n); string_burn(n);
string_free(n); string_free(n);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
key->rsa_pub = RSA_new(); key->rsa_pub = RSA_new();
skipping to change at line 481 skipping to change at line 489
string_free(e); string_free(e);
string_burn(n); string_burn(n);
string_free(n); string_free(n);
#endif #endif
publickey_free(key); publickey_free(key);
return NULL; return NULL;
} }
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
static int dsa_public_to_string(gcry_sexp_t key, BUFFER *buffer) { static int dsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
static int dsa_public_to_string(DSA *key, BUFFER *buffer) { static int dsa_public_to_string(DSA *key, ssh_buffer buffer) {
#endif #endif
STRING *p = NULL; ssh_string p = NULL;
STRING *q = NULL; ssh_string q = NULL;
STRING *g = NULL; ssh_string g = NULL;
STRING *n = NULL; ssh_string n = NULL;
int rc = -1; int rc = -1;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
const char *tmp = NULL; const char *tmp = NULL;
size_t size; size_t size;
gcry_sexp_t sexp; gcry_sexp_t sexp;
sexp = gcry_sexp_find_token(key, "p", 0); sexp = gcry_sexp_find_token(key, "p", 0);
if (sexp == NULL) { if (sexp == NULL) {
skipping to change at line 585 skipping to change at line 593
string_free(q); string_free(q);
string_burn(g); string_burn(g);
string_free(g); string_free(g);
string_burn(n); string_burn(n);
string_free(n); string_free(n);
return rc; return rc;
} }
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
static int rsa_public_to_string(gcry_sexp_t key, BUFFER *buffer) { static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
static int rsa_public_to_string(RSA *key, BUFFER *buffer) { static int rsa_public_to_string(RSA *key, ssh_buffer buffer) {
#endif #endif
STRING *e = NULL; ssh_string e = NULL;
STRING *n = NULL; ssh_string n = NULL;
int rc = -1; int rc = -1;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
const char *tmp; const char *tmp;
size_t size; size_t size;
gcry_sexp_t sexp; gcry_sexp_t sexp;
sexp = gcry_sexp_find_token(key, "n", 0); sexp = gcry_sexp_find_token(key, "n", 0);
if (sexp == NULL) { if (sexp == NULL) {
skipping to change at line 657 skipping to change at line 665
string_free(n); string_free(n);
return rc; return rc;
} }
/** \brief makes a SSH String out of a PUBLIC_KEY object /** \brief makes a SSH String out of a PUBLIC_KEY object
* \param key the public key * \param key the public key
* \returns a SSH String containing the public key * \returns a SSH String containing the public key
* \see string_free() * \see string_free()
*/ */
STRING *publickey_to_string(PUBLIC_KEY *key) { ssh_string publickey_to_string(ssh_public_key key) {
STRING *type = NULL; ssh_string type = NULL;
STRING *ret = NULL; ssh_string ret = NULL;
BUFFER *buf = NULL; ssh_buffer buf = NULL;
buf = buffer_new(); buf = buffer_new();
if (buf == NULL) { if (buf == NULL) {
return NULL; return NULL;
} }
type = string_from_char(key->type_c); type = string_from_char(key->type_c);
if (type == NULL) { if (type == NULL) {
goto error; goto error;
} }
skipping to change at line 704 skipping to change at line 712
string_fill(ret, buffer_get(buf), buffer_get_len(buf)); string_fill(ret, buffer_get(buf), buffer_get_len(buf));
error: error:
buffer_free(buf); buffer_free(buf);
string_free(type); string_free(type);
return ret; return ret;
} }
/* Signature decoding functions */ /* Signature decoding functions */
static STRING *signature_to_string(SIGNATURE *sign) { static ssh_string signature_to_string(SIGNATURE *sign) {
unsigned char buffer[40] = {0}; unsigned char buffer[40] = {0};
BUFFER *tmpbuf = NULL; ssh_buffer tmpbuf = NULL;
STRING *str = NULL; ssh_string str = NULL;
STRING *tmp = NULL; ssh_string tmp = NULL;
STRING *rs = NULL; ssh_string rs = NULL;
int rc = -1; int rc = -1;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
const char *r = NULL; const char *r = NULL;
const char *s = NULL; const char *s = NULL;
gcry_sexp_t sexp; gcry_sexp_t sexp;
size_t size = 0; size_t size = 0;
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
STRING *r = NULL; ssh_string r = NULL;
STRING *s = NULL; ssh_string s = NULL;
#endif #endif
tmpbuf = buffer_new(); tmpbuf = buffer_new();
if (tmpbuf == NULL) { if (tmpbuf == NULL) {
return NULL; return NULL;
} }
tmp = string_from_char(ssh_type_to_char(sign->type)); tmp = string_from_char(ssh_type_to_char(sign->type));
if (tmp == NULL) { if (tmp == NULL) {
buffer_free(tmpbuf); buffer_free(tmpbuf);
skipping to change at line 779 skipping to change at line 787
buffer_free(tmpbuf); buffer_free(tmpbuf);
return NULL; return NULL;
} }
s = make_bignum_string(sign->dsa_sign->s); s = make_bignum_string(sign->dsa_sign->s);
if (s == NULL) { if (s == NULL) {
buffer_free(tmpbuf); buffer_free(tmpbuf);
string_free(r); string_free(r);
return NULL; return NULL;
} }
memcpy(buffer, r->string + string_len(r) - 20, 20); memcpy(buffer, (char *)string_data(r) + string_len(r) - 20, 20);
memcpy(buffer + 20, s->string + string_len(s) - 20, 20); memcpy(buffer + 20, (char *)string_data(s) + string_len(s) - 20, 20);
string_free(r); string_free(r);
string_free(s); string_free(s);
#endif /* HAVE_LIBCRYPTO */ #endif /* HAVE_LIBCRYPTO */
rs = string_new(40); rs = string_new(40);
if (rs == NULL) { if (rs == NULL) {
buffer_free(tmpbuf); buffer_free(tmpbuf);
return NULL; return NULL;
} }
skipping to change at line 848 skipping to change at line 856
buffer_free(tmpbuf); buffer_free(tmpbuf);
return NULL; return NULL;
} }
string_fill(str, buffer_get(tmpbuf), buffer_get_len(tmpbuf)); string_fill(str, buffer_get(tmpbuf), buffer_get_len(tmpbuf));
buffer_free(tmpbuf); buffer_free(tmpbuf);
return str; return str;
} }
/* TODO : split this function in two so it becomes smaller */ /* TODO : split this function in two so it becomes smaller */
SIGNATURE *signature_from_string(SSH_SESSION *session, STRING *signature, SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
PUBLIC_KEY *pubkey, int needed_type) { ssh_public_key pubkey, int needed_type) {
SIGNATURE *sign = NULL; SIGNATURE *sign = NULL;
BUFFER *tmpbuf = NULL; ssh_buffer tmpbuf = NULL;
STRING *rs = NULL; ssh_string rs = NULL;
STRING *type_s = NULL; ssh_string type_s = NULL;
STRING *e = NULL; ssh_string e = NULL;
char *type_c = NULL; char *type_c = NULL;
int type; int type;
int len; int len;
int rsalen; int rsalen;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_t sig; gcry_sexp_t sig;
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
DSA_SIG *sig = NULL; DSA_SIG *sig = NULL;
STRING *r = NULL; ssh_string r = NULL;
STRING *s = NULL; ssh_string s = NULL;
#endif #endif
sign = malloc(sizeof(SIGNATURE)); sign = malloc(sizeof(SIGNATURE));
if (sign == NULL) { if (sign == NULL) {
ssh_set_error(session, SSH_FATAL, "Not enough space"); ssh_set_error(session, SSH_FATAL, "Not enough space");
return NULL; return NULL;
} }
tmpbuf = buffer_new(); tmpbuf = buffer_new();
if (tmpbuf == NULL) { if (tmpbuf == NULL) {
ssh_set_error(session, SSH_FATAL, "Not enough space"); ssh_set_error(session, SSH_FATAL, "Not enough space");
signature_free(sign); signature_free(sign);
return NULL; return NULL;
} }
if (buffer_add_data(tmpbuf, signature->string, string_len(signature)) < 0 ) { if (buffer_add_data(tmpbuf, string_data(signature), string_len(signature) ) < 0) {
signature_free(sign); signature_free(sign);
buffer_free(tmpbuf); buffer_free(tmpbuf);
return NULL; return NULL;
} }
type_s = buffer_get_ssh_string(tmpbuf); type_s = buffer_get_ssh_string(tmpbuf);
if (type_s == NULL) { if (type_s == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid signature packet"); ssh_set_error(session, SSH_FATAL, "Invalid signature packet");
signature_free(sign); signature_free(sign);
buffer_free(tmpbuf); buffer_free(tmpbuf);
skipping to change at line 928 skipping to change at line 936
if (rs == NULL || string_len(rs) != 40) { if (rs == NULL || string_len(rs) != 40) {
string_free(rs); string_free(rs);
signature_free(sign); signature_free(sign);
return NULL; return NULL;
} }
/* we make use of strings (because we have all-made functions to conv ert /* we make use of strings (because we have all-made functions to conv ert
* them to bignums (ou pas ;) */ * them to bignums (ou pas ;) */
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))", if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
20 ,rs->string, 20, rs->string + 20)) { 20 ,string_data(rs), 20,(unsigned char *)string_data(rs) + 20)) {
string_free(rs); string_free(rs);
signature_free(sign); signature_free(sign);
return NULL; return NULL;
} }
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
r = string_new(20); r = string_new(20);
s = string_new(20); s = string_new(20);
if (r == NULL || s == NULL) { if (r == NULL || s == NULL) {
string_free(r); string_free(r);
string_free(s); string_free(s);
string_free(rs); string_free(rs);
signature_free(sign); signature_free(sign);
return NULL; return NULL;
} }
string_fill(r, rs->string, 20); string_fill(r, string_data(rs), 20);
string_fill(s, rs->string + 20, 20); string_fill(s, (char *)string_data(rs) + 20, 20);
sig = DSA_SIG_new(); sig = DSA_SIG_new();
if (sig == NULL) { if (sig == NULL) {
string_free(r); string_free(r);
string_free(s); string_free(s);
string_free(rs); string_free(rs);
signature_free(sign); signature_free(sign);
return NULL; return NULL;
} }
sig->r = make_string_bn(r); /* is that really portable ? Openssh's ha ck isn't better */ sig->r = make_string_bn(r); /* is that really portable ? Openssh's ha ck isn't better */
skipping to change at line 1006 skipping to change at line 1014
return NULL; return NULL;
} }
if (len < rsalen) { if (len < rsalen) {
ssh_log(session, SSH_LOG_RARE, "RSA signature len %d < %d", ssh_log(session, SSH_LOG_RARE, "RSA signature len %d < %d",
len, rsalen); len, rsalen);
} }
sign->type = TYPE_RSA; sign->type = TYPE_RSA;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))", if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
string_len(e), e->string)) { string_len(e), string_data(e))) {
signature_free(sign); signature_free(sign);
string_free(e); string_free(e);
return NULL; return NULL;
} }
sign->rsa_sign = sig; sign->rsa_sign = sig;
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
sign->rsa_sign = e; sign->rsa_sign = e;
#endif #endif
skipping to change at line 1072 skipping to change at line 1080
SAFE_FREE(sign); SAFE_FREE(sign);
} }
#ifdef HAVE_LIBCRYPTO #ifdef HAVE_LIBCRYPTO
/* /*
* Maybe the missing function from libcrypto * Maybe the missing function from libcrypto
* *
* I think now, maybe it's a bad idea to name it has it should have be * I think now, maybe it's a bad idea to name it has it should have be
* named in libcrypto * named in libcrypto
*/ */
static STRING *RSA_do_sign(const unsigned char *payload, int len, RSA *priv static ssh_string RSA_do_sign(const unsigned char *payload, int len, RSA *p
key) { rivkey) {
STRING *sign = NULL; ssh_string sign = NULL;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
unsigned int size; unsigned int size;
buffer = malloc(RSA_size(privkey)); buffer = malloc(RSA_size(privkey));
if (buffer == NULL) { if (buffer == NULL) {
return NULL; return NULL;
} }
if (RSA_sign(NID_sha1, payload, len, buffer, &size, privkey) == 0) { if (RSA_sign(NID_sha1, payload, len, buffer, &size, privkey) == 0) {
SAFE_FREE(buffer); SAFE_FREE(buffer);
skipping to change at line 1101 skipping to change at line 1109
} }
string_fill(sign, buffer, size); string_fill(sign, buffer, size);
SAFE_FREE(buffer); SAFE_FREE(buffer);
return sign; return sign;
} }
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
STRING *ssh_do_sign_with_agent(struct ssh_session *session, ssh_string ssh_do_sign_with_agent(ssh_session session,
struct buffer_struct *buf, struct public_key_struct *publickey) { struct ssh_buffer_struct *buf, struct ssh_public_key_struct *publickey)
struct buffer_struct *sigbuf = NULL; {
struct string_struct *signature = NULL; struct ssh_buffer_struct *sigbuf = NULL;
struct string_struct *session_id = NULL; struct ssh_string_struct *signature = NULL;
struct ssh_string_struct *session_id = NULL;
struct ssh_crypto_struct *crypto = NULL; struct ssh_crypto_struct *crypto = NULL;
if (session->current_crypto) { if (session->current_crypto) {
crypto = session->current_crypto; crypto = session->current_crypto;
} else { } else {
crypto = session->next_crypto; crypto = session->next_crypto;
} }
/* prepend session identifier */ /* prepend session identifier */
session_id = string_new(SHA_DIGEST_LEN); session_id = string_new(SHA_DIGEST_LEN);
skipping to change at line 1150 skipping to change at line 1158
/* create signature */ /* create signature */
signature = agent_sign_data(session, sigbuf, publickey); signature = agent_sign_data(session, sigbuf, publickey);
buffer_free(sigbuf); buffer_free(sigbuf);
return signature; return signature;
} }
#endif /* _WIN32 */ #endif /* _WIN32 */
/* /*
* This function concats in a buffer the values needed to do a signature
* verification. */
ssh_buffer ssh_userauth_build_digest(ssh_session session, ssh_message msg,
char *service) {
/*
The value of 'signature' is a signature by the corresponding private
key over the following data, in the following order:
string session identifier
byte SSH_MSG_USERAUTH_REQUEST
string user name
string service name
string "publickey"
boolean TRUE
string public key algorithm name
string public key to be used for authentication
*/
struct ssh_crypto_struct *crypto = session->current_crypto ? session
->current_crypto :
session->next_crypto;
ssh_buffer buffer = NULL;
ssh_string session_id = NULL;
uint8_t type = SSH2_MSG_USERAUTH_REQUEST;
ssh_string username = string_from_char(msg->auth_request.username);
ssh_string servicename = string_from_char(service);
ssh_string method = string_from_char("publickey");
uint8_t has_sign = 1;
ssh_string algo = string_from_char(msg->auth_request.public_key->type_c);
ssh_string publickey = publickey_to_string(msg->auth_request.public_key);
buffer = buffer_new();
if (buffer == NULL) {
goto error;
}
session_id = string_new(SHA_DIGEST_LEN);
if (session_id == NULL) {
buffer_free(buffer);
buffer = NULL;
goto error;
}
string_fill(session_id, crypto->session_id, SHA_DIGEST_LEN);
if(buffer_add_ssh_string(buffer, session_id) < 0 ||
buffer_add_u8(buffer, type) < 0 ||
buffer_add_ssh_string(buffer, username) < 0 ||
buffer_add_ssh_string(buffer, servicename) < 0 ||
buffer_add_ssh_string(buffer, method) < 0 ||
buffer_add_u8(buffer, has_sign) < 0 ||
buffer_add_ssh_string(buffer, algo) < 0 ||
buffer_add_ssh_string(buffer, publickey) < 0) {
buffer_free(buffer);
buffer = NULL;
goto error;
}
error:
if(session_id) string_free(session_id);
if(username) string_free(username);
if(servicename) string_free(servicename);
if(method) string_free(method);
if(algo) string_free(algo);
if(publickey) string_free(publickey);
return buffer;
}
/*
* This function signs the session id (known as H) as a string then * This function signs the session id (known as H) as a string then
* the content of sigbuf */ * the content of sigbuf */
STRING *ssh_do_sign(SSH_SESSION *session, BUFFER *sigbuf, ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
PRIVATE_KEY *privatekey) { ssh_private_key privatekey) {
CRYPTO *crypto = session->current_crypto ? session->current_crypto : struct ssh_crypto_struct *crypto = session->current_crypto ? session->cur
rent_crypto :
session->next_crypto; session->next_crypto;
unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
STRING *session_str = NULL; ssh_string session_str = NULL;
STRING *signature = NULL; ssh_string signature = NULL;
SIGNATURE *sign = NULL; SIGNATURE *sign = NULL;
SHACTX ctx = NULL; SHACTX ctx = NULL;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_t gcryhash; gcry_sexp_t gcryhash;
#endif #endif
session_str = string_new(SHA_DIGEST_LEN); session_str = string_new(SHA_DIGEST_LEN);
if (session_str == NULL) { if (session_str == NULL) {
return NULL; return NULL;
} }
skipping to change at line 1251 skipping to change at line 1323
#endif #endif
sign->type = privatekey->type; sign->type = privatekey->type;
signature = signature_to_string(sign); signature = signature_to_string(sign);
signature_free(sign); signature_free(sign);
return signature; return signature;
} }
STRING *ssh_encrypt_rsa1(SSH_SESSION *session, STRING *data, PUBLIC_KEY *ke ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_publi
y) { c_key key) {
STRING *str = NULL; ssh_string str = NULL;
size_t len = string_len(data); size_t len = string_len(data);
size_t size = 0; size_t size = 0;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
const char *tmp = NULL; const char *tmp = NULL;
gcry_sexp_t ret_sexp; gcry_sexp_t ret_sexp;
gcry_sexp_t data_sexp; gcry_sexp_t data_sexp;
if (gcry_sexp_build(&data_sexp, NULL, "(data(flags pkcs1)(value %b))", if (gcry_sexp_build(&data_sexp, NULL, "(data(flags pkcs1)(value %b))",
len, data->string)) { len, string_data(data))) {
ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error"); ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
return NULL; return NULL;
} }
if (gcry_pk_encrypt(&ret_sexp, data_sexp, key->rsa_pub)) { if (gcry_pk_encrypt(&ret_sexp, data_sexp, key->rsa_pub)) {
gcry_sexp_release(data_sexp); gcry_sexp_release(data_sexp);
ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error"); ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
return NULL; return NULL;
} }
gcry_sexp_release(data_sexp); gcry_sexp_release(data_sexp);
skipping to change at line 1305 skipping to change at line 1377
gcry_sexp_release(ret_sexp); gcry_sexp_release(ret_sexp);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
size = RSA_size(key->rsa_pub); size = RSA_size(key->rsa_pub);
str = string_new(size); str = string_new(size);
if (str == NULL) { if (str == NULL) {
ssh_set_error(session, SSH_FATAL, "Not enough space"); ssh_set_error(session, SSH_FATAL, "Not enough space");
return NULL; return NULL;
} }
if (RSA_public_encrypt(len, data->string, str->string, key->rsa_pub, if (RSA_public_encrypt(len, string_data(data), string_data(str), key->rsa _pub,
RSA_PKCS1_PADDING) < 0) { RSA_PKCS1_PADDING) < 0) {
string_free(str); string_free(str);
return NULL; return NULL;
} }
#endif #endif
return str; return str;
} }
/* this function signs the session id */ /* this function signs the session id */
STRING *ssh_sign_session_id(SSH_SESSION *session, PRIVATE_KEY *privatekey) ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key private
{ key) {
CRYPTO *crypto=session->current_crypto ? session->current_crypto : struct ssh_crypto_struct *crypto=session->current_crypto ? session->
current_crypto :
session->next_crypto; session->next_crypto;
unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
STRING *signature = NULL; ssh_string signature = NULL;
SIGNATURE *sign = NULL; SIGNATURE *sign = NULL;
SHACTX ctx = NULL; SHACTX ctx = NULL;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_t data_sexp; gcry_sexp_t data_sexp;
#endif #endif
ctx = sha1_init(); ctx = sha1_init();
if (ctx == NULL) { if (ctx == NULL) {
return NULL; return NULL;
} }
 End of changes. 44 change blocks. 
96 lines changed or deleted 174 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/