dh.c | dh.c | |||
---|---|---|---|---|
skipping to change at line 43 | skipping to change at line 43 | |||
* the server computes his own public key, f | * the server computes his own public key, f | |||
* f = g^y mod p | * f = g^y mod p | |||
* it sents it to the client | * it sents it to the client | |||
* the common key K is calculated by the client by doing | * the common key K is calculated by the client by doing | |||
* k = f^x mod p | * k = f^x mod p | |||
* the server does the same with the client public key e | * the server does the same with the client public key e | |||
* k' = e^y mod p | * k' = e^y mod p | |||
* if everything went correctly, k and k' are equal | * if everything went correctly, k and k' are equal | |||
*/ | */ | |||
#include "config.h" | ||||
#include <stdio.h> | #include <stdio.h> | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#include <string.h> | #include <string.h> | |||
#ifndef _WIN32 | #ifndef _WIN32 | |||
#include <arpa/inet.h> | #include <arpa/inet.h> | |||
#endif | #endif | |||
#include "libssh/priv.h" | #include "libssh/priv.h" | |||
#include "libssh/crypto.h" | #include "libssh/crypto.h" | |||
#include "libssh/buffer.h" | ||||
#include "libssh/session.h" | ||||
#include "libssh/keys.h" | ||||
#include "libssh/dh.h" | ||||
/* todo: remove it */ | ||||
#include "libssh/string.h" | ||||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
#include <openssl/rand.h> | #include <openssl/rand.h> | |||
#include <openssl/evp.h> | #include <openssl/evp.h> | |||
#include <openssl/err.h> | #include <openssl/err.h> | |||
#endif | #endif | |||
static unsigned char p_value[] = { | static unsigned char p_value[] = { | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0 xA2, | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0 xA2, | |||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0 xD1, | 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0 xD1, | |||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0 xA6, | 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0 xA6, | |||
skipping to change at line 219 | skipping to change at line 226 | |||
*/ | */ | |||
void ssh_print_hexa(const char *descr, const unsigned char *what, size_t le n) { | void ssh_print_hexa(const char *descr, const unsigned char *what, size_t le n) { | |||
char *hexa = ssh_get_hexa(what, len); | char *hexa = ssh_get_hexa(what, len); | |||
if (hexa == NULL) { | if (hexa == NULL) { | |||
return; | return; | |||
} | } | |||
printf("%s: %s\n", descr, hexa); | printf("%s: %s\n", descr, hexa); | |||
} | } | |||
int dh_generate_x(SSH_SESSION *session) { | int dh_generate_x(ssh_session session) { | |||
session->next_crypto->x = bignum_new(); | session->next_crypto->x = bignum_new(); | |||
if (session->next_crypto->x == NULL) { | if (session->next_crypto->x == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
#ifdef HAVE_LIBGCRYPT | #ifdef HAVE_LIBGCRYPT | |||
bignum_rand(session->next_crypto->x, 128); | bignum_rand(session->next_crypto->x, 128); | |||
#elif defined HAVE_LIBCRYPTO | #elif defined HAVE_LIBCRYPTO | |||
bignum_rand(session->next_crypto->x, 128, 0, -1); | bignum_rand(session->next_crypto->x, 128, 0, -1); | |||
#endif | #endif | |||
/* not harder than this */ | /* not harder than this */ | |||
#ifdef DEBUG_CRYPTO | #ifdef DEBUG_CRYPTO | |||
ssh_print_bignum("x", session->next_crypto->x); | ssh_print_bignum("x", session->next_crypto->x); | |||
#endif | #endif | |||
return 0; | return 0; | |||
} | } | |||
/* used by server */ | /* used by server */ | |||
int dh_generate_y(SSH_SESSION *session) { | int dh_generate_y(ssh_session session) { | |||
session->next_crypto->y = bignum_new(); | session->next_crypto->y = bignum_new(); | |||
if (session->next_crypto->y == NULL) { | if (session->next_crypto->y == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
#ifdef HAVE_LIBGCRYPT | #ifdef HAVE_LIBGCRYPT | |||
bignum_rand(session->next_crypto->y, 128); | bignum_rand(session->next_crypto->y, 128); | |||
#elif defined HAVE_LIBCRYPTO | #elif defined HAVE_LIBCRYPTO | |||
bignum_rand(session->next_crypto->y, 128, 0, -1); | bignum_rand(session->next_crypto->y, 128, 0, -1); | |||
#endif | #endif | |||
/* not harder than this */ | /* not harder than this */ | |||
#ifdef DEBUG_CRYPTO | #ifdef DEBUG_CRYPTO | |||
ssh_print_bignum("y", session->next_crypto->y); | ssh_print_bignum("y", session->next_crypto->y); | |||
#endif | #endif | |||
return 0; | return 0; | |||
} | } | |||
/* used by server */ | /* used by server */ | |||
int dh_generate_e(SSH_SESSION *session) { | int dh_generate_e(ssh_session session) { | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
bignum_CTX ctx = bignum_ctx_new(); | bignum_CTX ctx = bignum_ctx_new(); | |||
if (ctx == NULL) { | if (ctx == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
#endif | #endif | |||
session->next_crypto->e = bignum_new(); | session->next_crypto->e = bignum_new(); | |||
if (session->next_crypto->e == NULL) { | if (session->next_crypto->e == NULL) { | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
skipping to change at line 294 | skipping to change at line 301 | |||
ssh_print_bignum("e", session->next_crypto->e); | ssh_print_bignum("e", session->next_crypto->e); | |||
#endif | #endif | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
bignum_ctx_free(ctx); | bignum_ctx_free(ctx); | |||
#endif | #endif | |||
return 0; | return 0; | |||
} | } | |||
int dh_generate_f(SSH_SESSION *session) { | int dh_generate_f(ssh_session session) { | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
bignum_CTX ctx = bignum_ctx_new(); | bignum_CTX ctx = bignum_ctx_new(); | |||
if (ctx == NULL) { | if (ctx == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
#endif | #endif | |||
session->next_crypto->f = bignum_new(); | session->next_crypto->f = bignum_new(); | |||
if (session->next_crypto->f == NULL) { | if (session->next_crypto->f == NULL) { | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
skipping to change at line 327 | skipping to change at line 334 | |||
ssh_print_bignum("f", session->next_crypto->f); | ssh_print_bignum("f", session->next_crypto->f); | |||
#endif | #endif | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
bignum_ctx_free(ctx); | bignum_ctx_free(ctx); | |||
#endif | #endif | |||
return 0; | return 0; | |||
} | } | |||
STRING *make_bignum_string(bignum num) { | ssh_string make_bignum_string(bignum num) { | |||
STRING *ptr = NULL; | ssh_string ptr = NULL; | |||
int pad = 0; | int pad = 0; | |||
unsigned int len = bignum_num_bytes(num); | unsigned int len = bignum_num_bytes(num); | |||
unsigned int bits = bignum_num_bits(num); | unsigned int bits = bignum_num_bits(num); | |||
/* Remember if the fist bit is set, it is considered as a | /* Remember if the fist bit is set, it is considered as a | |||
* negative number. So 0's must be appended */ | * negative number. So 0's must be appended */ | |||
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) { | if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) { | |||
pad++; | pad++; | |||
} | } | |||
#ifdef DEBUG_CRYPTO | #ifdef DEBUG_CRYPTO | |||
fprintf(stderr, "%d bits, %d bytes, %d padding\n", bits, len, pad); | fprintf(stderr, "%d bits, %d bytes, %d padding\n", bits, len, pad); | |||
#endif /* DEBUG_CRYPTO */ | #endif /* DEBUG_CRYPTO */ | |||
/* TODO: fix that crap !! */ | ||||
ptr = malloc(4 + len + pad); | ptr = malloc(4 + len + pad); | |||
if (ptr == NULL) { | if (ptr == NULL) { | |||
return NULL; | return NULL; | |||
} | } | |||
ptr->size = htonl(len + pad); | ptr->size = htonl(len + pad); | |||
if (pad) { | if (pad) { | |||
ptr->string[0] = 0; | ptr->string[0] = 0; | |||
} | } | |||
#ifdef HAVE_LIBGCRYPT | #ifdef HAVE_LIBGCRYPT | |||
bignum_bn2bin(num, len, ptr->string + pad); | bignum_bn2bin(num, len, ptr->string + pad); | |||
#elif HAVE_LIBCRYPTO | #elif HAVE_LIBCRYPTO | |||
bignum_bn2bin(num, ptr->string + pad); | bignum_bn2bin(num, ptr->string + pad); | |||
#endif | #endif | |||
return ptr; | return ptr; | |||
} | } | |||
bignum make_string_bn(STRING *string){ | bignum make_string_bn(ssh_string string){ | |||
bignum bn = NULL; | bignum bn = NULL; | |||
unsigned int len = string_len(string); | unsigned int len = string_len(string); | |||
#ifdef DEBUG_CRYPTO | #ifdef DEBUG_CRYPTO | |||
fprintf(stderr, "Importing a %d bits, %d bytes object ...\n", | fprintf(stderr, "Importing a %d bits, %d bytes object ...\n", | |||
len * 8, len); | len * 8, len); | |||
#endif /* DEBUG_CRYPTO */ | #endif /* DEBUG_CRYPTO */ | |||
#ifdef HAVE_LIBGCRYPT | #ifdef HAVE_LIBGCRYPT | |||
bignum_bin2bn(string->string, len, &bn); | bignum_bin2bn(string->string, len, &bn); | |||
#elif defined HAVE_LIBCRYPTO | #elif defined HAVE_LIBCRYPTO | |||
bn = bignum_bin2bn(string->string, len, NULL); | bn = bignum_bin2bn(string->string, len, NULL); | |||
#endif | #endif | |||
return bn; | return bn; | |||
} | } | |||
STRING *dh_get_e(SSH_SESSION *session) { | ssh_string dh_get_e(ssh_session session) { | |||
return make_bignum_string(session->next_crypto->e); | return make_bignum_string(session->next_crypto->e); | |||
} | } | |||
/* used by server */ | /* used by server */ | |||
STRING *dh_get_f(SSH_SESSION *session) { | ssh_string dh_get_f(ssh_session session) { | |||
return make_bignum_string(session->next_crypto->f); | return make_bignum_string(session->next_crypto->f); | |||
} | } | |||
void dh_import_pubkey(SSH_SESSION *session, STRING *pubkey_string) { | void dh_import_pubkey(ssh_session session, ssh_string pubkey_string) { | |||
session->next_crypto->server_pubkey = pubkey_string; | session->next_crypto->server_pubkey = pubkey_string; | |||
} | } | |||
int dh_import_f(SSH_SESSION *session, STRING *f_string) { | int dh_import_f(ssh_session session, ssh_string f_string) { | |||
session->next_crypto->f = make_string_bn(f_string); | session->next_crypto->f = make_string_bn(f_string); | |||
if (session->next_crypto->f == NULL) { | if (session->next_crypto->f == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
#ifdef DEBUG_CRYPTO | #ifdef DEBUG_CRYPTO | |||
ssh_print_bignum("f",session->next_crypto->f); | ssh_print_bignum("f",session->next_crypto->f); | |||
#endif | #endif | |||
return 0; | return 0; | |||
} | } | |||
/* used by the server implementation */ | /* used by the server implementation */ | |||
int dh_import_e(SSH_SESSION *session, STRING *e_string) { | int dh_import_e(ssh_session session, ssh_string e_string) { | |||
session->next_crypto->e = make_string_bn(e_string); | session->next_crypto->e = make_string_bn(e_string); | |||
if (session->next_crypto->e == NULL) { | if (session->next_crypto->e == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
#ifdef DEBUG_CRYPTO | #ifdef DEBUG_CRYPTO | |||
ssh_print_bignum("e",session->next_crypto->e); | ssh_print_bignum("e",session->next_crypto->e); | |||
#endif | #endif | |||
return 0; | return 0; | |||
} | } | |||
int dh_build_k(SSH_SESSION *session) { | int dh_build_k(ssh_session session) { | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
bignum_CTX ctx = bignum_ctx_new(); | bignum_CTX ctx = bignum_ctx_new(); | |||
if (ctx == NULL) { | if (ctx == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
#endif | #endif | |||
session->next_crypto->k = bignum_new(); | session->next_crypto->k = bignum_new(); | |||
if (session->next_crypto->k == NULL) { | if (session->next_crypto->k == NULL) { | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
skipping to change at line 468 | skipping to change at line 475 | |||
#endif | #endif | |||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | |||
bignum_ctx_free(ctx); | bignum_ctx_free(ctx); | |||
#endif | #endif | |||
return 0; | return 0; | |||
} | } | |||
/* | /* | |||
static void sha_add(STRING *str,SHACTX ctx){ | static void sha_add(ssh_string str,SHACTX ctx){ | |||
sha1_update(ctx,str,string_len(str)+4); | sha1_update(ctx,str,string_len(str)+4); | |||
#ifdef DEBUG_CRYPTO | #ifdef DEBUG_CRYPTO | |||
ssh_print_hexa("partial hashed sessionid",str,string_len(str)+4); | ssh_print_hexa("partial hashed sessionid",str,string_len(str)+4); | |||
#endif | #endif | |||
} | } | |||
*/ | */ | |||
int make_sessionid(SSH_SESSION *session) { | int make_sessionid(ssh_session session) { | |||
SHACTX ctx; | SHACTX ctx; | |||
STRING *num = NULL; | ssh_string num = NULL; | |||
STRING *str = NULL; | ssh_string str = NULL; | |||
BUFFER *server_hash = NULL; | ssh_buffer server_hash = NULL; | |||
BUFFER *client_hash = NULL; | ssh_buffer client_hash = NULL; | |||
BUFFER *buf = NULL; | ssh_buffer buf = NULL; | |||
u32 len; | uint32_t len; | |||
int rc = SSH_ERROR; | int rc = SSH_ERROR; | |||
enter_function(); | enter_function(); | |||
ctx = sha1_init(); | ctx = sha1_init(); | |||
if (ctx == NULL) { | if (ctx == NULL) { | |||
return rc; | return rc; | |||
} | } | |||
buf = buffer_new(); | buf = buffer_new(); | |||
skipping to change at line 622 | skipping to change at line 629 | |||
session->out_hashbuf = NULL; | session->out_hashbuf = NULL; | |||
string_free(str); | string_free(str); | |||
string_free(num); | string_free(num); | |||
leave_function(); | leave_function(); | |||
return rc; | return rc; | |||
} | } | |||
int hashbufout_add_cookie(SSH_SESSION *session) { | int hashbufout_add_cookie(ssh_session session) { | |||
session->out_hashbuf = buffer_new(); | session->out_hashbuf = buffer_new(); | |||
if (session->out_hashbuf == NULL) { | if (session->out_hashbuf == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
if (buffer_add_u8(session->out_hashbuf, 20) < 0) { | if (buffer_add_u8(session->out_hashbuf, 20) < 0) { | |||
buffer_reinit(session->out_hashbuf); | buffer_reinit(session->out_hashbuf); | |||
return -1; | return -1; | |||
} | } | |||
skipping to change at line 650 | skipping to change at line 657 | |||
if (buffer_add_data(session->out_hashbuf, | if (buffer_add_data(session->out_hashbuf, | |||
session->client_kex.cookie, 16) < 0) { | session->client_kex.cookie, 16) < 0) { | |||
buffer_reinit(session->out_hashbuf); | buffer_reinit(session->out_hashbuf); | |||
return -1; | return -1; | |||
} | } | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
int hashbufin_add_cookie(SSH_SESSION *session, unsigned char *cookie) { | int hashbufin_add_cookie(ssh_session session, unsigned char *cookie) { | |||
session->in_hashbuf = buffer_new(); | session->in_hashbuf = buffer_new(); | |||
if (session->in_hashbuf == NULL) { | if (session->in_hashbuf == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
if (buffer_add_u8(session->in_hashbuf, 20) < 0) { | if (buffer_add_u8(session->in_hashbuf, 20) < 0) { | |||
buffer_reinit(session->in_hashbuf); | buffer_reinit(session->in_hashbuf); | |||
return -1; | return -1; | |||
} | } | |||
if (buffer_add_data(session->in_hashbuf,cookie, 16) < 0) { | if (buffer_add_data(session->in_hashbuf,cookie, 16) < 0) { | |||
buffer_reinit(session->in_hashbuf); | buffer_reinit(session->in_hashbuf); | |||
return -1; | return -1; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
static int generate_one_key(STRING *k, | static int generate_one_key(ssh_string k, | |||
unsigned char session_id[SHA_DIGEST_LEN], | unsigned char session_id[SHA_DIGEST_LEN], | |||
unsigned char output[SHA_DIGEST_LEN], | unsigned char output[SHA_DIGEST_LEN], | |||
char letter) { | char letter) { | |||
SHACTX ctx = NULL; | SHACTX ctx = NULL; | |||
ctx = sha1_init(); | ctx = sha1_init(); | |||
if (ctx == NULL) { | if (ctx == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
sha1_update(ctx, k, string_len(k) + 4); | sha1_update(ctx, k, string_len(k) + 4); | |||
sha1_update(ctx, session_id, SHA_DIGEST_LEN); | sha1_update(ctx, session_id, SHA_DIGEST_LEN); | |||
sha1_update(ctx, &letter, 1); | sha1_update(ctx, &letter, 1); | |||
sha1_update(ctx, session_id, SHA_DIGEST_LEN); | sha1_update(ctx, session_id, SHA_DIGEST_LEN); | |||
sha1_final(output, ctx); | sha1_final(output, ctx); | |||
return 0; | return 0; | |||
} | } | |||
int generate_session_keys(SSH_SESSION *session) { | int generate_session_keys(ssh_session session) { | |||
STRING *k_string = NULL; | ssh_string k_string = NULL; | |||
SHACTX ctx = NULL; | SHACTX ctx = NULL; | |||
int rc = -1; | int rc = -1; | |||
enter_function(); | enter_function(); | |||
k_string = make_bignum_string(session->next_crypto->k); | k_string = make_bignum_string(session->next_crypto->k); | |||
if (k_string == NULL) { | if (k_string == NULL) { | |||
goto error; | goto error; | |||
} | } | |||
skipping to change at line 818 | skipping to change at line 825 | |||
* @return The bytes allocated or < 0 on error. | * @return The bytes allocated or < 0 on error. | |||
* | * | |||
* @warning It is very important that you verify at some moment that the ha sh | * @warning It is very important that you verify at some moment that the ha sh | |||
* matches a known server. If you don't do it, cryptography wont h elp | * matches a known server. If you don't do it, cryptography wont h elp | |||
* you at making things secure | * you at making things secure | |||
* | * | |||
* @see ssh_is_server_known() | * @see ssh_is_server_known() | |||
* @see ssh_get_hexa() | * @see ssh_get_hexa() | |||
* @see ssh_print_hexa() | * @see ssh_print_hexa() | |||
*/ | */ | |||
int ssh_get_pubkey_hash(SSH_SESSION *session, unsigned char **hash) { | int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) { | |||
STRING *pubkey; | ssh_string pubkey; | |||
MD5CTX ctx; | MD5CTX ctx; | |||
unsigned char *h; | unsigned char *h; | |||
if (session == NULL || hash == NULL) { | if (session == NULL || hash == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
*hash = NULL; | *hash = NULL; | |||
h = malloc(sizeof(unsigned char *) * MD5_DIGEST_LEN); | h = malloc(sizeof(unsigned char *) * MD5_DIGEST_LEN); | |||
skipping to change at line 850 | skipping to change at line 857 | |||
pubkey = session->current_crypto->server_pubkey; | pubkey = session->current_crypto->server_pubkey; | |||
md5_update(ctx, pubkey->string, string_len(pubkey)); | md5_update(ctx, pubkey->string, string_len(pubkey)); | |||
md5_final(h, ctx); | md5_final(h, ctx); | |||
*hash = h; | *hash = h; | |||
return MD5_DIGEST_LEN; | return MD5_DIGEST_LEN; | |||
} | } | |||
STRING *ssh_get_pubkey(SSH_SESSION *session){ | /** | |||
* @brief Deallocate the hash obtained by ssh_get_pubkey_hash. | ||||
* This is required under Microsoft platform as this library might use a | ||||
* different C library than your software, hence a different heap. | ||||
* | ||||
* @param hash The buffer to deallocate. | ||||
* | ||||
* @see ssh_get_pubkey_hash() | ||||
*/ | ||||
void ssh_clean_pubkey_hash(unsigned char **hash) { | ||||
SAFE_FREE(*hash); | ||||
*hash = NULL; | ||||
} | ||||
ssh_string ssh_get_pubkey(ssh_session session){ | ||||
return string_copy(session->current_crypto->server_pubkey); | return string_copy(session->current_crypto->server_pubkey); | |||
} | } | |||
static int match(const char *group, const char *object){ | static int match(const char *group, const char *object){ | |||
const char *a; | const char *a; | |||
const char *z; | const char *z; | |||
a = z = group; | a = z = group; | |||
do { | do { | |||
a = strchr(z, ','); | a = strchr(z, ','); | |||
skipping to change at line 878 | skipping to change at line 899 | |||
return 1; | return 1; | |||
} | } | |||
} | } | |||
z = a + 1; | z = a + 1; | |||
} while(1); | } while(1); | |||
/* not reached */ | /* not reached */ | |||
return 0; | return 0; | |||
} | } | |||
static int sig_verify(SSH_SESSION *session, PUBLIC_KEY *pubkey, | int sig_verify(ssh_session session, ssh_public_key pubkey, | |||
SIGNATURE *signature, unsigned char *digest) { | SIGNATURE *signature, unsigned char *digest, int size) { | |||
#ifdef HAVE_LIBGCRYPT | #ifdef HAVE_LIBGCRYPT | |||
gcry_error_t valid = 0; | gcry_error_t valid = 0; | |||
gcry_sexp_t gcryhash; | gcry_sexp_t gcryhash; | |||
#elif defined HAVE_LIBCRYPTO | #elif defined HAVE_LIBCRYPTO | |||
int valid = 0; | int valid = 0; | |||
#endif | #endif | |||
unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; | unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; | |||
sha1(digest,SHA_DIGEST_LEN, hash + 1); | sha1(digest, size, hash + 1); | |||
#ifdef DEBUG_CRYPTO | #ifdef DEBUG_CRYPTO | |||
ssh_print_hexa("Hash to be verified with dsa", hash + 1, SHA_DIGEST_LEN); | ssh_print_hexa("Hash to be verified with dsa", hash + 1, SHA_DIGEST_LEN); | |||
#endif | #endif | |||
switch(pubkey->type) { | switch(pubkey->type) { | |||
case TYPE_DSS: | case TYPE_DSS: | |||
#ifdef HAVE_LIBGCRYPT | #ifdef HAVE_LIBGCRYPT | |||
valid = gcry_sexp_build(&gcryhash, NULL, "%b", SHA_DIGEST_LEN + 1, ha sh); | valid = gcry_sexp_build(&gcryhash, NULL, "%b", SHA_DIGEST_LEN + 1, ha sh); | |||
if (valid != 0) { | if (valid != 0) { | |||
skipping to change at line 973 | skipping to change at line 994 | |||
ssh_set_error(session, SSH_FATAL, "Invalid RSA signature"); | ssh_set_error(session, SSH_FATAL, "Invalid RSA signature"); | |||
return -1; | return -1; | |||
default: | default: | |||
ssh_set_error(session, SSH_FATAL, "Unknown public key type"); | ssh_set_error(session, SSH_FATAL, "Unknown public key type"); | |||
return -1; | return -1; | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
int signature_verify(SSH_SESSION *session, STRING *signature) { | int signature_verify(ssh_session session, ssh_string signature) { | |||
PUBLIC_KEY *pubkey = NULL; | ssh_public_key pubkey = NULL; | |||
SIGNATURE *sign = NULL; | SIGNATURE *sign = NULL; | |||
int err; | int err; | |||
enter_function(); | enter_function(); | |||
if (session->options->dont_verify_hostkey) { | ||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Host key wasn't verified"); | ||||
leave_function(); | ||||
return 0; | ||||
} | ||||
pubkey = publickey_from_string(session,session->next_crypto->server_pubke y); | pubkey = publickey_from_string(session,session->next_crypto->server_pubke y); | |||
if(pubkey == NULL) { | if(pubkey == NULL) { | |||
leave_function(); | leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
if (session->options->wanted_methods[SSH_HOSTKEYS]) { | if (session->wanted_methods[SSH_HOSTKEYS]) { | |||
if(!match(session->options->wanted_methods[SSH_HOSTKEYS],pubkey->type_c | if(!match(session->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)) { | |||
)) { | ||||
ssh_set_error(session, SSH_FATAL, | ssh_set_error(session, SSH_FATAL, | |||
"Public key from server (%s) doesn't match user preference (%s)", | "Public key from server (%s) doesn't match user preference (%s)", | |||
pubkey->type_c, session->options->wanted_methods[SSH_HOSTKEYS]); | pubkey->type_c, session->wanted_methods[SSH_HOSTKEYS]); | |||
publickey_free(pubkey); | publickey_free(pubkey); | |||
leave_function(); | leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
} | } | |||
sign = signature_from_string(session, signature, pubkey, pubkey->type); | sign = signature_from_string(session, signature, pubkey, pubkey->type); | |||
if (sign == NULL) { | if (sign == NULL) { | |||
ssh_set_error(session, SSH_FATAL, "Invalid signature blob"); | ssh_set_error(session, SSH_FATAL, "Invalid signature blob"); | |||
publickey_free(pubkey); | publickey_free(pubkey); | |||
leave_function(); | leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
ssh_log(session, SSH_LOG_FUNCTIONS, | ssh_log(session, SSH_LOG_FUNCTIONS, | |||
"Going to verify a %s type signature", pubkey->type_c); | "Going to verify a %s type signature", pubkey->type_c); | |||
err = sig_verify(session,pubkey,sign,session->next_crypto->session_id); | err = sig_verify(session,pubkey,sign, | |||
session->next_crypto->session_id,SHA_DIGEST_LEN | ||||
); | ||||
signature_free(sign); | signature_free(sign); | |||
session->next_crypto->server_pubkey_type = pubkey->type_c; | session->next_crypto->server_pubkey_type = pubkey->type_c; | |||
publickey_free(pubkey); | publickey_free(pubkey); | |||
leave_function(); | leave_function(); | |||
return err; | return err; | |||
} | } | |||
/** @} */ | /** @} */ | |||
/* vim: set ts=2 sw=2 et cindent: */ | /* vim: set ts=2 sw=2 et cindent: */ | |||
End of changes. 32 change blocks. | ||||
46 lines changed or deleted | 62 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/ |