1 /* dh.c */ 2 /* this file contains usefull stuff for Diffie helman algorithm against SSH 2 */ 3 /* 4 Copyright 2003 Aris Adamantiadis 5 6 This file is part of the SSH Library 7 8 The SSH Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 2.1 of the License, or (at your 11 option) any later version. 12 13 The SSH Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the SSH Library; see the file COPYING. If not, write to 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 21 MA 02111-1307, USA. */ 22 23 /* Let us resume the dh protocol. */ 24 /* Each side computes a private prime number, x at client side, y at server side. */ 25 /* g and n are two numbers common to every ssh software. */ 26 /* client's public key (e) is calculated by doing */ 27 /* e = g^x mod p */ 28 /* client sents e to the server . */ 29 /* the server computes his own public key, f */ 30 /* f = g^y mod p */ 31 /* it sents it to the client */ 32 /* the common key K is calculated by the client by doing */ 33 /* k = f^x mod p */ 34 /* the server does the same with the client public key e */ 35 /* k' = e^y mod p */ 36 /* if everything went correctly, k and k' are equal */ 37 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <unistd.h> 41 #include <fcntl.h> 42 #include <netdb.h> 43 #include "libssh/priv.h" 44 45 #include <openssl/rand.h> 46 #include <openssl/evp.h> 47 #include <openssl/err.h> 48 #include <string.h> 49 #include "libssh/crypto.h" 50 static unsigned char p_value[] = { 51 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 52 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 53 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 54 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 55 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 56 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 57 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 58 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 59 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 60 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 61 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 62 #define P_LEN 128 /* Size in bytes of the p number */ 63 64 static unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */ 65 static bignum g; 66 static bignum p; 67 68 /* maybe it might be enhanced .... */ 69 /* XXX Do it. */ 70 void ssh_get_random(void *where, int len){ 71 static int rndfd=0; 72 if(!rndfd){ 73 rndfd=open("/dev/urandom",O_RDONLY); 74 if(rndfd<0){ 75 fprintf(stderr,"Can't open /dev/urandom\n"); 76 exit(-1); 77 } 78 } 79 read(rndfd,where,len); 80 } 81 82 /* it inits the values g and p which are used for DH key agreement */ 83 void ssh_crypto_init(){ 84 static int init=0; 85 if(!init){ 86 g=bignum_new(); 87 bignum_set_word(g,g_int); 88 p=bignum_new(); 89 bignum_bin2bn(p_value,P_LEN,p); 90 init++; 91 } 92 } 93 94 /* prints the bignum on stderr */ 95 void ssh_print_bignum(char *which,bignum num){ 96 char *hex; 97 fprintf(stderr,"%s value: ",which); 98 hex=bignum_bn2hex(num); 99 fprintf(stderr,"%s\n",hex); 100 free(hex); 101 } 102 103 void ssh_print_hexa(char *descr,unsigned char *what, int len){ 104 int i; 105 printf("%s : ",descr); 106 for(i=0;i<len-1;i++) 107 printf("%.2hhx:",what[i]); 108 printf("%.2hhx\n",what[i]); 109 } 110 111 void dh_generate_x(SSH_SESSION *session){ 112 session->next_crypto->x=bignum_new(); 113 bignum_rand(session->next_crypto->x,128,0,-1); 114 /* not harder than this */ 115 #ifdef DEBUG_CRYPTO 116 ssh_print_bignum("x",session->next_crypto->x); 117 #endif 118 } 119 120 void dh_generate_e(SSH_SESSION *session){ 121 bignum_CTX ctx=bignum_ctx_new(); 122 session->next_crypto->e=bignum_new(); 123 bignum_mod_exp(session->next_crypto->e,g,session->next_crypto->x,p,ctx); 124 #ifdef DEBUG_CRYPTO 125 ssh_print_bignum("e",session->next_crypto->e); 126 #endif 127 bignum_ctx_free(ctx); 128 } 129 130 131 STRING *make_bignum_string(bignum num){ 132 STRING *ptr; 133 int pad=0; 134 int len=bignum_num_bytes(num); 135 int bits=bignum_num_bits(num); 136 int finallen; 137 /* remember if the fist bit is set, it is considered as a negative number. so 0's must be appended */ 138 if(!(bits%8) && bignum_is_bit_set(num,bits-1)) 139 pad++; 140 ssh_say(3,"%d bits, %d bytes, %d padding\n",bits,len,pad); 141 ptr=malloc(4 + len + pad); 142 ptr->size=htonl(len+pad); 143 if(pad) 144 ptr->string[0]=0; 145 finallen=bignum_bn2bin(num,ptr->string+pad); 146 return ptr; 147 } 148 149 bignum make_string_bn(STRING *string){ 150 int len=ntohl(string->size); 151 ssh_say(3,"Importing a %d bits,%d bytes object ...\n",len*8,len); 152 return bignum_bin2bn(string->string,len,NULL); 153 } 154 155 STRING *dh_get_e(SSH_SESSION *session){ 156 return make_bignum_string(session->next_crypto->e); 157 } 158 159 void dh_import_pubkey(SSH_SESSION *session,STRING *pubkey_string){ 160 session->next_crypto->server_pubkey=pubkey_string; 161 } 162 163 void dh_import_f(SSH_SESSION *session,STRING *f_string){ 164 session->next_crypto->f=make_string_bn(f_string); 165 #ifdef DEBUG_CRYPTO 166 ssh_print_bignum("f",session->next_crypto->f); 167 #endif 168 } 169 170 void dh_build_k(SSH_SESSION *session){ 171 bignum_CTX ctx=bignum_ctx_new(); 172 session->next_crypto->k=bignum_new(); 173 bignum_mod_exp(session->next_crypto->k,session->next_crypto->f,session->next_crypto->x,p,ctx); 174 #ifdef DEBUG_CRYPTO 175 ssh_print_bignum("shared secret key",session->next_crypto->k); 176 #endif 177 bignum_ctx_free(ctx); 178 } 179 180 static void sha_add(STRING *str,SHACTX *ctx){ 181 sha1_update(ctx,str,string_len(str)+4); 182 } 183 184 void make_sessionid(SSH_SESSION *session){ 185 SHACTX *ctx; 186 STRING *num,*str; 187 int len; 188 ctx=sha1_init(); 189 190 str=string_from_char(session->clientbanner); 191 sha_add(str,ctx); 192 free(str); 193 194 str=string_from_char(session->serverbanner); 195 sha_add(str,ctx); 196 free(str); 197 198 buffer_add_u32(session->in_hashbuf,0); 199 buffer_add_u8(session->in_hashbuf,0); 200 buffer_add_u32(session->out_hashbuf,0); 201 buffer_add_u8(session->out_hashbuf,0); 202 203 len=ntohl(buffer_get_len(session->out_hashbuf)); 204 sha1_update(ctx,&len,4); 205 206 sha1_update(ctx,buffer_get(session->out_hashbuf),buffer_get_len(session->out_hashbuf)); 207 buffer_free(session->out_hashbuf); 208 session->out_hashbuf=NULL; 209 210 len=ntohl(buffer_get_len(session->in_hashbuf)); 211 sha1_update(ctx,&len,4); 212 213 sha1_update(ctx,buffer_get(session->in_hashbuf),buffer_get_len(session->in_hashbuf)); 214 buffer_free(session->in_hashbuf); 215 session->in_hashbuf=NULL; 216 sha1_update(ctx,session->next_crypto->server_pubkey,len=(string_len(session->next_crypto->server_pubkey)+4)); 217 num=make_bignum_string(session->next_crypto->e); 218 sha1_update(ctx,num,len=(string_len(num)+4)); 219 free(num); 220 num=make_bignum_string(session->next_crypto->f); 221 sha1_update(ctx,num,len=(string_len(num)+4)); 222 free(num); 223 num=make_bignum_string(session->next_crypto->k); 224 sha1_update(ctx,num,len=(string_len(num)+4)); 225 free(num); 226 sha1_final(session->next_crypto->session_id,ctx); 227 228 #ifdef DEBUG_CRYPTO 229 printf("Session hash : "); 230 ssh_print_hexa("session id",session->next_crypto->session_id,SHA_DIGEST_LENGTH); 231 #endif 232 } 233 234 void hashbufout_add_cookie(SSH_SESSION *session){ 235 session->out_hashbuf=buffer_new(); 236 buffer_add_u8(session->out_hashbuf,20); 237 buffer_add_data(session->out_hashbuf,session->client_kex.cookie,16); 238 } 239 240 241 void hashbufin_add_cookie(SSH_SESSION *session,unsigned char *cookie){ 242 session->in_hashbuf=buffer_new(); 243 buffer_add_u8(session->in_hashbuf,20); 244 buffer_add_data(session->in_hashbuf,cookie,16); 245 } 246 247 static void generate_one_key(STRING *k,char session_id[SHA_DIGEST_LENGTH],char output[SHA_DIGEST_LENGTH],char letter){ 248 SHACTX *ctx=sha1_init(); 249 sha1_update(ctx,k,string_len(k)+4); 250 sha1_update(ctx,session_id,SHA_DIGEST_LENGTH); 251 sha1_update(ctx,&letter,1); 252 sha1_update(ctx,session_id,SHA_DIGEST_LENGTH); 253 sha1_final(output,ctx); 254 } 255 256 void generate_session_keys(SSH_SESSION *session){ 257 STRING *k_string; 258 SHACTX *ctx; 259 k_string=make_bignum_string(session->next_crypto->k); 260 261 /* IV */ 262 generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptIV,'A'); 263 generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptIV,'B'); 264 265 generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptkey,'C'); 266 267 /* some ciphers need more than 20 bytes of input key */ 268 if(session->next_crypto->out_cipher->keylen > SHA_DIGEST_LENGTH*8){ 269 ctx=sha1_init(); 270 sha1_update(ctx,k_string,string_len(k_string)+4); 271 sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LENGTH); 272 sha1_update(ctx,session->next_crypto->encryptkey,SHA_DIGEST_LENGTH); 273 sha1_final(session->next_crypto->encryptkey+SHA_DIGEST_LEN,ctx); 274 } 275 276 generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptkey,'D'); 277 278 if(session->next_crypto->in_cipher->keylen > SHA_DIGEST_LENGTH*8){ 279 ctx=sha1_init(); 280 sha1_update(ctx,k_string,string_len(k_string)+4); 281 sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LENGTH); 282 sha1_update(ctx,session->next_crypto->decryptkey,SHA_DIGEST_LENGTH); 283 sha1_final(session->next_crypto->decryptkey+SHA_DIGEST_LEN,ctx); 284 } 285 286 generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptMAC,'E'); 287 generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptMAC,'F'); 288 289 #ifdef DEBUG_CRYPTO 290 ssh_print_hexa("client->server IV",session->next_crypto->encryptIV,SHA_DIGEST_LENGTH); 291 ssh_print_hexa("server->client IV",session->next_crypto->decryptIV,SHA_DIGEST_LENGTH); 292 ssh_print_hexa("encryption key",session->next_crypto->encryptkey,16); 293 ssh_print_hexa("decryption key",session->next_crypto->decryptkey,16); 294 ssh_print_hexa("Encryption MAC",session->next_crypto->encryptMAC,SHA_DIGEST_LENGTH); 295 ssh_print_hexa("Decryption MAC",session->next_crypto->decryptMAC,20); 296 #endif 297 free(k_string); 298 } 299 300 int ssh_get_pubkey_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]){ 301 STRING *pubkey=session->current_crypto->server_pubkey; 302 MD5CTX *ctx; 303 int len=string_len(pubkey); 304 305 ctx=md5_init(); 306 md5_update(ctx,pubkey->string,len); 307 md5_final(hash,ctx); 308 return MD5_DIGEST_LEN; 309 } 310 311 int pubkey_get_hash(SSH_SESSION *session, char hash[MD5_DIGEST_LEN]){ 312 return ssh_get_pubkey_hash(session,hash); 313 } 314 315 STRING *ssh_get_pubkey(SSH_SESSION *session){ 316 return string_copy(session->current_crypto->server_pubkey); 317 } 318 319 /* XXX i doubt it is still needed, or may need some fix */ 320 static int match(char *group,char *object){ 321 char *ptr,*saved; 322 char *end; 323 ptr=strdup(group); 324 saved=ptr; 325 while(1){ 326 end=strchr(ptr,','); 327 if(end) 328 *end=0; 329 if(!strcmp(ptr,object)){ 330 free(saved); 331 return 0; 332 } 333 if(end) 334 ptr=end+1; 335 else{ 336 free(saved); 337 return -1; 338 } 339 } 340 /* not reached */ 341 return 1; 342 } 343 344 int sig_verify(PUBLIC_KEY *pubkey, SIGNATURE *signature, char *digest){ 345 int valid=0; 346 char hash[SHA_DIGEST_LENGTH]; 347 sha1(digest,SHA_DIGEST_LENGTH,hash); 348 switch(pubkey->type){ 349 case TYPE_DSS: 350 valid=DSA_do_verify(hash,SHA_DIGEST_LENGTH,signature->dsa_sign, 351 pubkey->dsa_pub); 352 if(valid==1) 353 return 0; 354 if(valid==-1){ 355 ssh_set_error(NULL,SSH_INVALID_DATA,"DSA error : %s",ERR_error_string(ERR_get_error(),NULL)); 356 return -1; 357 } 358 ssh_set_error(NULL,SSH_NO_ERROR,"Invalid DSA signature"); 359 return -1; 360 case TYPE_RSA: 361 case TYPE_RSA1: 362 valid=RSA_verify(NID_sha1,hash,SHA_DIGEST_LENGTH, 363 signature->rsa_sign->string,string_len(signature->rsa_sign),pubkey->rsa_pub); 364 if(valid==1) 365 return 0; 366 if(valid==-1){ 367 ssh_set_error(NULL,SSH_INVALID_DATA,"RSA error : %s",ERR_error_string(ERR_get_error(),NULL)); 368 return -1; 369 } 370 ssh_set_error(NULL,SSH_NO_ERROR,"Invalid RSA signature"); 371 return -1; 372 default: 373 ssh_set_error(NULL,SSH_INVALID_DATA,"Unknown public key type"); 374 return -1; 375 } 376 return -1; 377 } 378 379 380 int signature_verify(SSH_SESSION *session,STRING *signature){ 381 PUBLIC_KEY *pubkey; 382 SIGNATURE *sign; 383 int err; 384 if(session->options->dont_verify_hostkey){ 385 ssh_say(1,"Host key wasn't verified\n"); 386 return 0; 387 } 388 pubkey=publickey_from_string(session->next_crypto->server_pubkey); 389 if(!pubkey) 390 return -1; 391 if(session->options->wanted_methods[KEX_HOSTKEY]){ 392 if(match(session->options->wanted_methods[KEX_HOSTKEY],pubkey->type_c)){ 393 ssh_set_error((session->connected?session:NULL),SSH_FATAL,"Public key from server (%s) doesn't match user preference (%s)", 394 pubkey->type,session->options->wanted_methods[KEX_HOSTKEY]); 395 publickey_free(pubkey); 396 return -1; 397 } 398 } 399 sign=signature_from_string(signature,pubkey,pubkey->type); 400 if(!sign){ 401 ssh_set_error((session->connected?session:NULL),SSH_INVALID_DATA,"Invalid signature blob"); 402 publickey_free(pubkey); 403 return -1; 404 } 405 ssh_say(1,"Going to verify a %s type signature\n",pubkey->type_c); 406 err=sig_verify(pubkey,sign,session->next_crypto->session_id); 407 signature_free(sign); 408 session->next_crypto->server_pubkey_type=pubkey->type_c; 409 publickey_free(pubkey); 410 return err; 411 } |